gambit-0.2010.09.01/0000777000076500007650000000000011441457127010532 500000000000000gambit-0.2010.09.01/acinclude.m40000644000076500007650000003041211352541425012633 00000000000000dnl dnl $Source$ dnl $Date$ dnl $Revision$ dnl dnl DESCRIPTION: dnl Local macro definitions for Gambit configure.in dnl dnl --------------------------------------------------------------------------- dnl Macros for wxWidgets detection. Typically used in configure.in as: dnl dnl AC_ARG_ENABLE(...) dnl AC_ARG_WITH(...) dnl ... dnl AM_OPTIONS_WXCONFIG dnl ... dnl ... dnl AM_PATH_WXCONFIG(2.6.0, wxWin=1) dnl if test "$wxWin" != 1; then dnl AC_MSG_ERROR([ dnl wxWidgets must be installed on your system dnl but wx-config script couldn't be found. dnl dnl Please check that wx-config is in path, the directory dnl where wxWidgets libraries are installed (returned by dnl 'wx-config --libs' command) is in LD_LIBRARY_PATH or dnl equivalent variable and wxWidgets version is 2.3.4 or above. dnl ]) dnl fi dnl CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS" dnl CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY" dnl CFLAGS="$CFLAGS $WX_CFLAGS_ONLY" dnl dnl LIBS="$LIBS $WX_LIBS" dnl --------------------------------------------------------------------------- dnl --------------------------------------------------------------------------- dnl AM_OPTIONS_WXCONFIG dnl dnl adds support for --wx-prefix, --wx-exec-prefix, --with-wxdir and dnl --wx-config command line options dnl --------------------------------------------------------------------------- AC_DEFUN([AM_OPTIONS_WXCONFIG], [ AC_ARG_WITH(wxdir, [ --with-wxdir=PATH Use uninstalled version of wxWidgets in PATH], [ wx_config_name="$withval/wx-config" wx_config_args="--inplace"]) AC_ARG_WITH(wx-config, [ --with-wx-config=CONFIG wx-config script to use (optional)], wx_config_name="$withval" ) AC_ARG_WITH(wx-prefix, [ --with-wx-prefix=PREFIX Prefix where wxWidgets is installed (optional)], wx_config_prefix="$withval", wx_config_prefix="") AC_ARG_WITH(wx-exec-prefix, [ --with-wx-exec-prefix=PREFIX Exec prefix where wxWidgets is installed (optional)], wx_config_exec_prefix="$withval", wx_config_exec_prefix="") ]) dnl Helper macro for checking if wx version is at least $1.$2.$3, set's dnl wx_ver_ok=yes if it is: AC_DEFUN([_WX_PRIVATE_CHECK_VERSION], [ wx_ver_ok="" if test "x$WX_VERSION" != x ; then if test $wx_config_major_version -gt $1; then wx_ver_ok=yes else if test $wx_config_major_version -eq $1; then if test $wx_config_minor_version -gt $2; then wx_ver_ok=yes else if test $wx_config_minor_version -eq $2; then if test $wx_config_micro_version -ge $3; then wx_ver_ok=yes fi fi fi fi fi fi ]) dnl --------------------------------------------------------------------------- dnl AM_PATH_WXCONFIG(VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND dnl [, WX-LIBS [, ADDITIONAL-WX-CONFIG-FLAGS]]]]) dnl dnl Test for wxWidgets, and define WX_C*FLAGS, WX_LIBS and WX_LIBS_STATIC dnl (the latter is for static linking against wxWidgets). Set WX_CONFIG_NAME dnl environment variable to override the default name of the wx-config script dnl to use. Set WX_CONFIG_PATH to specify the full path to wx-config - in this dnl case the macro won't even waste time on tests for its existence. dnl dnl Optional WX-LIBS argument contains comma- or space-separated list of dnl wxWidgets libraries to link against (it may include contrib libraries). If dnl it is not specified then WX_LIBS and WX_LIBS_STATIC will contain flags to dnl link with all of the core wxWidgets libraries. dnl dnl Optional ADDITIONAL-WX-CONFIG-FLAGS argument is appended to wx-config dnl invocation command in present. It can be used to fine-tune lookup of dnl best wxWidgets build available. dnl dnl Example use: dnl AM_PATH_WXCONFIG([2.6.0], [wxWin=1], [wxWin=0], [html,core,net] dnl [--unicode --debug]) dnl --------------------------------------------------------------------------- dnl dnl Get the cflags and libraries from the wx-config script dnl AC_DEFUN([AM_PATH_WXCONFIG], [ dnl do we have wx-config name: it can be wx-config or wxd-config or ... if test x${WX_CONFIG_NAME+set} != xset ; then WX_CONFIG_NAME=wx-config fi if test "x$wx_config_name" != x ; then WX_CONFIG_NAME="$wx_config_name" fi dnl deal with optional prefixes if test x$wx_config_exec_prefix != x ; then wx_config_args="$wx_config_args --exec-prefix=$wx_config_exec_prefix" WX_LOOKUP_PATH="$wx_config_exec_prefix/bin" fi if test x$wx_config_prefix != x ; then wx_config_args="$wx_config_args --prefix=$wx_config_prefix" WX_LOOKUP_PATH="$WX_LOOKUP_PATH:$wx_config_prefix/bin" fi if test "$cross_compiling" = "yes"; then wx_config_args="$wx_config_args --host=$host_alias" fi dnl don't search the PATH if WX_CONFIG_NAME is absolute filename if test -x "$WX_CONFIG_NAME" ; then AC_MSG_CHECKING(for wx-config) WX_CONFIG_PATH="$WX_CONFIG_NAME" AC_MSG_RESULT($WX_CONFIG_PATH) else AC_PATH_PROG(WX_CONFIG_PATH, $WX_CONFIG_NAME, no, "$WX_LOOKUP_PATH:$PATH") fi if test "$WX_CONFIG_PATH" != "no" ; then WX_VERSION="" min_wx_version=ifelse([$1], ,2.2.1,$1) if test -z "$5" ; then AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version]) else AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version ($5)]) fi WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args $5 $4" WX_VERSION=`$WX_CONFIG_WITH_ARGS --version 2>/dev/null` wx_config_major_version=`echo $WX_VERSION | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` wx_config_minor_version=`echo $WX_VERSION | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` wx_config_micro_version=`echo $WX_VERSION | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` wx_requested_major_version=`echo $min_wx_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` wx_requested_minor_version=`echo $min_wx_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` wx_requested_micro_version=`echo $min_wx_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` _WX_PRIVATE_CHECK_VERSION([$wx_requested_major_version], [$wx_requested_minor_version], [$wx_requested_micro_version]) if test -n "$wx_ver_ok"; then AC_MSG_RESULT(yes (version $WX_VERSION)) WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs` dnl is this even still appropriate? --static is a real option now dnl and WX_CONFIG_WITH_ARGS is likely to contain it if that is dnl what the user actually wants, making this redundant at best. dnl For now keep it in case anyone actually used it in the past. AC_MSG_CHECKING([for wxWidgets static library]) WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs 2>/dev/null` if test "x$WX_LIBS_STATIC" = "x"; then AC_MSG_RESULT(no) else AC_MSG_RESULT(yes) fi dnl starting with version 2.2.6 wx-config has --cppflags argument wx_has_cppflags="" if test $wx_config_major_version -gt 2; then wx_has_cppflags=yes else if test $wx_config_major_version -eq 2; then if test $wx_config_minor_version -gt 2; then wx_has_cppflags=yes else if test $wx_config_minor_version -eq 2; then if test $wx_config_micro_version -ge 6; then wx_has_cppflags=yes fi fi fi fi fi dnl starting with version 2.7.0 wx-config has --rescomp option wx_has_rescomp="" if test $wx_config_major_version -gt 2; then wx_has_rescomp=yes else if test $wx_config_major_version -eq 2; then if test $wx_config_minor_version -ge 7; then wx_has_rescomp=yes fi fi fi if test "x$wx_has_rescomp" = x ; then dnl cannot give any useful info for resource compiler WX_RESCOMP= else WX_RESCOMP=`$WX_CONFIG_WITH_ARGS --rescomp` fi if test "x$wx_has_cppflags" = x ; then dnl no choice but to define all flags like CFLAGS WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags` WX_CPPFLAGS=$WX_CFLAGS WX_CXXFLAGS=$WX_CFLAGS WX_CFLAGS_ONLY=$WX_CFLAGS WX_CXXFLAGS_ONLY=$WX_CFLAGS else dnl we have CPPFLAGS included in CFLAGS included in CXXFLAGS WX_CPPFLAGS=`$WX_CONFIG_WITH_ARGS --cppflags` WX_CXXFLAGS=`$WX_CONFIG_WITH_ARGS --cxxflags` WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags` WX_CFLAGS_ONLY=`echo $WX_CFLAGS | sed "s@^$WX_CPPFLAGS *@@"` WX_CXXFLAGS_ONLY=`echo $WX_CXXFLAGS | sed "s@^$WX_CFLAGS *@@"` fi ifelse([$2], , :, [$2]) else if test "x$WX_VERSION" = x; then dnl no wx-config at all AC_MSG_RESULT(no) else AC_MSG_RESULT(no (version $WX_VERSION is not new enough)) fi WX_CFLAGS="" WX_CPPFLAGS="" WX_CXXFLAGS="" WX_LIBS="" WX_LIBS_STATIC="" WX_RESCOMP="" ifelse([$3], , :, [$3]) fi else WX_CFLAGS="" WX_CPPFLAGS="" WX_CXXFLAGS="" WX_LIBS="" WX_LIBS_STATIC="" WX_RESCOMP="" ifelse([$3], , :, [$3]) fi AC_SUBST(WX_CPPFLAGS) AC_SUBST(WX_CFLAGS) AC_SUBST(WX_CXXFLAGS) AC_SUBST(WX_CFLAGS_ONLY) AC_SUBST(WX_CXXFLAGS_ONLY) AC_SUBST(WX_LIBS) AC_SUBST(WX_LIBS_STATIC) AC_SUBST(WX_VERSION) AC_SUBST(WX_RESCOMP) ]) dnl --------------------------------------------------------------------------- dnl Get information on the wxrc program for making C++, Python and xrs dnl resource files. dnl dnl AC_ARG_ENABLE(...) dnl AC_ARG_WITH(...) dnl ... dnl AM_OPTIONS_WXCONFIG dnl ... dnl AM_PATH_WXCONFIG(2.6.0, wxWin=1) dnl if test "$wxWin" != 1; then dnl AC_MSG_ERROR([ dnl wxWidgets must be installed on your system dnl but wx-config script couldn't be found. dnl dnl Please check that wx-config is in path, the directory dnl where wxWidgets libraries are installed (returned by dnl 'wx-config --libs' command) is in LD_LIBRARY_PATH or dnl equivalent variable and wxWidgets version is 2.6.0 or above. dnl ]) dnl fi dnl dnl AM_PATH_WXRC([HAVE_WXRC=1], [HAVE_WXRC=0]) dnl if test "x$HAVE_WXRC" != x1; then dnl AC_MSG_ERROR([ dnl The wxrc program was not installed or not found. dnl dnl Please check the wxWidgets installation. dnl ]) dnl fi dnl dnl CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS" dnl CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY" dnl CFLAGS="$CFLAGS $WX_CFLAGS_ONLY" dnl dnl LDFLAGS="$LDFLAGS $WX_LIBS" dnl --------------------------------------------------------------------------- dnl --------------------------------------------------------------------------- dnl AM_PATH_WXRC([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) dnl dnl Test for wxWidgets' wxrc program for creating either C++, Python or XRS dnl resources. The variable WXRC will be set and substituted in the configure dnl script and Makefiles. dnl dnl Example use: dnl AM_PATH_WXRC([wxrc=1], [wxrc=0]) dnl --------------------------------------------------------------------------- dnl dnl wxrc program from the wx-config script dnl AC_DEFUN([AM_PATH_WXRC], [ AC_ARG_VAR([WXRC], [Path to wxWidget's wxrc resource compiler]) if test "x$WX_CONFIG_NAME" = x; then AC_MSG_ERROR([The wxrc tests must run after wxWidgets test.]) else AC_MSG_CHECKING([for wxrc]) if test "x$WXRC" = x ; then dnl wx-config --utility is a new addition to wxWidgets: _WX_PRIVATE_CHECK_VERSION(2,5,3) if test -n "$wx_ver_ok"; then WXRC=`$WX_CONFIG_WITH_ARGS --utility=wxrc` fi fi if test "x$WXRC" = x ; then AC_MSG_RESULT([not found]) ifelse([$2], , :, [$2]) else AC_MSG_RESULT([$WXRC]) ifelse([$1], , :, [$1]) fi AC_SUBST(WXRC) fi ]) gambit-0.2010.09.01/aclocal.m40000644000076500007650000101523711441453547012321 00000000000000# generated automatically by aclocal 1.9.6 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # serial 52 AC_PROG_LIBTOOL # AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) # ----------------------------------------------------------- # If this macro is not defined by Autoconf, define it here. m4_ifdef([AC_PROVIDE_IFELSE], [], [m4_define([AC_PROVIDE_IFELSE], [m4_ifdef([AC_PROVIDE_$1], [$2], [$3])])]) # AC_PROG_LIBTOOL # --------------- AC_DEFUN([AC_PROG_LIBTOOL], [AC_REQUIRE([_AC_PROG_LIBTOOL])dnl dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. AC_PROVIDE_IFELSE([AC_PROG_CXX], [AC_LIBTOOL_CXX], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX ])]) dnl And a similar setup for Fortran 77 support AC_PROVIDE_IFELSE([AC_PROG_F77], [AC_LIBTOOL_F77], [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 ])]) dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [AC_LIBTOOL_GCJ], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [AC_LIBTOOL_GCJ], [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], [AC_LIBTOOL_GCJ], [ifdef([AC_PROG_GCJ], [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) ifdef([A][M_PROG_GCJ], [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) ifdef([LT_AC_PROG_GCJ], [define([LT_AC_PROG_GCJ], defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) ])])# AC_PROG_LIBTOOL # _AC_PROG_LIBTOOL # ---------------- AC_DEFUN([_AC_PROG_LIBTOOL], [AC_REQUIRE([AC_LIBTOOL_SETUP])dnl AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl # Prevent multiple expansion define([AC_PROG_LIBTOOL], []) ])# _AC_PROG_LIBTOOL # AC_LIBTOOL_SETUP # ---------------- AC_DEFUN([AC_LIBTOOL_SETUP], [AC_PREREQ(2.50)dnl AC_REQUIRE([AC_ENABLE_SHARED])dnl AC_REQUIRE([AC_ENABLE_STATIC])dnl AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_LD])dnl AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl AC_REQUIRE([AC_PROG_NM])dnl AC_REQUIRE([AC_PROG_LN_S])dnl AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! AC_REQUIRE([AC_OBJEXT])dnl AC_REQUIRE([AC_EXEEXT])dnl dnl AC_LIBTOOL_SYS_MAX_CMD_LEN AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE AC_LIBTOOL_OBJDIR AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl _LT_AC_PROG_ECHO_BACKSLASH case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' [sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] # Same as above, but do not quote variable references. [double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" AC_CHECK_TOOL(AR, ar, false) AC_CHECK_TOOL(RANLIB, ranlib, :) AC_CHECK_TOOL(STRIP, strip, :) old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$SED" && SED=sed test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then AC_PATH_MAGIC fi ;; esac _LT_REQUIRED_DARWIN_CHECKS AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], enable_win32_dll=yes, enable_win32_dll=no) AC_ARG_ENABLE([libtool-lock], [AC_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes AC_ARG_WITH([pic], [AC_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) test -z "$pic_mode" && pic_mode=default # Use C for the default configuration in the libtool script tagname= AC_LIBTOOL_LANG_C_CONFIG _LT_AC_TAGCONFIG ])# AC_LIBTOOL_SETUP # _LT_AC_SYS_COMPILER # ------------------- AC_DEFUN([_LT_AC_SYS_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_AC_SYS_COMPILER # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. AC_DEFUN([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` ]) # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. AC_DEFUN([_LT_COMPILER_BOILERPLATE], [AC_REQUIRE([LT_AC_PROG_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. AC_DEFUN([_LT_LINKER_BOILERPLATE], [AC_REQUIRE([LT_AC_PROG_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # -------------------------- # Check for some things on darwin AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. echo "int foo(void){return 1;}" > conftest.c $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib ${wl}-single_module conftest.c if test -f libconftest.dylib; then lt_cv_apple_cc_single_mod=yes rm -rf libconftest.dylib* fi rm conftest.c fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) case $host_os in rhapsody* | darwin1.[[0123]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms="~$NMEDIT -s \$output_objdir/\${libname}-symbols.expsym \${lib}" fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil="~$DSYMUTIL \$lib || :" else _lt_dsymutil= fi ;; esac ]) # _LT_AC_SYS_LIBPATH_AIX # ---------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], [AC_REQUIRE([LT_AC_PROG_SED])dnl AC_LINK_IFELSE(AC_LANG_PROGRAM,[ lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ])# _LT_AC_SYS_LIBPATH_AIX # _LT_AC_SHELL_INIT(ARG) # ---------------------- AC_DEFUN([_LT_AC_SHELL_INIT], [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], [AC_DIVERT_PUSH(NOTICE)]) $1 AC_DIVERT_POP ])# _LT_AC_SHELL_INIT # _LT_AC_PROG_ECHO_BACKSLASH # -------------------------- # Add some code to the start of the generated configure script which # will find an echo command which doesn't interpret backslashes. AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], [_LT_AC_SHELL_INIT([ # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` ;; esac echo=${ECHO-echo} if test "X[$]1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X[$]1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} fi if test "X[$]1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null 2>&1 && unset CDPATH if test -z "$ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if (echo_test_string=`eval $cmd`) 2>/dev/null && echo_test_string=`eval $cmd` && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL [$]0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL [$]0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "[$]0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" fi AC_SUBST(ECHO) ])])# _LT_AC_PROG_ECHO_BACKSLASH # _LT_AC_LOCK # ----------- AC_DEFUN([_LT_AC_LOCK], [AC_ARG_ENABLE([libtool-lock], [AC_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], [*-*-cygwin* | *-*-mingw* | *-*-pw32*) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; ]) esac need_locks="$enable_libtool_lock" ])# _LT_AC_LOCK # AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [AC_REQUIRE([LT_AC_PROG_SED]) AC_CACHE_CHECK([$1], [$2], [$2=no ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $rm conftest* ]) if test x"[$]$2" = xyes; then ifelse([$5], , :, [$5]) else ifelse([$6], , :, [$6]) fi ])# AC_LIBTOOL_COMPILER_OPTION # AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ------------------------------------------------------------ # Check whether the given compiler option works AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [AC_REQUIRE([LT_AC_PROG_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $rm -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then ifelse([$4], , :, [$4]) else ifelse([$5], , :, [$5]) fi ])# AC_LIBTOOL_LINKER_OPTION # AC_LIBTOOL_SYS_MAX_CMD_LEN # -------------------------- AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [# find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ = "XX$teststring") >/dev/null 2>&1 && new_result=`expr "X$teststring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done teststring= # Add a significant safety factor because C++ compilers can tack on massive # amounts of additional arguments before passing them to the linker. # It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi ])# AC_LIBTOOL_SYS_MAX_CMD_LEN # _LT_AC_CHECK_DLFCN # ------------------ AC_DEFUN([_LT_AC_CHECK_DLFCN], [AC_CHECK_HEADERS(dlfcn.h)dnl ])# _LT_AC_CHECK_DLFCN # _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # --------------------------------------------------------------------- AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], [AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); exit (status); }] EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_AC_TRY_DLOPEN_SELF # AC_LIBTOOL_DLOPEN_SELF # ---------------------- AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi ])# AC_LIBTOOL_DLOPEN_SELF # AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) # --------------------------------- # Check to see if options -c and -o are simultaneously supported by compiler AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], [AC_REQUIRE([LT_AC_PROG_SED])dnl AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* ]) ])# AC_LIBTOOL_PROG_CC_C_O # AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) # ----------------------------------------- # Check to see if we can do hard links to lock some files if needed AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_REQUIRE([_LT_AC_LOCK])dnl hard_links="nottested" if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi ])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS # AC_LIBTOOL_OBJDIR # ----------------- AC_DEFUN([AC_LIBTOOL_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir ])# AC_LIBTOOL_OBJDIR # AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) # ---------------------------------------------- # Check hardcoding attributes. AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_AC_TAGVAR(hardcode_action, $1)= if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existant directories. if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_AC_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_AC_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_AC_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi ])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH # AC_LIBTOOL_SYS_LIB_STRIP # ------------------------ AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], [striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi ])# AC_LIBTOOL_SYS_LIB_STRIP # AC_LIBTOOL_SYS_DYNAMIC_LINKER # ----------------------------- # PORTME Fill in your ld.so characteristics AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_REQUIRE([LT_AC_PROG_SED])dnl AC_MSG_CHECKING([dynamic linker characteristics]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" m4_if($1,[],[ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`echo $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[123]]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[[3-9]]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no AC_CACHE_VAL([lt_cv_sys_lib_search_path_spec], [lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec"]) sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" AC_CACHE_VAL([lt_cv_sys_lib_dlsearch_path_spec], [lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec"]) sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi ])# AC_LIBTOOL_SYS_DYNAMIC_LINKER # _LT_AC_TAGCONFIG # ---------------- AC_DEFUN([_LT_AC_TAGCONFIG], [AC_REQUIRE([LT_AC_PROG_SED])dnl AC_ARG_WITH([tags], [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], [include additional configurations @<:@automatic@:>@])], [tagnames="$withval"]) if test -f "$ltmain" && test -n "$tagnames"; then if test ! -f "${ofile}"; then AC_MSG_WARN([output file `$ofile' does not exist]) fi if test -z "$LTCC"; then eval "`$SHELL ${ofile} --config | grep '^LTCC='`" if test -z "$LTCC"; then AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) else AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) fi fi if test -z "$LTCFLAGS"; then eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for tagname in $tagnames; do IFS="$lt_save_ifs" # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in "") ;; *) AC_MSG_ERROR([invalid tag name: $tagname]) ;; esac if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then AC_MSG_ERROR([tag name \"$tagname\" already exists]) fi # Update the list of available tags. if test -n "$tagname"; then echo appending configuration tag \"$tagname\" to $ofile case $tagname in CXX) if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_LIBTOOL_LANG_CXX_CONFIG else tagname="" fi ;; F77) if test -n "$F77" && test "X$F77" != "Xno"; then AC_LIBTOOL_LANG_F77_CONFIG else tagname="" fi ;; GCJ) if test -n "$GCJ" && test "X$GCJ" != "Xno"; then AC_LIBTOOL_LANG_GCJ_CONFIG else tagname="" fi ;; RC) AC_LIBTOOL_LANG_RC_CONFIG ;; *) AC_MSG_ERROR([Unsupported tag name: $tagname]) ;; esac # Append the new tag name to the list of available tags. if test -n "$tagname" ; then available_tags="$available_tags $tagname" fi fi done IFS="$lt_save_ifs" # Now substitute the updated list of available tags. if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then mv "${ofile}T" "$ofile" chmod +x "$ofile" else rm -f "${ofile}T" AC_MSG_ERROR([unable to update list of available tagged configurations.]) fi fi ])# _LT_AC_TAGCONFIG # AC_LIBTOOL_DLOPEN # ----------------- # enable checks for dlopen support AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) ])# AC_LIBTOOL_DLOPEN # AC_LIBTOOL_WIN32_DLL # -------------------- # declare package support for building win32 DLLs AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) ])# AC_LIBTOOL_WIN32_DLL # AC_ENABLE_SHARED([DEFAULT]) # --------------------------- # implement the --enable-shared flag # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. AC_DEFUN([AC_ENABLE_SHARED], [define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([shared], [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]AC_ENABLE_SHARED_DEFAULT) ])# AC_ENABLE_SHARED # AC_DISABLE_SHARED # ----------------- # set the default shared flag to --disable-shared AC_DEFUN([AC_DISABLE_SHARED], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_SHARED(no) ])# AC_DISABLE_SHARED # AC_ENABLE_STATIC([DEFAULT]) # --------------------------- # implement the --enable-static flag # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. AC_DEFUN([AC_ENABLE_STATIC], [define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([static], [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]AC_ENABLE_STATIC_DEFAULT) ])# AC_ENABLE_STATIC # AC_DISABLE_STATIC # ----------------- # set the default static flag to --disable-static AC_DEFUN([AC_DISABLE_STATIC], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_STATIC(no) ])# AC_DISABLE_STATIC # AC_ENABLE_FAST_INSTALL([DEFAULT]) # --------------------------------- # implement the --enable-fast-install flag # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. AC_DEFUN([AC_ENABLE_FAST_INSTALL], [define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE([fast-install], [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) ])# AC_ENABLE_FAST_INSTALL # AC_DISABLE_FAST_INSTALL # ----------------------- # set the default to --disable-fast-install AC_DEFUN([AC_DISABLE_FAST_INSTALL], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_FAST_INSTALL(no) ])# AC_DISABLE_FAST_INSTALL # AC_LIBTOOL_PICMODE([MODE]) # -------------------------- # implement the --with-pic flag # MODE is either `yes' or `no'. If omitted, it defaults to `both'. AC_DEFUN([AC_LIBTOOL_PICMODE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl pic_mode=ifelse($#,1,$1,default) ])# AC_LIBTOOL_PICMODE # AC_PROG_EGREP # ------------- # This is predefined starting with Autoconf 2.54, so this conditional # definition can be removed once we require Autoconf 2.54 or later. m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], [AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi]) EGREP=$ac_cv_prog_egrep AC_SUBST([EGREP]) ])]) # AC_PATH_TOOL_PREFIX # ------------------- # find a file program which can recognize shared library AC_DEFUN([AC_PATH_TOOL_PREFIX], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="ifelse([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi ])# AC_PATH_TOOL_PREFIX # AC_PATH_MAGIC # ------------- # find a file program which can recognize a shared library AC_DEFUN([AC_PATH_MAGIC], [AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# AC_PATH_MAGIC # AC_PROG_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([AC_PROG_LD], [AC_ARG_WITH([gnu-ld], [AC_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no]) AC_REQUIRE([LT_AC_PROG_SED])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; nto-qnx*) lt_cv_deplibs_check_method=unknown ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown ])# AC_DEPLIBS_CHECK_METHOD # AC_PROG_NM # ---------- # find the pathname to a BSD-compatible name lister AC_DEFUN([AC_PROG_NM], [AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi]) NM="$lt_cv_path_NM" ])# AC_PROG_NM # AC_CHECK_LIBM # ------------- # check for math library AC_DEFUN([AC_CHECK_LIBM], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac ])# AC_CHECK_LIBM # AC_LIBLTDL_CONVENIENCE([DIRECTORY]) # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl convenience library and # LTDLINCL to the include flags for the libltdl header and adds # --enable-ltdl-convenience to the configure arguments. Note that # AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, # it is assumed to be `libltdl'. LIBLTDL will be prefixed with # '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' # (note the single quotes!). If your package is not flat and you're not # using automake, define top_builddir and top_srcdir appropriately in # the Makefiles. AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl case $enable_ltdl_convenience in no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; "") enable_ltdl_convenience=yes ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; esac LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ])# AC_LIBLTDL_CONVENIENCE # AC_LIBLTDL_INSTALLABLE([DIRECTORY]) # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl installable library and # LTDLINCL to the include flags for the libltdl header and adds # --enable-ltdl-install to the configure arguments. Note that # AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, # and an installed libltdl is not found, it is assumed to be `libltdl'. # LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with # '${top_srcdir}/' (note the single quotes!). If your package is not # flat and you're not using automake, define top_builddir and top_srcdir # appropriately in the Makefiles. # In the future, this macro may have to be called after AC_PROG_LIBTOOL. AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_CHECK_LIB(ltdl, lt_dlinit, [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], [if test x"$enable_ltdl_install" = xno; then AC_MSG_WARN([libltdl not installed, but installation disabled]) else enable_ltdl_install=yes fi ]) if test x"$enable_ltdl_install" = x"yes"; then ac_configure_args="$ac_configure_args --enable-ltdl-install" LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) else ac_configure_args="$ac_configure_args --enable-ltdl-install=no" LIBLTDL="-lltdl" LTDLINCL= fi # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ])# AC_LIBLTDL_INSTALLABLE # AC_LIBTOOL_CXX # -------------- # enable support for C++ libraries AC_DEFUN([AC_LIBTOOL_CXX], [AC_REQUIRE([_LT_AC_LANG_CXX]) ])# AC_LIBTOOL_CXX # _LT_AC_LANG_CXX # --------------- AC_DEFUN([_LT_AC_LANG_CXX], [AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([_LT_AC_PROG_CXXCPP]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) ])# _LT_AC_LANG_CXX # _LT_AC_PROG_CXXCPP # ------------------ AC_DEFUN([_LT_AC_PROG_CXXCPP], [ AC_REQUIRE([AC_PROG_CXX]) if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP fi ])# _LT_AC_PROG_CXXCPP # AC_LIBTOOL_F77 # -------------- # enable support for Fortran 77 libraries AC_DEFUN([AC_LIBTOOL_F77], [AC_REQUIRE([_LT_AC_LANG_F77]) ])# AC_LIBTOOL_F77 # _LT_AC_LANG_F77 # --------------- AC_DEFUN([_LT_AC_LANG_F77], [AC_REQUIRE([AC_PROG_F77]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) ])# _LT_AC_LANG_F77 # AC_LIBTOOL_GCJ # -------------- # enable support for GCJ libraries AC_DEFUN([AC_LIBTOOL_GCJ], [AC_REQUIRE([_LT_AC_LANG_GCJ]) ])# AC_LIBTOOL_GCJ # _LT_AC_LANG_GCJ # --------------- AC_DEFUN([_LT_AC_LANG_GCJ], [AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) ])# _LT_AC_LANG_GCJ # AC_LIBTOOL_RC # ------------- # enable support for Windows resource files AC_DEFUN([AC_LIBTOOL_RC], [AC_REQUIRE([LT_AC_PROG_RC]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) ])# AC_LIBTOOL_RC # AC_LIBTOOL_LANG_C_CONFIG # ------------------------ # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) AC_DEFUN([_LT_AC_LANG_C_CONFIG], [lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_SYS_LIB_STRIP AC_LIBTOOL_DLOPEN_SELF # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_C_CONFIG # AC_LIBTOOL_LANG_CXX_CONFIG # -------------------------- # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], [AC_LANG_PUSH(C++) AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([_LT_AC_PROG_CXXCPP]) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_AC_TAGVAR(no_undefined_flag, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Dependencies to place before and after the object being linked: _LT_AC_TAGVAR(predep_objects, $1)= _LT_AC_TAGVAR(postdep_objects, $1)= _LT_AC_TAGVAR(predeps, $1)= _LT_AC_TAGVAR(postdeps, $1)= _LT_AC_TAGVAR(compiler_lib_search_path, $1)= _LT_AC_TAGVAR(compiler_lib_search_dirs, $1)= # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration AC_PROG_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ grep 'no-whole-archive' > /dev/null; then _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_AC_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_AC_TAGVAR(archive_cmds, $1)='' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_AC_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; darwin* | rhapsody*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes _LT_AC_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" if test "$GXX" = yes ; then output_verbose_link_cmd='echo' _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_AC_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_AC_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi else case $cc_basename in xlc*) output_verbose_link_cmd='echo' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac fi ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[[12]]*) # C++ shared libraries reported to be fairly broken before switch to ELF _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_AC_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; hpux9*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi fi _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; linux* | k*bsd*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc*) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; openbsd2*) # C++ shared libraries are fairly broken _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd='echo' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; osf3*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; cxx*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; cxx*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ $rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | grep -v '^2\.7' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. # So that behaviour is only enabled if SCOABSPATH is set to a # non-empty value in the environment. Most likely only useful for # creating official distributions of packages. # This is a hack until libtool officially supports absolute path # names for shared libraries. _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_AC_TAGVAR(GCC, $1)="$GXX" _LT_AC_TAGVAR(LD, $1)="$LD" AC_LIBTOOL_POSTDEP_PREDEP($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ldcxx=$with_gnu_ld with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld ])# AC_LIBTOOL_LANG_CXX_CONFIG # AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) # ------------------------------------ # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP], [AC_REQUIRE([LT_AC_PROG_SED])dnl dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_AC_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac ])# AC_LIBTOOL_POSTDEP_PREDEP # AC_LIBTOOL_LANG_F77_CONFIG # -------------------------- # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)]) AC_DEFUN([_LT_AC_LANG_F77_CONFIG], [AC_REQUIRE([AC_PROG_F77]) AC_LANG_PUSH(Fortran 77) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_AC_TAGVAR(no_undefined_flag, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${F77-"f77"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_AC_TAGVAR(GCC, $1)="$G77" _LT_AC_TAGVAR(LD, $1)="$LD" AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_F77_CONFIG # AC_LIBTOOL_LANG_GCJ_CONFIG # -------------------------- # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)]) AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], [AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${GCJ-"gcj"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_CONFIG($1) AC_LANG_RESTORE CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_GCJ_CONFIG # AC_LIBTOOL_LANG_RC_CONFIG # ------------------------- # Ensure that the configuration vars for the Windows resource compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)]) AC_DEFUN([_LT_AC_LANG_RC_CONFIG], [AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${RC-"windres"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes AC_LIBTOOL_CONFIG($1) AC_LANG_RESTORE CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_RC_CONFIG # AC_LIBTOOL_CONFIG([TAGNAME]) # ---------------------------- # If TAGNAME is not passed, then create an initial libtool script # with a default configuration from the untagged config vars. Otherwise # add code to config.status for appending the configuration named by # TAGNAME from the matching tagged config vars. AC_DEFUN([AC_LIBTOOL_CONFIG], [# The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ _LT_AC_TAGVAR(compiler, $1) \ _LT_AC_TAGVAR(CC, $1) \ _LT_AC_TAGVAR(LD, $1) \ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \ _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \ _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \ _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \ _LT_AC_TAGVAR(old_archive_cmds, $1) \ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ _LT_AC_TAGVAR(predep_objects, $1) \ _LT_AC_TAGVAR(postdep_objects, $1) \ _LT_AC_TAGVAR(predeps, $1) \ _LT_AC_TAGVAR(postdeps, $1) \ _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ _LT_AC_TAGVAR(compiler_lib_search_dirs, $1) \ _LT_AC_TAGVAR(archive_cmds, $1) \ _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ _LT_AC_TAGVAR(postinstall_cmds, $1) \ _LT_AC_TAGVAR(postuninstall_cmds, $1) \ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ _LT_AC_TAGVAR(allow_undefined_flag, $1) \ _LT_AC_TAGVAR(no_undefined_flag, $1) \ _LT_AC_TAGVAR(export_symbols_cmds, $1) \ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \ _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \ _LT_AC_TAGVAR(hardcode_automatic, $1) \ _LT_AC_TAGVAR(module_cmds, $1) \ _LT_AC_TAGVAR(module_expsym_cmds, $1) \ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ _LT_AC_TAGVAR(fix_srcfile_path, $1) \ _LT_AC_TAGVAR(exclude_expsyms, $1) \ _LT_AC_TAGVAR(include_expsyms, $1); do case $var in _LT_AC_TAGVAR(old_archive_cmds, $1) | \ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ _LT_AC_TAGVAR(archive_cmds, $1) | \ _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ _LT_AC_TAGVAR(module_cmds, $1) | \ _LT_AC_TAGVAR(module_expsym_cmds, $1) | \ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \ _LT_AC_TAGVAR(export_symbols_cmds, $1) | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\[$]0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'` ;; esac ifelse([$1], [], [cfgfile="${ofile}T" trap "$rm \"$cfgfile\"; exit 1" 1 2 15 $rm -f "$cfgfile" AC_MSG_NOTICE([creating $ofile])], [cfgfile="$ofile"]) cat <<__EOF__ >> "$cfgfile" ifelse([$1], [], [#! $SHELL # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: # Originally by Gordon Matzigkeit , 1996 # # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e 1s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # The names of the tagged configurations supported by this script. available_tags= # ### BEGIN LIBTOOL CONFIG], [# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) # Is the compiler the GNU C compiler? with_gcc=$_LT_AC_TAGVAR(GCC, $1) # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_[]_LT_AC_TAGVAR(LD, $1) # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) # Commands used to build and install a shared archive. archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) # The directories searched by this compiler when creating a shared # library compiler_lib_search_dirs=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_dirs, $1) # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) # Flag that forces no undefined symbols. no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) # The commands to list exported symbols. export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) # Symbols that must always be exported. include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) ifelse([$1],[], [# ### END LIBTOOL CONFIG], [# ### END LIBTOOL TAG CONFIG: $tagname]) __EOF__ ifelse([$1],[], [ case $host_os in aix3*) cat <<\EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || \ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ]) else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ])# AC_LIBTOOL_CONFIG # AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------------------- AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi ])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # --------------------------------- AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([LT_AC_PROG_SED]) AC_REQUIRE([AC_PROG_NM]) AC_REQUIRE([AC_OBJEXT]) # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32*) symcode='[[ABCDGISTW]]' ;; hpux*) # Its linker distinguishes data from code symbols if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; linux* | k*bsd*-gnu) if test "$host_cpu" = ia64; then symcode='[[ABCDGIRSTW]]' lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if grep ' nm_test_var$' "$nlist" >/dev/null; then if grep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[[]] = { EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi ]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) # --------------------------------------- AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], [_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)= AC_MSG_CHECKING([for $compiler option to produce PIC]) ifelse([$1],[CXX],[ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; esac ;; dgux*) case $cc_basename in ec++*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; icpc* | ecpc*) # Intel C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler. _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; vxworks*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; esac ;; mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; newsos6) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; linux* | k*bsd*-gnu) case $cc_basename in icc* | ecc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='' ;; esac ;; esac ;; osf3* | osf4* | osf5*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], _LT_AC_TAGVAR(lt_cv_prog_compiler_pic_works, $1), [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" ;; esac # # Check to make sure the static flag actually works. # wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_AC_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) ]) # AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) # ------------------------------------ # See if the linker supports building shared libraries. AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_REQUIRE([LT_AC_PROG_SED])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) ifelse([$1],[CXX],[ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' else _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw*) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' ;; *) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac _LT_AC_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] ],[ runpath_var= _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_AC_TAGVAR(archive_cmds, $1)= _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_AC_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_AC_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. _LT_CC_BASENAME([$compiler]) case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_AC_TAGVAR(ld_shlibs, $1)=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; interix[[3-9]]*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; *) tmp_sharedflag='-shared' ;; esac _LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=yes _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' else _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_AC_TAGVAR(archive_cmds, $1)='' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_AC_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # see comment about different semantics on the GNU ld section _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; bsdi[[45]]*) _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; darwin* | rhapsody*) _LT_AC_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_AC_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_AC_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else case $cc_basename in xlc*) output_verbose_link_cmd='echo' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac fi ;; dgux*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' if test "$GCC" = yes; then wlarc='${wl}' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_AC_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_AC_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac fi ]) AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_AC_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) $rm conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) _LT_AC_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no else _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) ;; esac fi ;; esac ])# AC_LIBTOOL_PROG_LD_SHLIBS # _LT_AC_FILE_LTDLL_C # ------------------- # Be careful that the start marker always follows a newline. AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include # #undef WIN32_LEAN_AND_MEAN # #include # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ ])# _LT_AC_FILE_LTDLL_C # _LT_AC_TAGVAR(VARNAME, [TAGNAME]) # --------------------------------- AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) # old names AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) # This is just to silence aclocal about the macro not being used ifelse([AC_DISABLE_FAST_INSTALL]) AC_DEFUN([LT_AC_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj, no) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS) ]) AC_DEFUN([LT_AC_PROG_RC], [AC_CHECK_TOOL(RC, windres, no) ]) # Cheap backport of AS_EXECUTABLE_P and required macros # from Autoconf 2.59; we should not use $as_executable_p directly. # _AS_TEST_PREPARE # ---------------- m4_ifndef([_AS_TEST_PREPARE], [m4_defun([_AS_TEST_PREPARE], [if test -x / >/dev/null 2>&1; then as_executable_p='test -x' else as_executable_p='test -f' fi ])])# _AS_TEST_PREPARE # AS_EXECUTABLE_P # --------------- # Check whether a file is executable. m4_ifndef([AS_EXECUTABLE_P], [m4_defun([AS_EXECUTABLE_P], [AS_REQUIRE([_AS_TEST_PREPARE])dnl $as_executable_p $1[]dnl ])])# AS_EXECUTABLE_P # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # # LT_AC_PROG_SED # -------------- # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. AC_DEFUN([LT_AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ]) # Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.9.6])]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE]) AC_SUBST([$1_FALSE]) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH]) ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 3 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 12 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.58])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $1 | $1:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"$am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. # # Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories # created by `make install' are always world readable, even if the # installer happens to have an overly restrictive umask (e.g. 077). # This was a mistake. There are at least two reasons why we must not # use `-m 0755': # - it causes special bits like SGID to be ignored, # - it may be too restrictive (some setups expect 775 directories). # # Do not use -m 0755 and let people choose whatever they expect by # setting umask. # # We cannot accept any implementation of `mkdir' that recognizes `-p'. # Some implementations (such as Solaris 8's) are not thread-safe: if a # parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' # concurrently, both version can detect that a/ is missing, but only # one can create it and the other will error out. Consequently we # restrict ourselves to GNU make (using the --version option ensures # this.) AC_DEFUN([AM_PROG_MKDIR_P], [if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi AC_SUBST([mkdir_p])]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([acinclude.m4]) gambit-0.2010.09.01/AUTHORS0000644000076500007650000000567211350032206011512 00000000000000-*-text-*- This is Gambit, an Open Source software project dedicated to developing and providing tools and methods for computation in game theory. Contacting Gambit: ------------------ The Gambit developers can be reached at gambit (at) econmail (dot) tamu (dot) edu, or individually at email addresses listed below. The surface mail contact address for Gambit is The Gambit Project c/o Theodore Turocy Department of Economics Texas A&M University 4228 TAMU College Station TX 77843 Main Developers: ---------------- Richard D. McKelvey Andrew M. McLennan -- mclennan (at) icarus (dot) socsci (dot) umn (dot) edu Theodore L. Turocy -- arbiter (at) econ (dot) tamu (dot) edu Other sources of code in this distribution: ------------------------------------------- Gambit incorporates portions of other software packages in this distribution. These are acknowledged individually below. Pelican: -------- The code in sources/pelican is the Pelican system, copyright (C) 1995 by Birk Huber, modified only to work within the Gambit build system. Integer/Rational classes: ------------------------- The files integer.(cc,h), rational.(cc,h), and gnulib.(cc,h) in sources/base are from an old GNU g++ library, with copyright statement: Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) These files have been modified only to work as appropriate with other Gambit classes. Function minimization code: --------------------------- The files gfuncmin.(cc,h) in sources/numerical contain source code derived from the GNU Scientific Library, version 1.2. The original files have the copyright statement: Copyright (C) 1996, 1997, 1998, 1999, 2000 Fabrice Rossi These files have been modified only to port them from C to C++ and to use the gFunction class. Clique determination: --------------------- The gambit-nfg-enummixed program incorporates the code of Bernhard von Stengel to determine the connectedness of components of Nash equilibria. (BvS has also contributed numerous other improvements and fixes to other areas of Gambit.) Gametracer: ----------- The global Newton and iterated polymatrix implementations are based on those in Gametracer 0.2, copyright (C) 2002 by Ben Blum and Christian Shelton, distributed under the GPL. See the directory sources/tools/gt in the distribution. wxSheet classes: ---------------- The graphical interface makes significant use of the wxSheet classes for wxWidgets, which are Copyright (C) 2004-5 by John Labenski, and distributed under the wxWidgets license. The version included here is the version dated 20 July 2005; see http://wxcode.sourceforge.net for details on these classes. TinyXML parser: --------------- The graphical interface reads and writes files in XML format. The parsing is done using the TinyXml package from http://www.grinninglizard.com/tinyxml, and is distributed under the zlib license. These are the files named tiny* in the sources/gui directory of the distribution. gambit-0.2010.09.01/ChangeLog0000644000076500007650000000000011350032206012170 00000000000000gambit-0.2010.09.01/compile0000755000076500007650000000717311441456101012023 00000000000000#! /bin/sh # Wrapper for compilers which do not understand `-c -o'. scriptversion=2009-04-28.21; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software # Foundation, Inc. # Written by Tom Tromey . # # 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. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand `-c -o'. Remove `-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file `INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; esac ofile= cfile= eat= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as `compile cc -o foo foo.c'. # So we strip `-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no `-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # `.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use `[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gambit-0.2010.09.01/config.guess0000755000076500007650000012753411352250350012770 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. timestamp='2008-01-23' # This file 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., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[456]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) case ${UNAME_MACHINE} in pc98) echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:[3456]*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; EM64T | authenticamd) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-gnu else echo ${UNAME_MACHINE}-unknown-linux-gnueabi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) echo frv-unknown-linux-gnu exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo or32-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^LIBC/{ s: ::g p }'`" test x"${LIBC}" != x && { echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit } test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: gambit-0.2010.09.01/config.sub0000755000076500007650000010115311352250350012420 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. timestamp='2008-01-16' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file 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., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | mt \ | msp430 \ | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | score \ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tile*) basic_machine=tile-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: gambit-0.2010.09.01/configure0000755000076500007650000253550211441453557012374 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.63 for gambit 0.2010.09.01. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : (as_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell bug-autoconf@gnu.org about your system, echo including any error possibly output before this message. echo This can help us improve future autoconf versions. echo Configuration will now proceed without shell functions. } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac echo=${ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null 2>&1 && unset CDPATH if test -z "$ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if (echo_test_string=`eval $cmd`) 2>/dev/null && echo_test_string=`eval $cmd` && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi tagnames=${tagnames+${tagnames},}CXX tagnames=${tagnames+${tagnames},}F77 exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='gambit' PACKAGE_TARNAME='gambit' PACKAGE_VERSION='0.2010.09.01' PACKAGE_STRING='gambit 0.2010.09.01' PACKAGE_BUGREPORT='' ac_unique_file="src/libgambit/libgambit.h" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS REZFLAGS ENUMPOLY_PROGS GUI_PROGS RC_OBJECT_PATH RC_OBJECT WX_RESCOMP WX_VERSION WX_LIBS_STATIC WX_LIBS WX_CXXFLAGS_ONLY WX_CFLAGS_ONLY WX_CXXFLAGS WX_CFLAGS WX_CPPFLAGS WX_CONFIG_PATH LIBTOOL ac_ct_F77 FFLAGS F77 CXXCPP CPP NMEDIT DSYMUTIL RANLIB AR ECHO LN_S EGREP GREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC WITH_ENUMPOLY_FALSE WITH_ENUMPOLY_TRUE WITH_GUI_FALSE WITH_GUI_TRUE am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_wxdir with_wx_config with_wx_prefix with_wx_exec_prefix enable_gui enable_enumpoly enable_dependency_tracking enable_shared enable_static enable_fast_install with_gnu_ld enable_libtool_lock with_pic with_tags ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CXX CXXFLAGS CCC CPP CXXCPP F77 FFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 { (exit 1); exit 1; }; } ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 { (exit 1); exit 1; }; } ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2 { (exit 1); exit 1; }; } ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2 { (exit 1); exit 1; }; } ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { $as_echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { $as_echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2 { (exit 1); exit 1; }; } ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { $as_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || { $as_echo "$as_me: error: working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { $as_echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." { $as_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures gambit 0.2010.09.01 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/gambit] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of gambit 0.2010.09.01:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-gui don't build graphical interface --disable-enumpoly don't build gambit-enumpoly (not supported on 64bit) --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-wxdir=PATH Use uninstalled version of wxWidgets in PATH --with-wx-config=CONFIG wx-config script to use (optional) --with-wx-prefix=PREFIX Prefix where wxWidgets is installed (optional) --with-wx-exec-prefix=PREFIX Exec prefix where wxWidgets is installed (optional) --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-pic try to use only PIC/non-PIC objects [default=use both] --with-tags[=TAGS] include additional configurations [automatic] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags CPP C preprocessor CXXCPP C++ preprocessor F77 Fortran 77 compiler command FFLAGS Fortran 77 compiler flags Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF gambit configure 0.2010.09.01 generated by GNU Autoconf 2.63 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by gambit $as_me 0.2010.09.01, which was generated by GNU Autoconf 2.63. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test -r "$ac_site_file"; then { $as_echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { $as_echo "$as_me:$LINENO: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:$LINENO: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:$LINENO: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:$LINENO: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 $as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version="1.9" ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { $as_echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 $as_echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} { (exit 1); exit 1; }; } fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:$LINENO: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:$LINENO: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { $as_echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 $as_echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { $as_echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 $as_echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AWK+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:$LINENO: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { { $as_echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 $as_echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='gambit' VERSION='0.2010.09.01' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} install_sh=${install_sh-"$am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:$LINENO: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' # Check whether --with-wxdir was given. if test "${with_wxdir+set}" = set; then withval=$with_wxdir; wx_config_name="$withval/wx-config" wx_config_args="--inplace" fi # Check whether --with-wx-config was given. if test "${with_wx_config+set}" = set; then withval=$with_wx_config; wx_config_name="$withval" fi # Check whether --with-wx-prefix was given. if test "${with_wx_prefix+set}" = set; then withval=$with_wx_prefix; wx_config_prefix="$withval" else wx_config_prefix="" fi # Check whether --with-wx-exec-prefix was given. if test "${with_wx_exec_prefix+set}" = set; then withval=$with_wx_exec_prefix; wx_config_exec_prefix="$withval" else wx_config_exec_prefix="" fi # Check whether --enable-gui was given. if test "${enable_gui+set}" = set; then enableval=$enable_gui; case "${enableval}" in yes) with_gui=true ;; no) with_gui=false ;; *) { { $as_echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-gui" >&5 $as_echo "$as_me: error: bad value ${enableval} for --enable-gui" >&2;} { (exit 1); exit 1; }; } ;; esac else with_gui=true fi if test x$with_gui = xtrue; then WITH_GUI_TRUE= WITH_GUI_FALSE='#' else WITH_GUI_TRUE='#' WITH_GUI_FALSE= fi # Check whether --enable-enumpoly was given. if test "${enable_enumpoly+set}" = set; then enableval=$enable_enumpoly; case "${enableval}" in yes) with_enumpoly=true ;; no) with_enumpoly=false ;; *) { { $as_echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-enumpoly" >&5 $as_echo "$as_me: error: bad value ${enableval} for --enable-enumpoly" >&2;} { (exit 1); exit 1; }; } ;; esac else with_enumpoly=true fi if test x$with_enumpoly = xtrue; then WITH_ENUMPOLY_TRUE= WITH_ENUMPOLY_FALSE='#' else WITH_ENUMPOLY_TRUE='#' WITH_ENUMPOLY_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 $as_echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } # Provide some information about the compiler. $as_echo "$as_me:$LINENO: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi { $as_echo "$as_me:$LINENO: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } if test -z "$ac_file"; then $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 $as_echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:$LINENO: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } fi fi fi { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } { $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } { $as_echo "$as_me:$LINENO: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } fi rm -f conftest$ac_cv_exeext { $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:$LINENO: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:$LINENO: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi { $as_echo "$as_me:$LINENO: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CXX+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:$LINENO: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:$LINENO: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { $as_echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if test "${ac_cv_cxx_compiler_gnu+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if test "${ac_cv_prog_cxx_g+set}" = set; then $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CXXFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || { { $as_echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 $as_echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} { (exit 1); exit 1; }; } { $as_echo "$as_me:$LINENO: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if test "${ac_cv_build+set}" = set; then $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && { { $as_echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 $as_echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 $as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi { $as_echo "$as_me:$LINENO: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 $as_echo "$as_me: error: invalid value of canonical build" >&2;} { (exit 1); exit 1; }; };; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:$LINENO: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if test "${ac_cv_host+set}" = set; then $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 $as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} { (exit 1); exit 1; }; } fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 $as_echo "$as_me: error: invalid value of canonical host" >&2;} { (exit 1); exit 1; }; };; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if test "${lt_cv_path_SED+set}" = set; then $as_echo_n "(cached) " >&6 else # Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$lt_ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$lt_ac_prog$ac_exec_ext"; }; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done fi SED=$lt_cv_path_SED { $as_echo "$as_me:$LINENO: result: $SED" >&5 $as_echo "$SED" >&6; } { $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if test "${ac_cv_path_GREP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 $as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:$LINENO: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if test "${ac_cv_path_EGREP+set}" = set; then $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 $as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:$LINENO: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:$LINENO: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:$LINENO: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if test "${lt_cv_path_LD+set}" = set; then $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && { { $as_echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 $as_echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} { (exit 1); exit 1; }; } { $as_echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if test "${lt_cv_prog_gnu_ld+set}" = set; then $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if test "${lt_cv_ld_reload_flag+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac { $as_echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 $as_echo_n "checking for BSD-compatible nm... " >&6; } if test "${lt_cv_path_NM+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi fi { $as_echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } NM="$lt_cv_path_NM" { $as_echo "$as_me:$LINENO: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:$LINENO: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi { $as_echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if test "${lt_cv_deplibs_check_method+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; nto-qnx*) lt_cv_deplibs_check_method=unknown ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 4984 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if test "${lt_cv_cc_needs_belf+set}" = set; then $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_cv_cc_needs_belf=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_cc_needs_belf=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:$LINENO: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 $as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -rf conftest.dSYM rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if test "${ac_cv_prog_CXXCPP+set}" = set; then $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:$LINENO: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&5 $as_echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu fi ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_F77+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$F77"; then ac_cv_prog_F77="$F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_F77="$ac_tool_prefix$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi F77=$ac_cv_prog_F77 if test -n "$F77"; then { $as_echo "$as_me:$LINENO: result: $F77" >&5 $as_echo "$F77" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$F77" && break done fi if test -z "$F77"; then ac_ct_F77=$F77 for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_F77+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_F77"; then ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_F77="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_F77=$ac_cv_prog_ac_ct_F77 if test -n "$ac_ct_F77"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 $as_echo "$ac_ct_F77" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_F77" && break done if test "x$ac_ct_F77" = x; then F77="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac F77=$ac_ct_F77 fi fi # Provide some information about the compiler. $as_echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5 set X $ac_compile ac_compiler=$2 { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -f a.out # If we don't use `.F' as extension, the preprocessor is not run on the # input file. (Note that this only needs to work for GNU compilers.) ac_save_ext=$ac_ext ac_ext=F { $as_echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 $as_echo_n "checking whether we are using the GNU Fortran 77 compiler... " >&6; } if test "${ac_cv_f77_compiler_gnu+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF program main #ifndef __GNUC__ choke me #endif end _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_f77_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 $as_echo "$ac_cv_f77_compiler_gnu" >&6; } ac_ext=$ac_save_ext ac_test_FFLAGS=${FFLAGS+set} ac_save_FFLAGS=$FFLAGS FFLAGS= { $as_echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 $as_echo_n "checking whether $F77 accepts -g... " >&6; } if test "${ac_cv_prog_f77_g+set}" = set; then $as_echo_n "(cached) " >&6 else FFLAGS=-g cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_f77_g=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_f77_g=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 $as_echo "$ac_cv_prog_f77_g" >&6; } if test "$ac_test_FFLAGS" = set; then FFLAGS=$ac_save_FFLAGS elif test $ac_cv_prog_f77_g = yes; then if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-g -O2" else FFLAGS="-g" fi else if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-O2" else FFLAGS= fi fi if test $ac_compiler_gnu = yes; then G77=yes else G77= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! # find the maximum length of command line arguments { $as_echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if test "${lt_cv_sys_max_cmd_len+set}" = set; then $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ = "XX$teststring") >/dev/null 2>&1 && new_result=`expr "X$teststring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done teststring= # Add a significant safety factor because C++ compilers can tack on massive # amounts of additional arguments before passing them to the linker. # It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:$LINENO: result: none" >&5 $as_echo "none" >&6; } fi # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32*) symcode='[ABCDGISTW]' ;; hpux*) # Its linker distinguishes data from code symbols if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; linux* | k*bsd*-gnu) if test "$host_cpu" = ia64; then symcode='[ABCDGIRSTW]' lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Now try to grab the symbols. nlist=conftest.nm if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if grep ' nm_test_var$' "$nlist" >/dev/null; then if grep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[] = { EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:$LINENO: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:$LINENO: result: ok" >&5 $as_echo "ok" >&6; } fi { $as_echo "$as_me:$LINENO: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if test "${lt_cv_objdir+set}" = set; then $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AR+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:$LINENO: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_AR+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:$LINENO: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:$LINENO: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$SED" && SED=sed test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:$LINENO: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_DSYMUTIL+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:$LINENO: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_NMEDIT+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:$LINENO: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi { $as_echo "$as_me:$LINENO: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if test "${lt_cv_apple_cc_single_mod+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. echo "int foo(void){return 1;}" > conftest.c $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib ${wl}-single_module conftest.c if test -f libconftest.dylib; then lt_cv_apple_cc_single_mod=yes rm -rf libconftest.dylib* fi rm conftest.c fi fi { $as_echo "$as_me:$LINENO: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:$LINENO: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if test "${lt_cv_ld_exported_symbols_list+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_cv_ld_exported_symbols_list=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_ld_exported_symbols_list=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:$LINENO: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } case $host_os in rhapsody* | darwin1.[0123]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms="~$NMEDIT -s \$output_objdir/\${libname}-symbols.expsym \${lib}" fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil="~$DSYMUTIL \$lib || :" else _lt_dsymutil= fi ;; esac enable_dlopen=no enable_win32_dll=no # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Check whether --with-pic was given. if test "${with_pic+set}" = set; then withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Use C for the default configuration in the libtool script tagname= lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm -r conftest* lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' { $as_echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7584: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7588: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= { $as_echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; *) lt_prog_compiler_pic='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic='-qnocommon' lt_prog_compiler_wl='-Wl,' ;; esac ;; mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; linux* | k*bsd*-gnu) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; esac ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi { $as_echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 $as_echo "$lt_prog_compiler_pic" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if test "${lt_cv_prog_compiler_pic_works+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7874: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7878: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test "${lt_cv_prog_compiler_static_works+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $rm -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7978: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7982: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:$LINENO: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= enable_shared_with_static_runtimes=no archive_cmds= archive_expsym_cmds= old_archive_From_new_cmds= old_archive_from_expsyms_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported link_all_deplibs=unknown hardcode_automatic=no module_cmds= module_expsym_cmds= always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; *) tmp_sharedflag='-shared' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_libdir_separator=':' link_all_deplibs=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) allow_undefined_flag="$_lt_dar_allow_undefined" archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='' link_all_deplibs=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs=no ;; esac fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld='-rpath $libdir' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z text' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi { $as_echo "$as_me:$LINENO: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $rm conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc=no else archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { $as_echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 $as_echo "$archive_cmds_need_lc" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`echo $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:$LINENO: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" fi sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" fi sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi { $as_echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var" || \ test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:$LINENO: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= { $as_echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } ;; esac fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dl_dlopen=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = x""yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) { $as_echo "$as_me:$LINENO: checking for shl_load" >&5 $as_echo_n "checking for shl_load... " >&6; } if test "${ac_cv_func_shl_load+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define shl_load to an innocuous variant, in case declares shl_load. For example, HP-UX 11i declares gettimeofday. */ #define shl_load innocuous_shl_load /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef shl_load /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_shl_load || defined __stub___shl_load choke me #endif int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_shl_load=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 $as_echo "$ac_cv_func_shl_load" >&6; } if test "x$ac_cv_func_shl_load" = x""yes; then lt_cv_dlopen="shl_load" else { $as_echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dld_shl_load=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = x""yes; then lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else { $as_echo "$as_me:$LINENO: checking for dlopen" >&5 $as_echo_n "checking for dlopen... " >&6; } if test "${ac_cv_func_dlopen+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define dlopen to an innocuous variant, in case declares dlopen. For example, HP-UX 11i declares gettimeofday. */ #define dlopen innocuous_dlopen /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef dlopen /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_dlopen || defined __stub___dlopen choke me #endif int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_dlopen=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 $as_echo "$ac_cv_func_dlopen" >&6; } if test "x$ac_cv_func_dlopen" = x""yes; then lt_cv_dlopen="dlopen" else { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dl_dlopen=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = x""yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if test "${ac_cv_lib_svld_dlopen+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_svld_dlopen=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = x""yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if test "${ac_cv_lib_dld_dld_link+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dld_dld_link=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = x""yes; then lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if test "${lt_cv_dlopen_self+set}" = set; then $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); exit (status); } EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if test "${lt_cv_dlopen_self_static+set}" = set; then $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); exit (status); } EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:$LINENO: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:$LINENO: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:$LINENO: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:$LINENO: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler \ CC \ LD \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_prog_compiler_no_builtin_flag \ export_dynamic_flag_spec \ thread_safe_flag_spec \ whole_archive_flag_spec \ enable_shared_with_static_runtimes \ old_archive_cmds \ old_archive_from_new_cmds \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ compiler_lib_search_dirs \ archive_cmds \ archive_expsym_cmds \ postinstall_cmds \ postuninstall_cmds \ old_archive_from_expsyms_cmds \ allow_undefined_flag \ no_undefined_flag \ export_symbols_cmds \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ hardcode_automatic \ module_cmds \ module_expsym_cmds \ lt_cv_prog_compiler_c_o \ fix_srcfile_path \ exclude_expsyms \ include_expsyms; do case $var in old_archive_cmds | \ old_archive_from_new_cmds | \ archive_cmds | \ archive_expsym_cmds | \ module_cmds | \ module_expsym_cmds | \ old_archive_from_expsyms_cmds | \ export_symbols_cmds | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="${ofile}T" trap "$rm \"$cfgfile\"; exit 1" 1 2 15 $rm -f "$cfgfile" { $as_echo "$as_me:$LINENO: creating $ofile" >&5 $as_echo "$as_me: creating $ofile" >&6;} cat <<__EOF__ >> "$cfgfile" #! $SHELL # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: # Originally by Gordon Matzigkeit , 1996 # # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e 1s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # The names of the tagged configurations supported by this script. available_tags= # ### BEGIN LIBTOOL CONFIG # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler # Is the compiler the GNU C compiler? with_gcc=$GCC # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps # The directories searched by this compiler when creating a shared # library compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # ### END LIBTOOL CONFIG __EOF__ case $host_os in aix3*) cat <<\EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || \ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" # Check whether --with-tags was given. if test "${with_tags+set}" = set; then withval=$with_tags; tagnames="$withval" fi if test -f "$ltmain" && test -n "$tagnames"; then if test ! -f "${ofile}"; then { $as_echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 $as_echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} fi if test -z "$LTCC"; then eval "`$SHELL ${ofile} --config | grep '^LTCC='`" if test -z "$LTCC"; then { $as_echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 $as_echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} else { $as_echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 $as_echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} fi fi if test -z "$LTCFLAGS"; then eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for tagname in $tagnames; do IFS="$lt_save_ifs" # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in "") ;; *) { { $as_echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 $as_echo "$as_me: error: invalid tag name: $tagname" >&2;} { (exit 1); exit 1; }; } ;; esac if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then { { $as_echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 $as_echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} { (exit 1); exit 1; }; } fi # Update the list of available tags. if test -n "$tagname"; then echo appending configuration tag \"$tagname\" to $ofile case $tagname in CXX) if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_flag_spec_ld_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= compiler_lib_search_dirs_CXX= # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC compiler_CXX=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:$LINENO: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:$LINENO: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:$LINENO: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if test "${lt_cv_path_LD+set}" = set; then $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && { { $as_echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 $as_echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} { (exit 1); exit 1; }; } { $as_echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if test "${lt_cv_prog_gnu_ld+set}" = set; then $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes if test "$GXX" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_CXX=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' archive_cmds_need_lc_CXX=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported whole_archive_flag_spec_CXX='' link_all_deplibs_CXX=yes allow_undefined_flag_CXX="$_lt_dar_allow_undefined" if test "$GXX" = yes ; then output_verbose_link_cmd='echo' archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" if test "$lt_cv_apple_cc_single_mod" != "yes"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs_CXX=no ;; esac fi ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd[12]*) # C++ shared libraries reported to be fairly broken before switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; gnu*) ;; hpux9*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: ;; linux* | k*bsd*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc*) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; openbsd2*) # C++ shared libraries are fairly broken ld_shlibs_CXX=no ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='${wl}-E' whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd='echo' else ld_shlibs_CXX=no fi ;; osf3*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ $rm $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | grep -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='${wl}-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. # So that behaviour is only enabled if SCOABSPATH is set to a # non-empty value in the environment. Most likely only useful for # creating official distributions of packages. # This is a hack until libtool officially supports absolute path # names for shared libraries. no_undefined_flag_CXX='${wl}-z,text' allow_undefined_flag_CXX='${wl}-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no GCC_CXX="$GXX" LD_CXX="$LD" cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no # The `*' in the case matches for architectures that use `case' in # $output_verbose_cmd can trigger glob expansion during the loop # eval without this substitution. output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` for p in `eval $output_verbose_link_cmd`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" \ || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX="${prev}${p}" else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX="${prev}${p}" else postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$predep_objects_CXX"; then predep_objects_CXX="$p" else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX="$p" else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $rm -f confest.$objext compiler_lib_search_dirs_CXX= if test -n "$compiler_lib_search_path_CXX"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then postdeps_CXX='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then postdeps_CXX='-library=Cstd -library=Crun' fi ;; esac ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= { $as_echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic_CXX='-qnocommon' lt_prog_compiler_wl_CXX='-Wl,' ;; esac ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; icpc* | ecpc*) # Intel C++ lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi { $as_echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 $as_echo "$lt_prog_compiler_pic_CXX" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:12869: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:12873: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { $as_echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $rm -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then : else lt_prog_compiler_static_CXX= fi { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:12973: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:12977: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:$LINENO: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw*) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' { $as_echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $rm conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_CXX=no else archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { $as_echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 $as_echo "$archive_cmds_need_lc_CXX" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:$LINENO: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" fi sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" fi sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi { $as_echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || \ test -n "$runpath_var_CXX" || \ test "X$hardcode_automatic_CXX" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_CXX" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && test "$hardcode_minus_L_CXX" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test "$hardcode_action_CXX" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_CXX \ CC_CXX \ LD_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_static_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ export_dynamic_flag_spec_CXX \ thread_safe_flag_spec_CXX \ whole_archive_flag_spec_CXX \ enable_shared_with_static_runtimes_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX \ compiler_lib_search_dirs_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ postinstall_cmds_CXX \ postuninstall_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ export_symbols_cmds_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_flag_spec_ld_CXX \ hardcode_libdir_separator_CXX \ hardcode_automatic_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ lt_cv_prog_compiler_c_o_CXX \ fix_srcfile_path_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX; do case $var in old_archive_cmds_CXX | \ old_archive_from_new_cmds_CXX | \ archive_cmds_CXX | \ archive_expsym_cmds_CXX | \ module_cmds_CXX | \ module_expsym_cmds_CXX | \ old_archive_from_expsyms_cmds_CXX | \ export_symbols_cmds_CXX | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU C compiler? with_gcc=$GCC_CXX # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_CXX # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_CXX old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_CXX # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_CXX # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_CXX # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_CXX # The directories searched by this compiler when creating a shared # library compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_CXX # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ldcxx=$with_gnu_ld with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld else tagname="" fi ;; F77) if test -n "$F77" && test "X$F77" != "Xno"; then ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu archive_cmds_need_lc_F77=no allow_undefined_flag_F77= always_export_symbols_F77=no archive_expsym_cmds_F77= export_dynamic_flag_spec_F77= hardcode_direct_F77=no hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_minus_L_F77=no hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= link_all_deplibs_F77=unknown old_archive_cmds_F77=$old_archive_cmds no_undefined_flag_F77= whole_archive_flag_spec_F77= enable_shared_with_static_runtimes_F77=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o objext_F77=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm -r conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${F77-"f77"} compiler=$CC compiler_F77=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` { $as_echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:$LINENO: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:$LINENO: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:$LINENO: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:$LINENO: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } GCC_F77="$G77" LD_F77="$LD" lt_prog_compiler_wl_F77= lt_prog_compiler_pic_F77= lt_prog_compiler_static_F77= { $as_echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_static_F77='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_F77='-fno-common' ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_F77=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_F77=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_F77='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' else lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic_F77='-qnocommon' lt_prog_compiler_wl_F77='-Wl,' ;; esac ;; mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_F77='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_F77='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_F77='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_F77='-non_shared' ;; newsos6) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; linux* | k*bsd*-gnu) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-fpic' lt_prog_compiler_static_F77='-Bstatic' ;; ccc*) lt_prog_compiler_wl_F77='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' lt_prog_compiler_wl_F77='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' lt_prog_compiler_wl_F77='' ;; esac ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_F77='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; rdos*) lt_prog_compiler_static_F77='-non_shared' ;; solaris*) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl_F77='-Qoption ld ';; *) lt_prog_compiler_wl_F77='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl_F77='-Qoption ld ' lt_prog_compiler_pic_F77='-PIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_F77='-Kconform_pic' lt_prog_compiler_static_F77='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; unicos*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_can_build_shared_F77=no ;; uts4*) lt_prog_compiler_pic_F77='-pic' lt_prog_compiler_static_F77='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_F77=no ;; esac fi { $as_echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 $as_echo "$lt_prog_compiler_pic_F77" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_F77"; then { $as_echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... " >&6; } if test "${lt_cv_prog_compiler_pic_works_F77+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_F77=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_F77" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:14556: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:14560: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_F77=yes fi fi $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works_F77" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_F77" >&6; } if test x"$lt_cv_prog_compiler_pic_works_F77" = xyes; then case $lt_prog_compiler_pic_F77 in "" | " "*) ;; *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; esac else lt_prog_compiler_pic_F77= lt_prog_compiler_can_build_shared_F77=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_F77= ;; *) lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" { $as_echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test "${lt_cv_prog_compiler_static_works_F77+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_F77=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_F77=yes fi else lt_cv_prog_compiler_static_works_F77=yes fi fi $rm -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works_F77" >&5 $as_echo "$lt_cv_prog_compiler_static_works_F77" >&6; } if test x"$lt_cv_prog_compiler_static_works_F77" = xyes; then : else lt_prog_compiler_static_F77= fi { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_F77=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:14660: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:14664: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_F77=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 $as_echo "$lt_cv_prog_compiler_c_o_F77" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:$LINENO: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag_F77= enable_shared_with_static_runtimes_F77=no archive_cmds_F77= archive_expsym_cmds_F77= old_archive_From_new_cmds_F77= old_archive_from_expsyms_cmds_F77= export_dynamic_flag_spec_F77= whole_archive_flag_spec_F77= thread_safe_flag_spec_F77= hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_direct_F77=no hardcode_minus_L_F77=no hardcode_shlibpath_var_F77=unsupported link_all_deplibs_F77=unknown hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= always_export_symbols_F77=no export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_F77= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_F77='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs_F77=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_F77='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_F77= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_F77=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs_F77=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_F77=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_F77=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_F77='-L$libdir' allow_undefined_flag_F77=unsupported always_export_symbols_F77=no enable_shared_with_static_runtimes_F77=yes export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_F77=no fi ;; interix[3-9]*) hardcode_direct_F77=no hardcode_shlibpath_var_F77=no hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec_F77='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; *) tmp_sharedflag='-shared' ;; esac archive_cmds_F77='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs_F77=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_F77=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs_F77=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac ;; sunos4*) archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac if test "$ld_shlibs_F77" = no; then runpath_var= hardcode_libdir_flag_spec_F77= export_dynamic_flag_spec_F77= whole_archive_flag_spec_F77= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_F77=unsupported always_export_symbols_F77=yes archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_F77=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_F77=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_F77='' hardcode_direct_F77=yes hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_F77=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_F77=yes hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_libdir_separator_F77= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_F77=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_F77='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_F77="-z nodefs" archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_F77=' ${wl}-bernotok' allow_undefined_flag_F77=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_F77='$convenience' archive_cmds_need_lc_F77=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes # see comment about different semantics on the GNU ld section ld_shlibs_F77=no ;; bsdi[45]*) export_dynamic_flag_spec_F77=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_F77=' ' allow_undefined_flag_F77=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_F77='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_F77='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path_F77='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_F77=yes ;; darwin* | rhapsody*) allow_undefined_flag_F77="$_lt_dar_allow_undefined" archive_cmds_need_lc_F77=no hardcode_direct_F77=no hardcode_automatic_F77=yes hardcode_shlibpath_var_F77=unsupported whole_archive_flag_spec_F77='' link_all_deplibs_F77=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' archive_cmds_F77="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds_F77="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds_F77="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds_F77="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs_F77=no ;; esac fi ;; dgux*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; freebsd1*) ld_shlibs_F77=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes export_dynamic_flag_spec_F77='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld_F77='+b $libdir' hardcode_direct_F77=no hardcode_shlibpath_var_F77=no ;; *) hardcode_direct_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: link_all_deplibs_F77=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; newsos6) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_shlibpath_var_F77=no ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-R$libdir' ;; *) archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs_F77=no fi ;; os2*) hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes allow_undefined_flag_F77=unsupported archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_F77='-rpath $libdir' fi hardcode_libdir_separator_F77=: ;; solaris*) no_undefined_flag_F77=' -z text' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_shlibpath_var_F77=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec_F77='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs_F77=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; sysv4) case $host_vendor in sni) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_F77='$CC -r -o $output$reload_objs' hardcode_direct_F77=no ;; motorola) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_F77=no ;; sysv4.3*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no export_dynamic_flag_spec_F77='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_F77=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_F77='${wl}-z,text' archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_F77='${wl}-z,text' allow_undefined_flag_F77='${wl}-z,nodefs' archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes export_dynamic_flag_spec_F77='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; *) ld_shlibs_F77=no ;; esac fi { $as_echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 $as_echo "$ld_shlibs_F77" >&6; } test "$ld_shlibs_F77" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_F77" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_F77=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_F77 in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $rm conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_F77 pic_flag=$lt_prog_compiler_pic_F77 compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_F77 allow_undefined_flag_F77= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_F77=no else archive_cmds_need_lc_F77=yes fi allow_undefined_flag_F77=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { $as_echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 $as_echo "$archive_cmds_need_lc_F77" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:$LINENO: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" fi sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" fi sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi { $as_echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_F77= if test -n "$hardcode_libdir_flag_spec_F77" || \ test -n "$runpath_var_F77" || \ test "X$hardcode_automatic_F77" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_F77" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && test "$hardcode_minus_L_F77" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_F77=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_F77=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_F77=unsupported fi { $as_echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 $as_echo "$hardcode_action_F77" >&6; } if test "$hardcode_action_F77" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_F77 \ CC_F77 \ LD_F77 \ lt_prog_compiler_wl_F77 \ lt_prog_compiler_pic_F77 \ lt_prog_compiler_static_F77 \ lt_prog_compiler_no_builtin_flag_F77 \ export_dynamic_flag_spec_F77 \ thread_safe_flag_spec_F77 \ whole_archive_flag_spec_F77 \ enable_shared_with_static_runtimes_F77 \ old_archive_cmds_F77 \ old_archive_from_new_cmds_F77 \ predep_objects_F77 \ postdep_objects_F77 \ predeps_F77 \ postdeps_F77 \ compiler_lib_search_path_F77 \ compiler_lib_search_dirs_F77 \ archive_cmds_F77 \ archive_expsym_cmds_F77 \ postinstall_cmds_F77 \ postuninstall_cmds_F77 \ old_archive_from_expsyms_cmds_F77 \ allow_undefined_flag_F77 \ no_undefined_flag_F77 \ export_symbols_cmds_F77 \ hardcode_libdir_flag_spec_F77 \ hardcode_libdir_flag_spec_ld_F77 \ hardcode_libdir_separator_F77 \ hardcode_automatic_F77 \ module_cmds_F77 \ module_expsym_cmds_F77 \ lt_cv_prog_compiler_c_o_F77 \ fix_srcfile_path_F77 \ exclude_expsyms_F77 \ include_expsyms_F77; do case $var in old_archive_cmds_F77 | \ old_archive_from_new_cmds_F77 | \ archive_cmds_F77 | \ archive_expsym_cmds_F77 | \ module_cmds_F77 | \ module_expsym_cmds_F77 | \ old_archive_from_expsyms_cmds_F77 | \ export_symbols_cmds_F77 | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_F77 # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_F77 # Is the compiler the GNU C compiler? with_gcc=$GCC_F77 # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_F77 # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_F77 # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_F77 pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_F77 # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_F77 old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_F77 archive_expsym_cmds=$lt_archive_expsym_cmds_F77 postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_F77 module_expsym_cmds=$lt_module_expsym_cmds_F77 # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_F77 # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_F77 # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_F77 # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_F77 # The directories searched by this compiler when creating a shared # library compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_F77 # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_F77 # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_F77 # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_F77 # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_F77 # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_F77 # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_F77 # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_F77 # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_F77 # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_F77 # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_F77 # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_F77 # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_F77 # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; GCJ) if test -n "$GCJ" && test "X$GCJ" != "Xno"; then # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o objext_GCJ=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm -r conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${GCJ-"gcj"} compiler=$CC compiler_GCJ=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # GCJ did not exist at the time GCC didn't implicitly link libc in. archive_cmds_need_lc_GCJ=no old_archive_cmds_GCJ=$old_archive_cmds lt_prog_compiler_no_builtin_flag_GCJ= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' { $as_echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:16857: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:16861: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl_GCJ= lt_prog_compiler_pic_GCJ= lt_prog_compiler_static_GCJ= { $as_echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_static_GCJ='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_GCJ='-fno-common' ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_GCJ=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_GCJ=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_GCJ='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' else lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' fi ;; darwin*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files case $cc_basename in xlc*) lt_prog_compiler_pic_GCJ='-qnocommon' lt_prog_compiler_wl_GCJ='-Wl,' ;; esac ;; mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_GCJ='-non_shared' ;; newsos6) lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; linux* | k*bsd*-gnu) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-fpic' lt_prog_compiler_static_GCJ='-Bstatic' ;; ccc*) lt_prog_compiler_wl_GCJ='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' lt_prog_compiler_wl_GCJ='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' lt_prog_compiler_wl_GCJ='' ;; esac ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_GCJ='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; rdos*) lt_prog_compiler_static_GCJ='-non_shared' ;; solaris*) lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl_GCJ='-Qoption ld ';; *) lt_prog_compiler_wl_GCJ='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl_GCJ='-Qoption ld ' lt_prog_compiler_pic_GCJ='-PIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_GCJ='-Kconform_pic' lt_prog_compiler_static_GCJ='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; unicos*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_can_build_shared_GCJ=no ;; uts4*) lt_prog_compiler_pic_GCJ='-pic' lt_prog_compiler_static_GCJ='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_GCJ=no ;; esac fi { $as_echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 $as_echo "$lt_prog_compiler_pic_GCJ" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_GCJ"; then { $as_echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... " >&6; } if test "${lt_cv_prog_compiler_pic_works_GCJ+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_GCJ=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_GCJ" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:17147: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:17151: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_GCJ=yes fi fi $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works_GCJ" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_GCJ" >&6; } if test x"$lt_cv_prog_compiler_pic_works_GCJ" = xyes; then case $lt_prog_compiler_pic_GCJ in "" | " "*) ;; *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; esac else lt_prog_compiler_pic_GCJ= lt_prog_compiler_can_build_shared_GCJ=no fi fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_GCJ= ;; *) lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" ;; esac # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" { $as_echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test "${lt_cv_prog_compiler_static_works_GCJ+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_GCJ=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_GCJ=yes fi else lt_cv_prog_compiler_static_works_GCJ=yes fi fi $rm -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works_GCJ" >&5 $as_echo "$lt_cv_prog_compiler_static_works_GCJ" >&6; } if test x"$lt_cv_prog_compiler_static_works_GCJ" = xyes; then : else lt_prog_compiler_static_GCJ= fi { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_GCJ=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:17251: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:17255: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_GCJ=yes fi fi chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 $as_echo "$lt_cv_prog_compiler_c_o_GCJ" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:$LINENO: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag_GCJ= enable_shared_with_static_runtimes_GCJ=no archive_cmds_GCJ= archive_expsym_cmds_GCJ= old_archive_From_new_cmds_GCJ= old_archive_from_expsyms_cmds_GCJ= export_dynamic_flag_spec_GCJ= whole_archive_flag_spec_GCJ= thread_safe_flag_spec_GCJ= hardcode_libdir_flag_spec_GCJ= hardcode_libdir_flag_spec_ld_GCJ= hardcode_libdir_separator_GCJ= hardcode_direct_GCJ=no hardcode_minus_L_GCJ=no hardcode_shlibpath_var_GCJ=unsupported link_all_deplibs_GCJ=unknown hardcode_automatic_GCJ=no module_cmds_GCJ= module_expsym_cmds_GCJ= always_export_symbols_GCJ=no export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_GCJ= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_GCJ='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs_GCJ=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_GCJ= fi supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_GCJ=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs_GCJ=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_GCJ=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_GCJ=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_GCJ='-L$libdir' allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=no enable_shared_with_static_runtimes_GCJ=yes export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_GCJ=no fi ;; interix[3-9]*) hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' export_dynamic_flag_spec_GCJ='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec_GCJ='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; *) tmp_sharedflag='-shared' ;; esac archive_cmds_GCJ='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs_GCJ=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_GCJ=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs_GCJ=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; esac ;; sunos4*) archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; esac if test "$ld_shlibs_GCJ" = no; then runpath_var= hardcode_libdir_flag_spec_GCJ= export_dynamic_flag_spec_GCJ= whole_archive_flag_spec_GCJ= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=yes archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_GCJ=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_GCJ=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_GCJ='' hardcode_direct_GCJ=yes hardcode_libdir_separator_GCJ=':' link_all_deplibs_GCJ=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_GCJ=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_GCJ=yes hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_libdir_separator_GCJ= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_GCJ=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_GCJ='-berok' # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_GCJ="-z nodefs" archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_GCJ=' ${wl}-bernotok' allow_undefined_flag_GCJ=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_GCJ='$convenience' archive_cmds_need_lc_GCJ=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes # see comment about different semantics on the GNU ld section ld_shlibs_GCJ=no ;; bsdi[45]*) export_dynamic_flag_spec_GCJ=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_GCJ=' ' allow_undefined_flag_GCJ=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_GCJ='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_GCJ='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_GCJ=yes ;; darwin* | rhapsody*) allow_undefined_flag_GCJ="$_lt_dar_allow_undefined" archive_cmds_need_lc_GCJ=no hardcode_direct_GCJ=no hardcode_automatic_GCJ=yes hardcode_shlibpath_var_GCJ=unsupported whole_archive_flag_spec_GCJ='' link_all_deplibs_GCJ=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' archive_cmds_GCJ="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds_GCJ="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds_GCJ="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds_GCJ="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else case $cc_basename in xlc*) output_verbose_link_cmd='echo' archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) ld_shlibs_GCJ=no ;; esac fi ;; dgux*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; freebsd1*) ld_shlibs_GCJ=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: case $host_cpu in hppa*64*|ia64*) hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no ;; *) hardcode_direct_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: link_all_deplibs_GCJ=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; newsos6) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_shlibpath_var_GCJ=no ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' export_dynamic_flag_spec_GCJ='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' ;; *) archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs_GCJ=no fi ;; os2*) hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes allow_undefined_flag_GCJ=unsupported archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_GCJ='-rpath $libdir' fi hardcode_libdir_separator_GCJ=: ;; solaris*) no_undefined_flag_GCJ=' -z text' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else wlarc='' archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_shlibpath_var_GCJ=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs_GCJ=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; sysv4) case $host_vendor in sni) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_GCJ='$CC -r -o $output$reload_objs' hardcode_direct_GCJ=no ;; motorola) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_GCJ=no ;; sysv4.3*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no export_dynamic_flag_spec_GCJ='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_GCJ=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_GCJ='${wl}-z,text' archive_cmds_need_lc_GCJ=no hardcode_shlibpath_var_GCJ=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_GCJ='${wl}-z,text' allow_undefined_flag_GCJ='${wl}-z,nodefs' archive_cmds_need_lc_GCJ=no hardcode_shlibpath_var_GCJ=no hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator_GCJ=':' link_all_deplibs_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; *) ld_shlibs_GCJ=no ;; esac fi { $as_echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 $as_echo "$ld_shlibs_GCJ" >&6; } test "$ld_shlibs_GCJ" = no && can_build_shared=no # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_GCJ" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_GCJ=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_GCJ in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $rm conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_GCJ pic_flag=$lt_prog_compiler_pic_GCJ compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ allow_undefined_flag_GCJ= if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc_GCJ=no else archive_cmds_need_lc_GCJ=yes fi allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { $as_echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 $as_echo "$archive_cmds_need_lc_GCJ" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' shlibpath_overrides_runpath=no else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' shlibpath_overrides_runpath=yes case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:$LINENO: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" fi sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" fi sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi { $as_echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_GCJ= if test -n "$hardcode_libdir_flag_spec_GCJ" || \ test -n "$runpath_var_GCJ" || \ test "X$hardcode_automatic_GCJ" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_GCJ" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && test "$hardcode_minus_L_GCJ" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_GCJ=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_GCJ=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_GCJ=unsupported fi { $as_echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 $as_echo "$hardcode_action_GCJ" >&6; } if test "$hardcode_action_GCJ" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_GCJ \ CC_GCJ \ LD_GCJ \ lt_prog_compiler_wl_GCJ \ lt_prog_compiler_pic_GCJ \ lt_prog_compiler_static_GCJ \ lt_prog_compiler_no_builtin_flag_GCJ \ export_dynamic_flag_spec_GCJ \ thread_safe_flag_spec_GCJ \ whole_archive_flag_spec_GCJ \ enable_shared_with_static_runtimes_GCJ \ old_archive_cmds_GCJ \ old_archive_from_new_cmds_GCJ \ predep_objects_GCJ \ postdep_objects_GCJ \ predeps_GCJ \ postdeps_GCJ \ compiler_lib_search_path_GCJ \ compiler_lib_search_dirs_GCJ \ archive_cmds_GCJ \ archive_expsym_cmds_GCJ \ postinstall_cmds_GCJ \ postuninstall_cmds_GCJ \ old_archive_from_expsyms_cmds_GCJ \ allow_undefined_flag_GCJ \ no_undefined_flag_GCJ \ export_symbols_cmds_GCJ \ hardcode_libdir_flag_spec_GCJ \ hardcode_libdir_flag_spec_ld_GCJ \ hardcode_libdir_separator_GCJ \ hardcode_automatic_GCJ \ module_cmds_GCJ \ module_expsym_cmds_GCJ \ lt_cv_prog_compiler_c_o_GCJ \ fix_srcfile_path_GCJ \ exclude_expsyms_GCJ \ include_expsyms_GCJ; do case $var in old_archive_cmds_GCJ | \ old_archive_from_new_cmds_GCJ | \ archive_cmds_GCJ | \ archive_expsym_cmds_GCJ | \ module_cmds_GCJ | \ module_expsym_cmds_GCJ | \ old_archive_from_expsyms_cmds_GCJ | \ export_symbols_cmds_GCJ | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_GCJ # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_GCJ # Is the compiler the GNU C compiler? with_gcc=$GCC_GCJ # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_GCJ # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_GCJ # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_GCJ pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_GCJ # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_GCJ old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_GCJ archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_GCJ module_expsym_cmds=$lt_module_expsym_cmds_GCJ # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_GCJ # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_GCJ # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_GCJ # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_GCJ # The directories searched by this compiler when creating a shared # library compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_GCJ # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_GCJ # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_GCJ # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_GCJ # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_GCJ # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_GCJ # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_GCJ # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_GCJ # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_GCJ # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_GCJ # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_GCJ # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_GCJ # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; RC) # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o objext_RC=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $rm -r conftest* # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${RC-"windres"} compiler=$CC compiler_RC=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` lt_cv_prog_compiler_c_o_RC=yes # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_RC \ CC_RC \ LD_RC \ lt_prog_compiler_wl_RC \ lt_prog_compiler_pic_RC \ lt_prog_compiler_static_RC \ lt_prog_compiler_no_builtin_flag_RC \ export_dynamic_flag_spec_RC \ thread_safe_flag_spec_RC \ whole_archive_flag_spec_RC \ enable_shared_with_static_runtimes_RC \ old_archive_cmds_RC \ old_archive_from_new_cmds_RC \ predep_objects_RC \ postdep_objects_RC \ predeps_RC \ postdeps_RC \ compiler_lib_search_path_RC \ compiler_lib_search_dirs_RC \ archive_cmds_RC \ archive_expsym_cmds_RC \ postinstall_cmds_RC \ postuninstall_cmds_RC \ old_archive_from_expsyms_cmds_RC \ allow_undefined_flag_RC \ no_undefined_flag_RC \ export_symbols_cmds_RC \ hardcode_libdir_flag_spec_RC \ hardcode_libdir_flag_spec_ld_RC \ hardcode_libdir_separator_RC \ hardcode_automatic_RC \ module_cmds_RC \ module_expsym_cmds_RC \ lt_cv_prog_compiler_c_o_RC \ fix_srcfile_path_RC \ exclude_expsyms_RC \ include_expsyms_RC; do case $var in old_archive_cmds_RC | \ old_archive_from_new_cmds_RC | \ archive_cmds_RC | \ archive_expsym_cmds_RC | \ module_cmds_RC | \ module_expsym_cmds_RC | \ old_archive_from_expsyms_cmds_RC | \ export_symbols_cmds_RC | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_RC # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # LTCC compiler flags. LTCFLAGS=$lt_LTCFLAGS # A language-specific compiler. CC=$lt_compiler_RC # Is the compiler the GNU C compiler? with_gcc=$GCC_RC # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_RC # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$lt_STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_RC # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext_cmds='$shrext_cmds' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_RC pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC # Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_RC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_RC old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_RC archive_expsym_cmds=$lt_archive_expsym_cmds_RC postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_RC module_expsym_cmds=$lt_module_expsym_cmds_RC # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_RC # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_RC # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_RC # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_RC # The directories searched by this compiler when creating a shared # library compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_RC # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_RC # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_RC # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_RC # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_RC # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_RC # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_RC # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_RC # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_RC # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_RC # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_RC # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_RC # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_RC # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_RC # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` if test -f "$ltmain_in"; then test -f Makefile && make "$ltmain" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ;; *) { { $as_echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 $as_echo "$as_me: error: Unsupported tag name: $tagname" >&2;} { (exit 1); exit 1; }; } ;; esac # Append the new tag name to the list of available tags. if test -n "$tagname" ; then available_tags="$available_tags $tagname" fi fi done IFS="$lt_save_ifs" # Now substitute the updated list of available tags. if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then mv "${ofile}T" "$ofile" chmod +x "$ofile" else rm -f "${ofile}T" { { $as_echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 $as_echo "$as_me: error: unable to update list of available tagged configurations." >&2;} { (exit 1); exit 1; }; } fi fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' # Prevent multiple expansion if test "x$CC" != xcc; then { $as_echo "$as_me:$LINENO: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:$LINENO: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -f conftest2.$ac_objext && { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -f conftest2.$ac_objext && { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } cat >>confdefs.h <<\_ACEOF #define NO_MINUS_C_MINUS_O 1 _ACEOF fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC ac_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi for ac_func in bcmp srand48 drand48 do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 $as_echo_n "checking for $ac_func... " >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then eval "$as_ac_var=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test x$with_gui = xtrue; then if test x${WX_CONFIG_NAME+set} != xset ; then WX_CONFIG_NAME=wx-config fi if test "x$wx_config_name" != x ; then WX_CONFIG_NAME="$wx_config_name" fi if test x$wx_config_exec_prefix != x ; then wx_config_args="$wx_config_args --exec-prefix=$wx_config_exec_prefix" WX_LOOKUP_PATH="$wx_config_exec_prefix/bin" fi if test x$wx_config_prefix != x ; then wx_config_args="$wx_config_args --prefix=$wx_config_prefix" WX_LOOKUP_PATH="$WX_LOOKUP_PATH:$wx_config_prefix/bin" fi if test "$cross_compiling" = "yes"; then wx_config_args="$wx_config_args --host=$host_alias" fi if test -x "$WX_CONFIG_NAME" ; then { $as_echo "$as_me:$LINENO: checking for wx-config" >&5 $as_echo_n "checking for wx-config... " >&6; } WX_CONFIG_PATH="$WX_CONFIG_NAME" { $as_echo "$as_me:$LINENO: result: $WX_CONFIG_PATH" >&5 $as_echo "$WX_CONFIG_PATH" >&6; } else # Extract the first word of "$WX_CONFIG_NAME", so it can be a program name with args. set dummy $WX_CONFIG_NAME; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_WX_CONFIG_PATH+set}" = set; then $as_echo_n "(cached) " >&6 else case $WX_CONFIG_PATH in [\\/]* | ?:[\\/]*) ac_cv_path_WX_CONFIG_PATH="$WX_CONFIG_PATH" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy=""$WX_LOOKUP_PATH:$PATH"" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_WX_CONFIG_PATH="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_WX_CONFIG_PATH" && ac_cv_path_WX_CONFIG_PATH="no" ;; esac fi WX_CONFIG_PATH=$ac_cv_path_WX_CONFIG_PATH if test -n "$WX_CONFIG_PATH"; then { $as_echo "$as_me:$LINENO: result: $WX_CONFIG_PATH" >&5 $as_echo "$WX_CONFIG_PATH" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test "$WX_CONFIG_PATH" != "no" ; then WX_VERSION="" min_wx_version=2.6.0 if test -z "" ; then { $as_echo "$as_me:$LINENO: checking for wxWidgets version >= $min_wx_version" >&5 $as_echo_n "checking for wxWidgets version >= $min_wx_version... " >&6; } else { $as_echo "$as_me:$LINENO: checking for wxWidgets version >= $min_wx_version ()" >&5 $as_echo_n "checking for wxWidgets version >= $min_wx_version ()... " >&6; } fi WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args " WX_VERSION=`$WX_CONFIG_WITH_ARGS --version 2>/dev/null` wx_config_major_version=`echo $WX_VERSION | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` wx_config_minor_version=`echo $WX_VERSION | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` wx_config_micro_version=`echo $WX_VERSION | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` wx_requested_major_version=`echo $min_wx_version | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` wx_requested_minor_version=`echo $min_wx_version | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` wx_requested_micro_version=`echo $min_wx_version | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` wx_ver_ok="" if test "x$WX_VERSION" != x ; then if test $wx_config_major_version -gt $wx_requested_major_version; then wx_ver_ok=yes else if test $wx_config_major_version -eq $wx_requested_major_version; then if test $wx_config_minor_version -gt $wx_requested_minor_version; then wx_ver_ok=yes else if test $wx_config_minor_version -eq $wx_requested_minor_version; then if test $wx_config_micro_version -ge $wx_requested_micro_version; then wx_ver_ok=yes fi fi fi fi fi fi if test -n "$wx_ver_ok"; then { $as_echo "$as_me:$LINENO: result: yes (version $WX_VERSION)" >&5 $as_echo "yes (version $WX_VERSION)" >&6; } WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs` { $as_echo "$as_me:$LINENO: checking for wxWidgets static library" >&5 $as_echo_n "checking for wxWidgets static library... " >&6; } WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs 2>/dev/null` if test "x$WX_LIBS_STATIC" = "x"; then { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } fi wx_has_cppflags="" if test $wx_config_major_version -gt 2; then wx_has_cppflags=yes else if test $wx_config_major_version -eq 2; then if test $wx_config_minor_version -gt 2; then wx_has_cppflags=yes else if test $wx_config_minor_version -eq 2; then if test $wx_config_micro_version -ge 6; then wx_has_cppflags=yes fi fi fi fi fi wx_has_rescomp="" if test $wx_config_major_version -gt 2; then wx_has_rescomp=yes else if test $wx_config_major_version -eq 2; then if test $wx_config_minor_version -ge 7; then wx_has_rescomp=yes fi fi fi if test "x$wx_has_rescomp" = x ; then WX_RESCOMP= else WX_RESCOMP=`$WX_CONFIG_WITH_ARGS --rescomp` fi if test "x$wx_has_cppflags" = x ; then WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags` WX_CPPFLAGS=$WX_CFLAGS WX_CXXFLAGS=$WX_CFLAGS WX_CFLAGS_ONLY=$WX_CFLAGS WX_CXXFLAGS_ONLY=$WX_CFLAGS else WX_CPPFLAGS=`$WX_CONFIG_WITH_ARGS --cppflags` WX_CXXFLAGS=`$WX_CONFIG_WITH_ARGS --cxxflags` WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags` WX_CFLAGS_ONLY=`echo $WX_CFLAGS | sed "s@^$WX_CPPFLAGS *@@"` WX_CXXFLAGS_ONLY=`echo $WX_CXXFLAGS | sed "s@^$WX_CFLAGS *@@"` fi WXCONFIG=1 else if test "x$WX_VERSION" = x; then { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:$LINENO: result: no (version $WX_VERSION is not new enough)" >&5 $as_echo "no (version $WX_VERSION is not new enough)" >&6; } fi WX_CFLAGS="" WX_CPPFLAGS="" WX_CXXFLAGS="" WX_LIBS="" WX_LIBS_STATIC="" WX_RESCOMP="" : fi else WX_CFLAGS="" WX_CPPFLAGS="" WX_CXXFLAGS="" WX_LIBS="" WX_LIBS_STATIC="" WX_RESCOMP="" : fi if test "$WXCONFIG" != 1; then { $as_echo "$as_me:$LINENO: WARNING: Did not find a new enough version of wxWidgets; disabling build of graphical interface. If you want to build the graphical interface, please check that wx-config is in path, the directory where wxWidgets libraries are installed (returned by 'wx-config --libs' command) is in LD_LIBRARY_PATH or equivalent variable and wxWidgets is version 2.6.0 or above. " >&5 $as_echo "$as_me: WARNING: Did not find a new enough version of wxWidgets; disabling build of graphical interface. If you want to build the graphical interface, please check that wx-config is in path, the directory where wxWidgets libraries are installed (returned by 'wx-config --libs' command) is in LD_LIBRARY_PATH or equivalent variable and wxWidgets is version 2.6.0 or above. " >&2;} GUI_PROGS="" WITH_GUI=0 fi fi if test "${WITH_GUI}" == 1; then { $as_echo "$as_me:$LINENO: checking for wxWidgets port" >&5 $as_echo_n "checking for wxWidgets port... " >&6; } if test `echo ${WX_CXXFLAGS} | grep -c __WXX11__` -eq 1; then { $as_echo "$as_me:$LINENO: result: universal" >&5 $as_echo "universal" >&6; } { $as_echo "$as_me:$LINENO: WARNING: Found universal port of wxWidgets; disabling build of graphical interface. The graphical interface cannot be built with this port because this port does not implement drag-and-drop capability. Gambit recommends the GTK port of wxWidgets for best results. " >&5 $as_echo "$as_me: WARNING: Found universal port of wxWidgets; disabling build of graphical interface. The graphical interface cannot be built with this port because this port does not implement drag-and-drop capability. Gambit recommends the GTK port of wxWidgets for best results. " >&2;} GUI_PROGS="" fi if test `echo ${WX_CXXFLAGS} | grep -c __WXMOTIF__` -eq 1; then { $as_echo "$as_me:$LINENO: result: Motif" >&5 $as_echo "Motif" >&6; } { $as_echo "$as_me:$LINENO: WARNING: Found Motif port of wxWidgets; disabling build of graphical interface. The graphical interface cannot be built with this port because this port does not implement drag-and-drop capability. Gambit recommends the GTK port of wxWidgets for best results. " >&5 $as_echo "$as_me: WARNING: Found Motif port of wxWidgets; disabling build of graphical interface. The graphical interface cannot be built with this port because this port does not implement drag-and-drop capability. Gambit recommends the GTK port of wxWidgets for best results. " >&2;} GUI_PROGS="" fi if test `echo ${WX_CXXFLAGS} | grep -c __WXGTK__` -eq 1; then { $as_echo "$as_me:$LINENO: result: GTK" >&5 $as_echo "GTK" >&6; } WXPORT="GTK" GUI_PROGS="gambit" fi if test `echo ${WX_CXXFLAGS} | grep -c __WXMSW__` -eq 1; then { $as_echo "$as_me:$LINENO: result: Windows" >&5 $as_echo "Windows" >&6; } WXPORT="MSW" GUI_PROGS="gambit" RC_OBJECT="gambitrc.o" RC_OBJECT_PATH="bitmaps/gambitrc.o" fi if test `echo ${WX_CXXFLAGS} | grep -c __WXMAC__` -eq 1; then { $as_echo "$as_me:$LINENO: result: Macintosh" >&5 $as_echo "Macintosh" >&6; } WXPORT="MAC" GUI_PROGS="gambit" fi if test -z "$WXPORT"; then { $as_echo "$as_me:$LINENO: WARNING: Could not identify wxWidgets port. Disabling build of Gambit graphical interface. " >&5 $as_echo "$as_me: WARNING: Could not identify wxWidgets port. Disabling build of Gambit graphical interface. " >&2;} GUI_PROGS="" fi fi REZFLAGS=`echo $CXXFLAGS $WX_CXXFLAGS | sed 's/-mthreads//g' | sed 's/-g//g' | sed 's/-O. / /g' | sed 's/-I/--include-dir /g'` ac_config_files="$ac_config_files Makefile contrib/Makefile contrib/scripts/Makefile contrib/scripts/enumpoly/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${WITH_GUI_TRUE}" && test -z "${WITH_GUI_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"WITH_GUI\" was never defined. Usually this means the macro was only invoked conditionally." >&5 $as_echo "$as_me: error: conditional \"WITH_GUI\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${WITH_ENUMPOLY_TRUE}" && test -z "${WITH_ENUMPOLY_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"WITH_ENUMPOLY\" was never defined. Usually this means the macro was only invoked conditionally." >&5 $as_echo "$as_me: error: conditional \"WITH_ENUMPOLY\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 $as_echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 $as_echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 $as_echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by gambit $as_me 0.2010.09.01, which was generated by GNU Autoconf 2.63. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTION]... [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ gambit config.status 0.2010.09.01 configured by $0, generated by GNU Autoconf 2.63, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2008 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac CONFIG_FILES="$CONFIG_FILES '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { $as_echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; "contrib/scripts/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/scripts/Makefile" ;; "contrib/scripts/enumpoly/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/scripts/enumpoly/Makefile" ;; *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 $as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { $as_echo "$as_me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=' ' ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 $as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 $as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 $as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\).*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\).*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5 $as_echo "$as_me: error: could not setup config files machinery" >&2;} { (exit 1); exit 1; }; } _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: invalid tag $ac_tag" >&5 $as_echo "$as_me: error: invalid tag $ac_tag" >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { $as_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 $as_echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac ac_file_inputs="$ac_file_inputs '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:$LINENO: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 $as_echo "$as_me: error: could not create $ac_file" >&2;} { (exit 1); exit 1; }; } ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 $as_echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 $as_echo "$as_me: error: could not create $ac_file" >&2;} { (exit 1); exit 1; }; } test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 $as_echo "$as_me: error: could not create $ac_file" >&2;} { (exit 1); exit 1; }; } ;; :C) { $as_echo "$as_me:$LINENO: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir=$dirpart/$fdir case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 $as_echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5 $as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:$LINENO: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi gambit-0.2010.09.01/configure.in0000644000076500007650000001260111441453517012756 00000000000000dnl dnl This file is part of Gambit dnl Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) dnl dnl FILE: configure.in dnl autoconf configuration script for Gambit dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. dnl AC_INIT([gambit], [0.2010.09.01]) AC_CONFIG_SRCDIR([src/libgambit/libgambit.h]) AM_INIT_AUTOMAKE([subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) AM_OPTIONS_WXCONFIG dnl AM_CONFIG_HEADER(config.h) dnl User-specified options dnl By default, we build the GUI AC_ARG_ENABLE(gui, [ --disable-gui don't build graphical interface ], [ case "${enableval}" in yes) with_gui=true ;; no) with_gui=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-gui) ;; esac], [with_gui=true]) AM_CONDITIONAL(WITH_GUI, test x$with_gui = xtrue) dnl Disable building enumpoly -- isn't supported on 64-bit platforms AC_ARG_ENABLE(enumpoly, [ --disable-enumpoly don't build gambit-enumpoly (not supported on 64bit) ], [ case "${enableval}" in yes) with_enumpoly=true ;; no) with_enumpoly=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-enumpoly) ;; esac], [with_enumpoly=true]) AM_CONDITIONAL(WITH_ENUMPOLY, test x$with_enumpoly = xtrue) dnl Checks for programs. AC_PROG_CC AC_PROG_CXX AC_PROG_LIBTOOL AM_PROG_CC_C_O dnl A number of the following checks are currently commented out. dnl These are checks for functions and headers we do actually use, dnl but for which we don't have any workarounds should they be missing. dnl Checks for header files. dnl AC_HEADER_STDC dnl AC_CHECK_HEADERS(fcntl.h limits.h malloc.h sys/time.h unistd.h) dnl Checks for typedefs, structures, and compiler characteristics. dnl AC_C_CONST dnl AC_C_INLINE dnl AC_TYPE_PID_T dnl AC_TYPE_SIZE_T dnl AC_STRUCT_TM dnl Checks for library functions. dnl AC_FUNC_MEMCMP dnl AC_TYPE_SIGNAL dnl AC_CHECK_FUNCS(ftime putenv strdup strstr strtod strtol) AC_CHECK_FUNCS(bcmp srand48 drand48) if test x$with_gui = xtrue; then dnl------------------------ dnl Checking for wxWidgets dnl------------------------ dnl check for wx-config AM_PATH_WXCONFIG(2.6.0, WXCONFIG=1) if test "$WXCONFIG" != 1; then AC_MSG_WARN([ Did not find a new enough version of wxWidgets; disabling build of graphical interface. If you want to build the graphical interface, please check that wx-config is in path, the directory where wxWidgets libraries are installed (returned by 'wx-config --libs' command) is in LD_LIBRARY_PATH or equivalent variable and wxWidgets is version 2.6.0 or above. ]) GUI_PROGS="" WITH_GUI=0 fi fi if test "${WITH_GUI}" == 1; then dnl----------------------------- dnl Checking for wxWidgets port dnl----------------------------- AC_MSG_CHECKING(for wxWidgets port) if test `echo ${WX_CXXFLAGS} | grep -c __WXX11__` -eq 1; then AC_MSG_RESULT(universal) AC_MSG_WARN([ Found universal port of wxWidgets; disabling build of graphical interface. The graphical interface cannot be built with this port because this port does not implement drag-and-drop capability. Gambit recommends the GTK port of wxWidgets for best results. ]) GUI_PROGS="" fi if test `echo ${WX_CXXFLAGS} | grep -c __WXMOTIF__` -eq 1; then AC_MSG_RESULT(Motif) AC_MSG_WARN([ Found Motif port of wxWidgets; disabling build of graphical interface. The graphical interface cannot be built with this port because this port does not implement drag-and-drop capability. Gambit recommends the GTK port of wxWidgets for best results. ]) GUI_PROGS="" fi if test `echo ${WX_CXXFLAGS} | grep -c __WXGTK__` -eq 1; then AC_MSG_RESULT(GTK) WXPORT="GTK" GUI_PROGS="gambit" fi if test `echo ${WX_CXXFLAGS} | grep -c __WXMSW__` -eq 1; then AC_MSG_RESULT(Windows) WXPORT="MSW" GUI_PROGS="gambit" dnl Windows uses the resources file RC_OBJECT="gambitrc.o" RC_OBJECT_PATH="bitmaps/gambitrc.o" AC_SUBST(RC_OBJECT) AC_SUBST(RC_OBJECT_PATH) fi if test `echo ${WX_CXXFLAGS} | grep -c __WXMAC__` -eq 1; then AC_MSG_RESULT(Macintosh) WXPORT="MAC" GUI_PROGS="gambit" fi if test -z "$WXPORT"; then AC_MSG_WARN([ Could not identify wxWidgets port. Disabling build of Gambit graphical interface. ]) GUI_PROGS="" fi fi AC_SUBST(GUI_PROGS) AC_SUBST(WX_CXXFLAGS) AC_SUBST(WX_LIBS) AC_SUBST(ENUMPOLY_PROGS) REZFLAGS=`echo $CXXFLAGS $WX_CXXFLAGS | sed 's/-mthreads//g' | sed 's/-g//g' | sed 's/-O. / /g' | sed 's/-I/--include-dir /g'` AC_SUBST(REZFLAGS) AC_OUTPUT(Makefile contrib/Makefile contrib/scripts/Makefile contrib/scripts/enumpoly/Makefile) gambit-0.2010.09.01/contrib/0000777000076500007650000000000011441457133012167 500000000000000gambit-0.2010.09.01/contrib/games/0000777000076500007650000000000011441457132013262 500000000000000gambit-0.2010.09.01/contrib/games/2s2x2x2.efg0000644000076500007650000000205011350032206014776 00000000000000EFG 2 R "Two stage McKelvey McLennan game with 9 equilibria each stage" { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "Infoset2" { "U1" "D1" } 0 p "" 2 1 ":1" { "U2" "D2" } 0 p "" 3 1 ":1" { "U3" "D3" } 0 p "" 1 2 "" { "U1" "D1" } 1 "Outcome 2" { 9, 8, 12 } p "" 2 2 "Infoset3" { "U2" "D2" } 0 p "" 3 2 "Infoset3" { "U3" "D3" } 0 t "" 1 "Outcome 2" { 9, 8, 12 } t "" 2 "Outcome 1" { 0, 0, 0 } p "" 3 2 "Infoset3" { "U3" "D3" } 0 t "" 2 "Outcome 1" { 0, 0, 0 } t "" 3 "Outcome 4" { 3, 4, 6 } p "" 2 2 "Infoset3" { "U2" "D2" } 0 p "" 3 2 "Infoset3" { "U3" "D3" } 0 t "" 2 "Outcome 1" { 0, 0, 0 } t "" 3 "Outcome 4" { 3, 4, 6 } p "" 3 2 "Infoset3" { "U3" "D3" } 0 t "" 4 "Outcome 3" { 9, 8, 2 } t "" 2 "Outcome 1" { 0, 0, 0 } t "" 2 "Outcome 1" { 0, 0, 0 } p "" 3 1 ":1" { "U3" "D3" } 0 t "" 2 "Outcome 1" { 0, 0, 0 } t "" 3 "Outcome 4" { 3, 4, 6 } p "" 2 1 ":1" { "U2" "D2" } 0 p "" 3 1 ":1" { "U3" "D3" } 0 t "" 2 "Outcome 1" { 0, 0, 0 } t "" 3 "Outcome 4" { 3, 4, 6 } p "" 3 1 ":1" { "U3" "D3" } 0 t "" 4 "Outcome 3" { 9, 8, 2 } t "" 2 "Outcome 1" { 0, 0, 0 } gambit-0.2010.09.01/contrib/games/2smp.efg0000644000076500007650000000170411350032206014532 00000000000000EFG 2 R "Two-stage matching pennies game" { "Player 1" "Player 2" } "" p "" 1 1 "" { "H" "T" } 0 p "" 2 1 "" { "H" "T" } 0 p "" 1 2 "" { "H" "T" } 1 "Match" { 1, -1 } p "" 2 2 "" { "H" "T" } 0 t "" 1 "Match" { 1, -1 } t "" 2 "Mismatch" { -1, 1 } p "" 2 2 "" { "H" "T" } 0 t "" 2 "Mismatch" { -1, 1 } t "" 1 "Match" { 1, -1 } p "" 1 3 "" { "H" "T" } 2 "Mismatch" { -1, 1 } p "" 2 3 "" { "H" "T" } 0 t "" 1 "Match" { 1, -1 } t "" 2 "Mismatch" { -1, 1 } p "" 2 3 "" { "H" "T" } 0 t "" 2 "Mismatch" { -1, 1 } t "" 1 "Match" { 1, -1 } p "" 2 1 "" { "H" "T" } 0 p "" 1 4 "" { "H" "T" } 2 "Mismatch" { -1, 1 } p "" 2 4 "" { "H" "T" } 0 t "" 1 "Match" { 1, -1 } t "" 2 "Mismatch" { -1, 1 } p "" 2 4 "" { "H" "T" } 0 t "" 2 "Mismatch" { -1, 1 } t "" 1 "Match" { 1, -1 } p "" 1 5 "" { "H" "T" } 1 "Match" { 1, -1 } p "" 2 5 "" { "H" "T" } 0 t "" 1 "Match" { 1, -1 } t "" 2 "Mismatch" { -1, 1 } p "" 2 5 "" { "H" "T" } 0 t "" 2 "Mismatch" { -1, 1 } t "" 1 "Match" { 1, -1 } gambit-0.2010.09.01/contrib/games/2x2.nfg0000644000076500007650000000026611350032206014277 00000000000000NFG 1 R "Two person 2 x 2 game with unique mixed equilibrium" { "Player 1" "Player 2" } { { "1" "2" } { "1" "2" } } "" { { "" 2, 0 } { "" 0, 1 } { "" 0, 1 } { "" 1, 0 } } 1 2 3 4 gambit-0.2010.09.01/contrib/games/2x2a.nfg0000644000076500007650000000026611350032206014440 00000000000000NFG 1 R "Two person 2 x 2 game with unique mixed equilibrium" { "Player 1" "Player 2" } { { "U" "D" } { "L" "R" } } "" { { "" 9, 0 } { "" 0, 1 } { "" 0, 1 } { "" 1, 0 } } 1 2 3 4 gambit-0.2010.09.01/contrib/games/2x2const.nfg0000644000076500007650000000027011350032206015341 00000000000000NFG 1 R "2 x 2 constant sum game with unique mixed equilibrium" { "Player 1" "Player 2" } { { "1" "2" } { "1" "2" } } "" { { "" 2, 0 } { "" 0, 2 } { "" 0, 2 } { "" 1, 1 } } 1 2 3 4 gambit-0.2010.09.01/contrib/games/2x2x2.efg0000644000076500007650000000102711350032206014534 00000000000000EFG 2 R "McKelvey McLennan game with 9 equilibria, 2 totally mixed" { "Player 1" "Player 2" "Player 3" } p "" 1 1 "" { "U1" "D1" } 0 p "" 2 1 "" { "U2" "D2" } 0 p "" 3 1 "" { "U3" "D3" } 0 t "" 1 "Outcome 2" { 9 8 12 } t "" 2 "Outcome 1" { 0 0 0 } p "" 3 1 "" { "U3" "D3" } 0 t "" 2 "Outcome 1" { 0 0 0 } t "" 4 "Outcome 4" { 3 4 6 } p "" 2 1 "" { "U2" "D2" } 0 p "" 3 1 "" { "U3" "D3" } 0 t "" 2 "Outcome 1" { 0 0 0 } t "" 4 "Outcome 4" { 3 4 6 } p "" 3 1 "" { "U3" "D3" } 0 t "" 3 "Outcome 3" { 9 8 2 } t "" 2 "Outcome 1" { 0 0 0 } gambit-0.2010.09.01/contrib/games/2x2x2.nfg0000644000076500007650000000047011350032206014546 00000000000000NFG 1 R "2x2x2 Example from McKelvey-McLennan, with 9 Nash equilibria, 2 totally mixed" { "Player 1" "Player 2" "Player 3" } { { "1" "2" } { "1" "2" } { "1" "2" } } "" { { "" 9, 8, 12 } { "" 0, 0, 0 } { "" 0, 0, 0 } { "" 9, 8, 2 } { "" 0, 0, 0 } { "" 3, 4, 6 } { "" 3, 4, 6 } { "" 0, 0, 0 } } 1 2 3 4 5 6 7 8 gambit-0.2010.09.01/contrib/games/2x2x2x2.nfg0000644000076500007650000000132411350032206015017 00000000000000NFG 1 R "Four person, 2x2x2x2 game with 3 Nash equilibria" { "1" "2" "3" "4" } { { "1" "2" } { "1" "2" } { "1" "2" } { "1" "2" } } "" { { "" 1.131, 1.210, 2.426, 2.429 } { "" 4.225, 5.277, 4.837, 5.645 } { "" 4.452, 4.549, 1.655, 1.347 } { "" 7.566, 4.655, 7.076, 4.423 } { "" 1.223, 1.358, 2.234, 2.238 } { "" 4.483, 5.764, 4.995, 5.754 } { "" 4.564, 4.326, 1.762, 1.576 } { "" 7.247, 4.943, 7.362, 4.382 } { "" 2.326, 2.422, 3.222, 3.024 } { "" 1.478, 2.544, 1.973, 7.486 } { "" 2.747, 2.243, 3.518, 3.062 } { "" 1.759, 2.705, 1.735, 4.043 } { "" 5.255, 5.334, 2.643, 2.873 } { "" 4.383, 1.436, 4.864, 5.267 } { "" 5.634, 5.675, 2.455, 6.523 } { "" 4.642, 1.897, 4.042, 3.830 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 gambit-0.2010.09.01/contrib/games/2x2x2x2x2.nfg0000644000076500007650000000402611350032206015273 00000000000000NFG 1 R "Five person 2x2x2x2x2 game with five equilibria" { "Player 1" "Player 2" "Player 3" "Player 4" "Player 5" } { { "1" "2" } { "1" "2" } { "1" "2" } { "1" "2" } { "1" "2" } } "" { { "" 7.247000, 7.362000, 4.642000, 4.042000, 4.225000 } { "" 2.537000, 1.427000, 4.542000, 7.577000, 2.236000 } { "" 1.223000, 2.234000, 5.255000, 2.643000, 4.564000 } { "" 2.675000, 1.132000, 5.369000, 4.669000, 1.131000 } { "" 1.759000, 1.735000, 4.452000, 1.655000, 2.747000 } { "" 2.778000, 2.342000, 2.164000, 2.243000, 1.473000 } { "" 4.120000, 7.324000, 4.483000, 4.995000, 4.383000 } { "" 2.747000, 3.518000, 1.223000, 2.234000, 5.255000 } { "" 4.837000, 1.478000, 1.973000, 7.566000, 7.076000 } { "" 2.355000, 2.798000, 2.832000, 3.974000, 3.575000 } { "" 1.762000, 5.634000, 2.455000, 1.335000, 4.434000 } { "" 2.426000, 2.326000, 3.222000, 4.452000, 1.655000 } { "" 3.518000, 1.131000, 2.426000, 2.326000, 3.222000 } { "" 1.740000, 3.803000, 3.464000, 1.323000, 1.214000 } { "" 4.864000, 1.428000, 4.248000, 5.231000, 4.486000 } { "" 2.643000, 4.564000, 1.762000, 5.634000, 2.455000 } { "" 4.943000, 4.382000, 1.897000, 3.830000, 5.277000 } { "" 2.417000, 1.624000, 4.572000, 7.969000, 5.174000 } { "" 1.358000, 2.238000, 5.334000, 2.873000, 4.326000 } { "" 2.238000, 1.985000, 5.395000, 4.274000, 1.210000 } { "" 2.705000, 4.043000, 4.549000, 1.347000, 2.243000 } { "" 1.646000, 1.640000, 5.349000, 5.056000, 4.580000 } { "" 4.976000, 7.723000, 5.764000, 5.754000, 1.436000 } { "" 2.243000, 3.062000, 1.358000, 2.238000, 5.334000 } { "" 5.645000, 2.544000, 7.486000, 4.655000, 4.423000 } { "" 5.347000, 1.403000, 1.380000, 2.793000, 2.269000 } { "" 1.576000, 5.675000, 6.523000, 1.734000, 4.271000 } { "" 2.429000, 2.422000, 3.024000, 4.549000, 1.347000 } { "" 3.062000, 1.210000, 2.429000, 2.422000, 3.024000 } { "" 4.192000, 2.685000, 2.678000, 4.792000, 4.462000 } { "" 5.267000, 1.521000, 4.533000, 5.458000, 4.882000 } { "" 2.873000, 4.326000, 1.576000, 5.675000, 6.523000 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 gambit-0.2010.09.01/contrib/games/3x3x3.nfg0000644000076500007650000000227111350032206014552 00000000000000NFG 1 R "Three person 3x3x3 game with five equilibria (two pure)" { "Player 1" "Player 2" "Player 3" } { { "1" "2" "3" } { "1" "2" "3" } { "1" "2" "3" } } "" { { "" 1.131000, 1.210000, 2.426000 } { "" 1.358000, 2.234000, 2.238000 } { "" 1.655000, 1.347000, 2.747000 } { "" 1.576000, 5.634000, 5.675000 } { "" 1.478000, 2.544000, 1.973000 } { "" 1.436000, 4.864000, 5.267000 } { "" 1.735000, 4.043000, 7.247000 } { "" 3.830000, 1.335000, 1.734000 } { "" 1.428000, 1.521000, 4.248000 } { "" 2.429000, 2.326000, 2.422000 } { "" 5.255000, 5.334000, 2.643000 } { "" 2.243000, 3.518000, 3.062000 } { "" 2.455000, 6.523000, 4.225000 } { "" 7.486000, 4.483000, 5.764000 } { "" 7.566000, 4.655000, 7.076000 } { "" 4.943000, 7.362000, 4.382000 } { "" 4.434000, 4.271000, 4.120000 } { "" 4.533000, 5.231000, 5.458000 } { "" 3.222000, 3.024000, 1.223000 } { "" 2.873000, 4.452000, 4.549000 } { "" 4.564000, 4.326000, 1.762000 } { "" 5.277000, 4.837000, 5.645000 } { "" 4.995000, 5.754000, 4.383000 } { "" 4.423000, 1.759000, 2.705000 } { "" 4.642000, 1.897000, 4.042000 } { "" 4.976000, 7.324000, 7.723000 } { "" 4.486000, 4.882000, 2.537000 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 gambit-0.2010.09.01/contrib/games/4cards.efg0000644000076500007650000000730311350032206015032 00000000000000EFG 2 R "4 Card poker, from Alix Martin" { "Player 1" "Player 2" } "" c "" 1 "" { "A-K" 1/12 "A-Q" 1/12 "A-J" 1/12 "K-A" 1/12 "K-Q" 1/12 "K-J" 1/12 "Q-A" 1/12 "Q-K" 1/12 "Q-J" 1/12 "J-A" 1/12 "J-K" 1/12 "J-Q" 1/12 } 0 p "player 1" 1 1 "A" { "raise" "check" } 0 p "player 2" 2 1 "1rK" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 2 "Outcome 2" { 2, 0 } p "player 2" 2 2 "1pK" { "raise" "check" } 0 p "player 1" 1 2 "1p2rA" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 3 "Outcome 3" { 0, 2 } t "" 2 "Outcome 2" { 2, 0 } p "" 1 1 "A" { "raise" "check" } 0 p "player 2" 2 3 "1rQ" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 2 "Outcome 2" { 2, 0 } p "player 2" 2 4 "1pQ" { "raise" "check" } 0 p "" 1 2 "1p2rA" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 3 "Outcome 3" { 0, 2 } t "" 2 "Outcome 2" { 2, 0 } p "" 1 1 "A" { "raise" "check" } 0 p "player 2" 2 5 "1rJ" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 2 "Outcome 2" { 2, 0 } p "player 2" 2 6 "1pJ" { "raise" "check" } 0 p "" 1 2 "1p2rA" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 3 "Outcome 3" { 0, 2 } t "" 2 "Outcome 2" { 2, 0 } p "player 1" 1 3 "K" { "raise" "check" } 0 p "" 2 7 "1rA" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 2 "Outcome 2" { 2, 0 } p "player 2" 2 8 "1pA" { "raise" "check" } 0 p "player 1" 1 4 "1p2rK" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 3 "Outcome 3" { 0, 2 } t "" 3 "Outcome 3" { 0, 2 } p "" 1 3 "K" { "raise" "check" } 0 p "" 2 3 "1rQ" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 2 "Outcome 2" { 2, 0 } p "" 2 4 "1pQ" { "raise" "check" } 0 p "" 1 4 "1p2rK" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 3 "Outcome 3" { 0, 2 } t "" 2 "Outcome 2" { 2, 0 } p "" 1 3 "K" { "raise" "check" } 0 p "" 2 5 "1rJ" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 2 "Outcome 2" { 2, 0 } p "" 2 6 "1pJ" { "raise" "check" } 0 p "" 1 4 "1p2rK" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 3 "Outcome 3" { 0, 2 } t "" 2 "Outcome 2" { 2, 0 } p "player 1" 1 5 "Q" { "raise" "check" } 0 p "player 2" 2 7 "1rA" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 2 "Outcome 2" { 2, 0 } p "" 2 8 "1pA" { "raise" "check" } 0 p "player 1" 1 6 "1p2rQ" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 3 "Outcome 3" { 0, 2 } t "" 3 "Outcome 3" { 0, 2 } p "" 1 5 "Q" { "raise" "check" } 0 p "" 2 1 "1rK" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 2 "Outcome 2" { 2, 0 } p "" 2 2 "1pK" { "raise" "check" } 0 p "" 1 6 "1p2rQ" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 3 "Outcome 3" { 0, 2 } t "" 3 "Outcome 3" { 0, 2 } p "" 1 5 "Q" { "raise" "check" } 0 p "" 2 5 "1rJ" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 2 "Outcome 2" { 2, 0 } p "" 2 6 "1pJ" { "raise" "check" } 0 p "" 1 6 "1p2rQ" { "call" "fold" } 0 t "" 1 "Outcome 1" { 3, -1 } t "" 3 "Outcome 3" { 0, 2 } t "" 2 "Outcome 2" { 2, 0 } p "player 1" 1 7 "J" { "raise" "check" } 0 p "" 2 7 "1rA" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 2 "Outcome 2" { 2, 0 } p "" 2 8 "1pA" { "raise" "check" } 0 p "player 1" 1 8 "1p2rJ" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 3 "Outcome 3" { 0, 2 } t "" 3 "Outcome 3" { 0, 2 } p "" 1 7 "J" { "raise" "check" } 0 p "" 2 1 "1rK" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 2 "Outcome 2" { 2, 0 } p "" 2 2 "1pK" { "raise" "check" } 0 p "" 1 8 "1p2rJ" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 3 "Outcome 3" { 0, 2 } t "" 3 "Outcome 3" { 0, 2 } p "" 1 7 "J" { "raise" "check" } 0 p "" 2 3 "1rQ" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 2 "Outcome 2" { 2, 0 } p "" 2 4 "1pQ" { "raise" "check" } 0 p "" 1 8 "1p2rJ" { "call" "fold" } 0 t "" 4 "Outcome 4" { -1, 3 } t "" 3 "Outcome 3" { 0, 2 } t "" 3 "Outcome 3" { 0, 2 } gambit-0.2010.09.01/contrib/games/5x4x3.nfg0000644000076500007650000000466311350032206014564 00000000000000NFG 1 R "Three person random 5x4x3 game" { "Player 1" "Player 2" "Player 3" } { { "1" "2" "3" "4" "5" } { "1" "2" "3" "4" } { "1" "2" "3" } } "" { { "" 1.131000, 1.210000, 2.426000 } { "" 1.358000, 2.234000, 2.238000 } { "" 1.655000, 1.347000, 2.747000 } { "" 1.576000, 5.634000, 5.675000 } { "" 1.478000, 2.544000, 1.973000 } { "" 1.436000, 4.864000, 5.267000 } { "" 1.735000, 4.043000, 7.247000 } { "" 3.830000, 1.335000, 1.734000 } { "" 1.428000, 1.521000, 4.248000 } { "" 2.417000, 1.427000, 1.624000 } { "" 1.132000, 1.985000, 5.369000 } { "" 5.056000, 1.473000, 4.580000 } { "" 2.798000, 1.403000, 2.832000 } { "" 4.792000, 1.214000, 4.462000 } { "" 2.342000, 1.640000, 1.131000 } { "" 3.024000, 1.223000, 1.358000 } { "" 4.452000, 4.549000, 1.655000 } { "" 4.326000, 1.762000, 1.576000 } { "" 4.837000, 5.645000, 1.478000 } { "" 5.754000, 4.383000, 1.436000 } { "" 2.429000, 2.326000, 2.422000 } { "" 5.255000, 5.334000, 2.643000 } { "" 2.243000, 3.518000, 3.062000 } { "" 2.455000, 6.523000, 4.225000 } { "" 7.486000, 4.483000, 5.764000 } { "" 7.566000, 4.655000, 7.076000 } { "" 4.943000, 7.362000, 4.382000 } { "" 4.434000, 4.271000, 4.120000 } { "" 4.533000, 5.231000, 5.458000 } { "" 4.542000, 4.572000, 7.577000 } { "" 5.395000, 4.669000, 4.274000 } { "" 1.740000, 4.192000, 2.236000 } { "" 1.380000, 3.803000, 2.685000 } { "" 3.974000, 2.793000, 3.575000 } { "" 1.210000, 2.426000, 2.429000 } { "" 2.234000, 2.238000, 5.255000 } { "" 1.347000, 2.747000, 2.243000 } { "" 5.634000, 5.675000, 2.455000 } { "" 2.544000, 1.973000, 7.486000 } { "" 4.864000, 5.267000, 7.566000 } { "" 3.222000, 3.024000, 1.223000 } { "" 2.873000, 4.452000, 4.549000 } { "" 4.564000, 4.326000, 1.762000 } { "" 5.277000, 4.837000, 5.645000 } { "" 4.995000, 5.754000, 4.383000 } { "" 4.423000, 1.759000, 2.705000 } { "" 4.642000, 1.897000, 4.042000 } { "" 4.976000, 7.324000, 7.723000 } { "" 4.486000, 4.882000, 2.537000 } { "" 7.969000, 2.675000, 2.238000 } { "" 2.164000, 5.349000, 2.243000 } { "" 5.174000, 2.355000, 5.347000 } { "" 3.464000, 2.678000, 1.323000 } { "" 2.269000, 2.778000, 1.646000 } { "" 2.326000, 2.422000, 3.222000 } { "" 5.334000, 2.643000, 2.873000 } { "" 3.518000, 3.062000, 4.564000 } { "" 6.523000, 4.225000, 5.277000 } { "" 4.483000, 5.764000, 4.995000 } { "" 4.655000, 7.076000, 4.423000 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 gambit-0.2010.09.01/contrib/games/8x2x2.nfg0000644000076500007650000000255711350032206014564 00000000000000NFG 1 R "Three person random 8x2x2 game" { "Player 1" "Player 2" "Player 3" } { { "1" "2" "3" "4" "5" "6" "7" "8" } { "1" "2" } { "1" "2" } } "" { { "" 1.131000, 1.210000, 2.426000 } { "" 3.222000, 3.024000, 1.223000 } { "" 5.255000, 5.334000, 2.643000 } { "" 1.655000, 1.347000, 2.747000 } { "" 4.564000, 4.326000, 1.762000 } { "" 2.455000, 6.523000, 4.225000 } { "" 1.478000, 2.544000, 1.973000 } { "" 4.995000, 5.754000, 4.383000 } { "" 7.566000, 4.655000, 7.076000 } { "" 1.735000, 4.043000, 7.247000 } { "" 4.642000, 1.897000, 4.042000 } { "" 4.434000, 4.271000, 4.120000 } { "" 1.428000, 1.521000, 4.248000 } { "" 4.486000, 4.882000, 2.537000 } { "" 4.542000, 4.572000, 7.577000 } { "" 1.132000, 1.985000, 5.369000 } { "" 2.429000, 2.326000, 2.422000 } { "" 1.358000, 2.234000, 2.238000 } { "" 2.873000, 4.452000, 4.549000 } { "" 2.243000, 3.518000, 3.062000 } { "" 1.576000, 5.634000, 5.675000 } { "" 5.277000, 4.837000, 5.645000 } { "" 7.486000, 4.483000, 5.764000 } { "" 1.436000, 4.864000, 5.267000 } { "" 4.423000, 1.759000, 2.705000 } { "" 4.943000, 7.362000, 4.382000 } { "" 3.830000, 1.335000, 1.734000 } { "" 4.976000, 7.324000, 7.723000 } { "" 4.533000, 5.231000, 5.458000 } { "" 2.417000, 1.427000, 1.624000 } { "" 7.969000, 2.675000, 2.238000 } { "" 5.395000, 4.669000, 4.274000 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 gambit-0.2010.09.01/contrib/games/8x8.nfg0000644000076500007650000000373411350032206014316 00000000000000NFG 1 R "Random 8x8 game with 5 equilibria (3 pure)" { "Player 1" "Player 2" } { { "1" "2" "3" "4" "5" "6" "7" "8" } { "1" "2" "3" "4" "5" "6" "7" "8" } } "" { { "" 1.131000, 1.210000 } { "" 2.426000, 2.429000 } { "" 2.326000, 2.422000 } { "" 3.222000, 3.024000 } { "" 1.223000, 1.358000 } { "" 2.234000, 2.238000 } { "" 5.255000, 5.334000 } { "" 2.643000, 2.873000 } { "" 4.452000, 4.549000 } { "" 1.655000, 1.347000 } { "" 2.747000, 2.243000 } { "" 3.518000, 3.062000 } { "" 4.564000, 4.326000 } { "" 1.762000, 1.576000 } { "" 5.634000, 5.675000 } { "" 2.455000, 6.523000 } { "" 4.225000, 5.277000 } { "" 4.837000, 5.645000 } { "" 1.478000, 2.544000 } { "" 1.973000, 7.486000 } { "" 4.483000, 5.764000 } { "" 4.995000, 5.754000 } { "" 4.383000, 1.436000 } { "" 4.864000, 5.267000 } { "" 7.566000, 4.655000 } { "" 7.076000, 4.423000 } { "" 1.759000, 2.705000 } { "" 1.735000, 4.043000 } { "" 7.247000, 4.943000 } { "" 7.362000, 4.382000 } { "" 4.642000, 1.897000 } { "" 4.042000, 3.830000 } { "" 1.335000, 1.734000 } { "" 4.434000, 4.271000 } { "" 4.120000, 4.976000 } { "" 7.324000, 7.723000 } { "" 1.428000, 1.521000 } { "" 4.248000, 4.533000 } { "" 5.231000, 5.458000 } { "" 4.486000, 4.882000 } { "" 2.537000, 2.417000 } { "" 1.427000, 1.624000 } { "" 4.542000, 4.572000 } { "" 7.577000, 7.969000 } { "" 2.675000, 2.238000 } { "" 1.132000, 1.985000 } { "" 5.369000, 5.395000 } { "" 4.669000, 4.274000 } { "" 2.164000, 5.349000 } { "" 2.243000, 5.056000 } { "" 1.473000, 4.580000 } { "" 1.740000, 4.192000 } { "" 2.236000, 5.174000 } { "" 2.355000, 5.347000 } { "" 2.798000, 1.403000 } { "" 2.832000, 1.380000 } { "" 3.803000, 2.685000 } { "" 3.464000, 2.678000 } { "" 1.323000, 4.792000 } { "" 1.214000, 4.462000 } { "" 3.974000, 2.793000 } { "" 3.575000, 2.269000 } { "" 2.778000, 1.646000 } { "" 2.342000, 1.640000 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 gambit-0.2010.09.01/contrib/games/artist1.efg0000644000076500007650000000373611350032206015247 00000000000000EFG 2 R "Artist problem, one stage" { "Player 1" "Player 2" } "" c "ROOT" 1 "(0,1)" { "good" 1/2 "bad" 1/2 } 0 c "" 2 "(0,2)" { "G" 4/5 "B" 1/5 } 0 c "" 3 "(0,3)" { "g" 4/5 "b" 1/5 } 0 p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } c "" 4 "(0,4)" { "g" 4/5 "b" 1/5 } 0 p "" 1 2 "(1,2)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 2 "(1,2)" { "H" "L" } 0 p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } c "" 5 "(0,5)" { "G" 1/5 "B" 4/5 } 0 c "" 6 "(0,6)" { "g" 1/5 "b" 4/5 } 0 p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } c "" 7 "(0,7)" { "g" 1/5 "b" 4/5 } 0 p "" 1 2 "(1,2)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 2 "(1,2)" { "H" "L" } 0 p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } gambit-0.2010.09.01/contrib/games/artist2.efg0000644000076500007650000002053511350032206015244 00000000000000EFG 2 R "Artist problem, two stages" { "Player 1" "Player 2" } "" c "ROOT" 1 "(0,1)" { "good" 1/2 "bad" 1/2 } 0 c "" 2 "(0,2)" { "1G" 4/5 "1B" 1/5 } 0 c "" 3 "(0,3)" { "2g" 4/5 "2b" 1/5 } 0 p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 2 "(1,3)" { "H" "L" } 1 "Outcome 1" { 1/2, 1/2 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 3 "(1,4)" { "H" "L" } 2 "Outcome 2" { 3, 0 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 4 "(1,5)" { "H" "L" } 3 "Outcome 3" { 0, 3 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 5 "(1,6)" { "H" "L" } 4 "Outcome 4" { 3/2, 3/2 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 2 "(1,3)" { "H" "L" } 1 "Outcome 1" { 1/2, 1/2 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 3 "(1,4)" { "H" "L" } 2 "Outcome 2" { 3, 0 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 4 "(1,5)" { "H" "L" } 3 "Outcome 3" { 0, 3 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 5 "(1,6)" { "H" "L" } 4 "Outcome 4" { 3/2, 3/2 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } c "" 4 "(0,4)" { "2g" 4/5 "2b" 1/5 } 0 p "" 1 6 "(1,2)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 7 "(1,7)" { "H" "L" } 1 "Outcome 1" { 1/2, 1/2 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 8 "(1,8)" { "H" "L" } 2 "Outcome 2" { 3, 0 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 9 "(1,9)" { "H" "L" } 3 "Outcome 3" { 0, 3 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 10 "(1,10)" { "H" "L" } 4 "Outcome 4" { 3/2, 3/2 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 6 "(1,2)" { "H" "L" } 0 p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 7 "(1,7)" { "H" "L" } 1 "Outcome 1" { 1/2, 1/2 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 8 "(1,8)" { "H" "L" } 2 "Outcome 2" { 3, 0 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 9 "(1,9)" { "H" "L" } 3 "Outcome 3" { 0, 3 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } p "" 1 10 "(1,10)" { "H" "L" } 4 "Outcome 4" { 3/2, 3/2 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 3/2, 3/2 } c "" 5 "(0,5)" { "G" 1/5 "B" 4/5 } 0 c "" 6 "(0,6)" { "g" 1/5 "b" 4/5 } 0 p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 2 "(1,3)" { "H" "L" } 5 "Outcome 5" { -1, -1 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 3 "(1,4)" { "H" "L" } 6 "Outcome 6" { 0, 0 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 4 "(1,5)" { "H" "L" } 7 "Outcome 7" { 0, 0 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 5 "(1,6)" { "H" "L" } 8 "Outcome 8" { 0, 0 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 2 "(1,3)" { "H" "L" } 5 "Outcome 5" { -1, -1 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 3 "(1,4)" { "H" "L" } 6 "Outcome 6" { 0, 0 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 4 "(1,5)" { "H" "L" } 7 "Outcome 7" { 0, 0 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 5 "(1,6)" { "H" "L" } 8 "Outcome 8" { 0, 0 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } c "" 7 "(0,7)" { "g" 1/5 "b" 4/5 } 0 p "" 1 6 "(1,2)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 7 "(1,7)" { "H" "L" } 5 "Outcome 5" { -1, -1 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 8 "(1,8)" { "H" "L" } 6 "Outcome 6" { 0, 0 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 9 "(1,9)" { "H" "L" } 7 "Outcome 7" { 0, 0 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 10 "(1,10)" { "H" "L" } 8 "Outcome 8" { 0, 0 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 6 "(1,2)" { "H" "L" } 0 p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 7 "(1,7)" { "H" "L" } 5 "Outcome 5" { -1, -1 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 8 "(1,8)" { "H" "L" } 6 "Outcome 6" { 0, 0 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 9 "(1,9)" { "H" "L" } 7 "Outcome 7" { 0, 0 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } p "" 1 10 "(1,10)" { "H" "L" } 8 "Outcome 8" { 0, 0 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 0, 0 } gambit-0.2010.09.01/contrib/games/badgame1.efg0000644000076500007650000000034111350032206015306 00000000000000EFG 2 R "Agent Nash not Player Nash" { "Player 1" "Player 2" } "" p "" 1 1 "" { "A" "B" } 0 t "" 1 "" { 2, 0 } p "" 1 2 "" { "X" "Y" } 0 t "" 2 "" { 1, 0 } p "" 2 1 "" { "a" "b" } 0 t "" 3 "" { 100, 100 } t "" 4 "" { 0, 0 } gambit-0.2010.09.01/contrib/games/badgame2.efg0000644000076500007650000000063511350032206015315 00000000000000EFG 2 R "Agent SPE not Player SPE" { "Player 1" "Player 2" } "" c "" 1 "" { "U" 1/2 "D" 1/2 } 0 p "" 1 1 "" { "A" "B" } 0 t "" 1 "" { 2, 0 } p "" 1 2 "" { "X" "Y" } 0 t "" 2 "" { 1, 0 } p "" 2 1 "" { "a" "b" } 0 t "" 3 "" { 100, 100 } t "" 4 "" { 0, 0 } p "" 1 1 "" { "A" "B" } 0 t "" 1 "" { 2, 0 } p "" 1 2 "" { "X" "Y" } 0 t "" 2 "" { 1, 0 } p "" 2 1 "" { "a" "b" } 0 t "" 3 "" { 100, 100 } t "" 4 "" { 0, 0 } gambit-0.2010.09.01/contrib/games/bayes1a.efg0000644000076500007650000000201111350032206015166 00000000000000EFG 2 R "General Bayes game, one stage" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "1G" 1/2 "1B" 1/2 } 0 c "" 2 "(0,2)" { "2g" 1/2 "2b" 1/2 } 0 p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 1 "Outcome 1" { 10, 2 } t "" 2 "Outcome 2" { 0, 10 } p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 3 "Outcome 3" { 2, 4 } t "" 4 "Outcome 4" { 4, 0 } p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 5 "Outcome 5" { 10, 2 } t "" 6 "Outcome 6" { 0, 10 } p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 7 "Outcome 7" { 2, 4 } t "" 8 "Outcome 8" { 4, 0 } c "" 3 "(0,3)" { "2g" 1/2 "2b" 1/2 } 0 p "" 1 2 "(1,2)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 9 "Outcome 9" { 4, 2 } t "" 10 "Outcome 10" { 2, 10 } p "" 2 1 "(2,1)" { "h" "l" } 0 t "" 11 "Outcome 11" { 0, 4 } t "ROOT" 12 "Outcome 12" { 10, 2 } p "" 1 2 "(1,2)" { "H" "L" } 0 p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 13 "Outcome 13" { 4, 2 } t "" 14 "Outcome 14" { 2, 10 } p "" 2 2 "(2,2)" { "h" "l" } 0 t "" 15 "Outcome 15" { 0, 4 } t "" 16 "Outcome 16" { 10, 0 } gambit-0.2010.09.01/contrib/games/bayes2a.efg0000644000076500007650000001031511350032206015175 00000000000000EFG 2 R "General Bayesian game, two stages" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "1G" 1/2 "1B" 1/2 } 0 c "" 2 "(0,2)" { "2g" 1/2 "2b" 1/2 } 0 p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 2 "(1,3)" { "H" "L" } 1 "Outcome 1" { 10, 2 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 1 "Outcome 1" { 10, 2 } t "" 2 "Outcome 2" { 0, 10 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 3 "Outcome 3" { 2, 4 } t "" 4 "Outcome 4" { 4, 0 } p "" 1 3 "(1,4)" { "H" "L" } 2 "Outcome 2" { 0, 10 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 1 "Outcome 1" { 10, 2 } t "" 2 "Outcome 2" { 0, 10 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 3 "Outcome 3" { 2, 4 } t "" 4 "Outcome 4" { 4, 0 } p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 4 "(1,5)" { "H" "L" } 3 "Outcome 3" { 2, 4 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 1 "Outcome 1" { 10, 2 } t "" 2 "Outcome 2" { 0, 10 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 3 "Outcome 3" { 2, 4 } t "" 4 "Outcome 4" { 4, 0 } p "" 1 5 "(1,6)" { "H" "L" } 4 "Outcome 4" { 4, 0 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 1 "Outcome 1" { 10, 2 } t "" 2 "Outcome 2" { 0, 10 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 3 "Outcome 3" { 2, 4 } t "" 4 "Outcome 4" { 4, 0 } p "" 1 1 "(1,1)" { "H" "L" } 0 p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 2 "(1,3)" { "H" "L" } 5 "Outcome 5" { 10, 2 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 5 "Outcome 5" { 10, 2 } t "" 6 "Outcome 6" { 0, 10 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 7 "Outcome 7" { 2, 4 } t "" 8 "Outcome 8" { 4, 0 } p "" 1 3 "(1,4)" { "H" "L" } 6 "Outcome 6" { 0, 10 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 5 "Outcome 5" { 10, 2 } t "" 6 "Outcome 6" { 0, 10 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 7 "Outcome 7" { 2, 4 } t "" 8 "Outcome 8" { 4, 0 } p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 4 "(1,5)" { "H" "L" } 7 "Outcome 7" { 2, 4 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 5 "Outcome 5" { 10, 2 } t "" 6 "Outcome 6" { 0, 10 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 7 "Outcome 7" { 2, 4 } t "" 8 "Outcome 8" { 4, 0 } p "" 1 5 "(1,6)" { "H" "L" } 8 "Outcome 8" { 4, 0 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 5 "Outcome 5" { 10, 2 } t "" 6 "Outcome 6" { 0, 10 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 7 "Outcome 7" { 2, 4 } t "" 8 "Outcome 8" { 4, 0 } c "" 3 "(0,3)" { "2g" 1/2 "2b" 1/2 } 0 p "" 1 6 "(1,2)" { "H" "L" } 0 p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 7 "(1,7)" { "H" "L" } 9 "Outcome 9" { 4, 2 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 9 "Outcome 9" { 4, 2 } t "" 10 "Outcome 10" { 2, 10 } p "" 2 2 "(2,3)" { "h" "l" } 0 t "" 11 "Outcome 11" { 0, 4 } t "" 12 "Outcome 12" { 10, 0 } p "" 1 8 "(1,8)" { "H" "L" } 10 "Outcome 10" { 2, 10 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 9 "Outcome 9" { 4, 2 } t "" 10 "Outcome 10" { 2, 10 } p "" 2 3 "(2,4)" { "h" "l" } 0 t "" 11 "Outcome 11" { 0, 4 } t "" 12 "Outcome 12" { 10, 0 } p "" 2 1 "(2,1)" { "h" "l" } 0 p "" 1 9 "(1,9)" { "H" "L" } 11 "Outcome 11" { 0, 4 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 9 "Outcome 9" { 4, 2 } t "" 10 "Outcome 10" { 2, 10 } p "" 2 4 "(2,5)" { "h" "l" } 0 t "" 11 "Outcome 11" { 0, 4 } t "" 12 "Outcome 12" { 10, 0 } p "" 1 10 "(1,10)" { "H" "L" } 12 "Outcome 12" { 10, 0 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 9 "Outcome 9" { 4, 2 } t "" 10 "Outcome 10" { 2, 10 } p "" 2 5 "(2,6)" { "h" "l" } 0 t "" 11 "Outcome 11" { 0, 4 } t "" 12 "Outcome 12" { 10, 0 } p "" 1 6 "(1,2)" { "H" "L" } 0 p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 7 "(1,7)" { "H" "L" } 13 "Outcome 13" { 4, 2 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 14 "Outcome 13" { 4, 2 } t "" 15 "Outcome 14" { 2, 10 } p "" 2 7 "(2,7)" { "h" "l" } 0 t "" 16 "Outcome 15" { 0, 4 } t "" 17 "Outcome 16" { 10, 0 } p "" 1 8 "(1,8)" { "H" "L" } 18 "Outcome 14" { 2, 10 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 14 "Outcome 13" { 4, 2 } t "" 15 "Outcome 14" { 2, 10 } p "" 2 8 "(2,8)" { "h" "l" } 0 t "" 16 "Outcome 15" { 0, 4 } t "" 17 "Outcome 16" { 10, 0 } p "" 2 6 "(2,2)" { "h" "l" } 0 p "" 1 9 "(1,9)" { "H" "L" } 19 "Outcome 15" { 0, 4 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 14 "Outcome 13" { 4, 2 } t "" 15 "Outcome 14" { 2, 10 } p "" 2 9 "(2,9)" { "h" "l" } 0 t "" 16 "Outcome 15" { 0, 4 } t "" 17 "Outcome 16" { 10, 0 } p "" 1 10 "(1,10)" { "H" "L" } 20 "Outcome 16" { 10, 0 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 14 "Outcome 13" { 4, 2 } t "" 15 "Outcome 14" { 2, 10 } p "" 2 10 "(2,10)" { "h" "l" } 0 t "" 16 "Outcome 15" { 0, 4 } t "" 17 "Outcome 16" { 10, 0 } gambit-0.2010.09.01/contrib/games/bcp2.efg0000644000076500007650000000143611350032206014501 00000000000000EFG 2 R "Banks-Camerer-Porter (GEB 94), Game 2" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "type 1" 1/2 "type 2" 1/2 } 0 p "" 1 1 "(1,1)" { "m1" "m2" "m3" } 0 p "" 2 1 "(2,1)" { "a1" "a2" "a3" } 0 t "" 1 "a" { 1, 2 } t "" 2 "b" { 2, 1 } t "" 3 "c" { 0, 3 } p "" 2 2 "(2,2)" { "a1" "a2" "a3" } 0 t "" 4 "d" { 1, 2 } t "" 5 "e" { 1, 1 } t "" 6 "f" { 2, 1 } p "" 2 3 "(2,3)" { "a1" "a2" "a3" } 0 t "" 7 "g" { 3, 1 } t "" 8 "h" { 0, 0 } t "" 9 "i" { 2, 1 } p "" 1 2 "(1,2)" { "m1" "m2" "m3" } 0 p "" 2 1 "(2,1)" { "a1" "a2" "a3" } 0 t "" 10 "j" { 2, 2 } t "" 11 "k" { 1, 4 } t "" 12 "l" { 3, 2 } p "" 2 2 "(2,2)" { "a1" "a2" "a3" } 0 t "" 13 "m" { 2, 2 } t "" 14 "n" { 0, 4 } t "" 15 "o" { 3, 1 } p "" 2 3 "(2,3)" { "a1" "a2" "a3" } 0 t "" 16 "p" { 2, 2 } t "" 17 "q" { 0, 0 } t "" 18 "r" { 2, 1 } gambit-0.2010.09.01/contrib/games/bcp3.efg0000644000076500007650000000143611350032206014502 00000000000000EFG 2 R "Banks-Camerer-Porter (GEB 94), Game 3" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "type 1" 1/2 "type 2" 1/2 } 0 p "" 1 1 "(1,1)" { "m1" "m2" "m3" } 0 p "" 2 1 "(2,1)" { "a1" "a2" "a3" } 0 t "" 1 "a" { 0, 3 } t "" 2 "b" { 2, 2 } t "" 3 "c" { 2, 1 } p "" 2 2 "(2,2)" { "a1" "a2" "a3" } 0 t "" 4 "d" { 1, 2 } t "" 5 "e" { 2, 1 } t "" 6 "f" { 3, 0 } p "" 2 3 "(2,3)" { "a1" "a2" "a3" } 0 t "" 7 "g" { 1, 6 } t "" 8 "h" { 4, 1 } t "" 9 "i" { 2, 0 } p "" 1 2 "(1,2)" { "m1" "m2" "m3" } 0 p "" 2 1 "(2,1)" { "a1" "a2" "a3" } 0 t "" 10 "j" { 1, 0 } t "" 11 "k" { 3, 2 } t "" 12 "l" { 2, 1 } p "" 2 2 "(2,2)" { "a1" "a2" "a3" } 0 t "" 13 "m" { 0, 1 } t "" 14 "n" { 3, 1 } t "" 15 "o" { 2, 6 } p "" 2 3 "(2,3)" { "a1" "a2" "a3" } 0 t "" 16 "p" { 0, 0 } t "" 17 "q" { 4, 1 } t "" 18 "r" { 0, 6 } gambit-0.2010.09.01/contrib/games/bcp4.efg0000644000076500007650000000143611350032206014503 00000000000000EFG 2 R "Banks-Camerer-Porter (GEB 94), Game 4" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "type 1" 1/2 "type 2" 1/2 } 0 p "" 1 1 "(1,1)" { "m1" "m2" "m3" } 0 p "" 2 1 "(2,1)" { "a1" "a2" "a3" } 0 t "" 1 "a" { 4, 0 } t "" 2 "b" { 0, 3 } t "" 3 "c" { 0, 4 } p "" 2 2 "(2,2)" { "a1" "a2" "a3" } 0 t "" 4 "d" { 2, 0 } t "" 5 "e" { 0, 3 } t "" 6 "f" { 3, 2 } p "" 2 3 "(2,3)" { "a1" "a2" "a3" } 0 t "" 7 "g" { 2, 3 } t "" 8 "h" { 1, 0 } t "" 9 "i" { 1, 2 } p "" 1 2 "(1,2)" { "m1" "m2" "m3" } 0 p "" 2 1 "(2,1)" { "a1" "a2" "a3" } 0 t "" 10 "j" { 3, 4 } t "" 11 "k" { 3, 3 } t "" 12 "l" { 1, 0 } p "" 2 2 "(2,2)" { "a1" "a2" "a3" } 0 t "" 13 "m" { 0, 3 } t "" 14 "n" { 0, 0 } t "" 15 "o" { 2, 2 } p "" 2 3 "(2,3)" { "a1" "a2" "a3" } 0 t "" 16 "p" { 4, 3 } t "" 17 "q" { 0, 4 } t "" 18 "r" { 3, 0 } gambit-0.2010.09.01/contrib/games/bhg1.efg0000644000076500007650000000125011350032206014466 00000000000000EFG 2 R "Brandts-Holt, IJGT 93, Game 1" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "Type A" 1/2 "Type B" 1/2 } 0 p "" 1 1 "(1,1)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 1 "Outcome 1" { 15, 30 } t "" 2 "Outcome 2" { 30, 30 } t "" 3 "Outcome 3" { 0, 45 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 4 "Outcome 4" { 45, 15 } t "" 5 "Outcome 5" { 0, 0 } t "" 6 "Outcome 6" { 30, 15 } p "" 1 2 "(1,2)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 7 "Outcome 7" { 30, 30 } t "" 8 "Outcome 8" { 15, 60 } t "" 9 "Outcome 9" { 45, 30 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 10 "Outcome 10" { 30, 30 } t "" 11 "Outcome 11" { 0, 0 } t "" 12 "Outcome 12" { 30, 15 } gambit-0.2010.09.01/contrib/games/bhg2.efg0000644000076500007650000000125011350032206014467 00000000000000EFG 2 R "Brandts-Holt, IJGT 93, Game 2" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "Type A" 1/2 "Type B" 1/2 } 0 p "" 1 1 "(1,1)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 1 "Outcome 1" { 75, 30 } t "" 2 "Outcome 2" { 45, 30 } t "" 3 "Outcome 3" { 75, 45 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 4 "Outcome 4" { 60, 15 } t "" 5 "Outcome 5" { 0, 0 } t "" 6 "Outcome 6" { 0, 45 } p "" 1 2 "(1,2)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 7 "Outcome 7" { 75, 30 } t "" 8 "Outcome 8" { 30, 75 } t "" 9 "Outcome 9" { 75, 30 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 10 "Outcome 10" { 45, 60 } t "" 11 "Outcome 11" { 0, 0 } t "" 12 "Outcome 12" { 45, 15 } gambit-0.2010.09.01/contrib/games/bhg3.efg0000644000076500007650000000125111350032206014471 00000000000000EFG 2 R "Brandts-Holt, IJGT 93, Game 3" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "Type A" 1/2 "Type B" 1/2 } 0 p "" 1 1 "(1,1)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 1 "Outcome 1" { 45, 30 } t "" 2 "Outcome 2" { 15, 0 } t "" 3 "Outcome 3" { 30, 15 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 4 "Outcome 4" { 30, 90 } t "" 5 "Outcome 5" { 0, 15 } t "" 6 "Outcome 6" { 45, 15 } p "" 1 2 "(1,2)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 7 "Outcome 7" { 30, 30 } t "" 8 "Outcome 8" { 0, 45 } t "" 9 "Outcome 9" { 30, 15 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 10 "Outcome 10" { 45, 0 } t "" 11 "Outcome 11" { 15, 30 } t "" 12 "Outcome 12" { 30, 15 } gambit-0.2010.09.01/contrib/games/bhg4.efg0000644000076500007650000000125011350032206014471 00000000000000EFG 2 R "Brandts-Holt, IJGT 93, Game 4" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "Type A" 1/2 "Type B" 1/2 } 0 p "" 1 1 "(1,1)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 1 "Outcome 1" { 30, 30 } t "" 2 "Outcome 2" { 0, 0 } t "" 3 "Outcome 3" { 50, 35 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 4 "Outcome 4" { 45, 90 } t "" 5 "Outcome 5" { 15, 15 } t "" 6 "Outcome 6" { 100, 30 } p "" 1 2 "(1,2)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 7 "Outcome 7" { 30, 30 } t "" 8 "Outcome 8" { 30, 45 } t "" 9 "Outcome 9" { 30, 0 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 10 "Outcome 10" { 45, 0 } t "" 11 "Outcome 11" { 0, 30 } t "" 12 "Outcome 12" { 0, 15 } gambit-0.2010.09.01/contrib/games/bhg5.efg0000644000076500007650000000124611350032206014477 00000000000000EFG 2 R "Brandts-Holt, IJGT 93, Game 5" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "Type A" 1/2 "Type B" 1/2 } 0 p "" 1 1 "(1,1)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 1 "Outcome 1" { 45, 30 } t "" 2 "Outcome 2" { 0, 0 } t "" 3 "Outcome 3" { 0, 15 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 4 "Outcome 4" { 30, 90 } t "" 5 "Outcome 5" { 30, 15 } t "" 6 "Outcome 6" { 60, 60 } p "" 1 2 "(1,2)" { "N" "S" } 0 p "" 2 1 "(2,1)" { "C" "D" "E" } 0 t "" 7 "Outcome 7" { 30, 30 } t "" 8 "Outcome 8" { 30, 45 } t "" 9 "Outcome 9" { 30, 0 } p "" 2 2 "(2,2)" { "C" "D" "E" } 0 t "" 10 "Outcome 10" { 45, 0 } t "" 11 "Outcome 11" { 0, 30 } t "" 12 "Outcome 12" { 0, 15 } gambit-0.2010.09.01/contrib/games/caro2.efg0000644000076500007650000000344211350032206014660 00000000000000EFG 2 R "Caro2" { "Player 1" "Player 2" } "" c "" 1 "" { "A- K" 1/6 "A - Q" 1/6 "K - A" 1/6 "K - Q" 1/6 "Q - A" 1/6 "Q - K" 1/6 } 0 p "player 1" 1 1 "p1 has A" { "raise" "pass" } 0 p "player 2" 2 1 "p2 r K" { "call" "pass" } 0 t "" 1 "ArKc" { 3, -1 } t "" 2 "ArKp" { 2, 0 } p "" 2 2 "p1pK" { "raise" "pass" } 0 p "Ap2r" 1 2 "p2rA" { "call" "pass" } 0 t "" 1 "ArKc" { 3, -1 } t "" 3 "ApKrAp" { 0, 2 } t "" 2 "ArKp" { 2, 0 } p "" 1 1 "p1 has A" { "raise" "pass" } 0 p "player 2" 2 3 "p2 r Q" { "call" "pass" } 0 t "" 1 "ArKc" { 3, -1 } t "" 2 "ArKp" { 2, 0 } p "" 2 4 "p1pQ" { "raise" "pass" } 0 p "" 1 2 "p2rA" { "call" "pass" } 0 t "" 1 "ArKc" { 3, -1 } t "" 3 "ApKrAp" { 0, 2 } t "" 2 "ArKp" { 2, 0 } p "player1" 1 3 "p1 has K" { "raise" "pass" } 0 p "player 2" 2 5 "p2 r A" { "call " "pass" } 0 t "" 4 "KrAc" { -1, 3 } t "" 2 "ArKp" { 2, 0 } p "" 2 6 "p1pA" { "raise" "pass" } 0 p "KpAr" 1 4 "p2rK" { "call" "pass" } 0 t "" 4 "KrAc" { -1, 3 } t "" 3 "ApKrAp" { 0, 2 } t "" 3 "ApKrAp" { 0, 2 } p "" 1 3 "p1 has K" { "raise" "pass" } 0 p "" 2 3 "p2 r Q" { "call" "pass" } 0 t "" 1 "ArKc" { 3, -1 } t "" 2 "ArKp" { 2, 0 } p "" 2 4 "p1pQ" { "raise" "pass" } 0 p "" 1 4 "p2rK" { "call" "pass" } 0 t "" 1 "ArKc" { 3, -1 } t "" 3 "ApKrAp" { 0, 2 } t "" 2 "ArKp" { 2, 0 } p "player 1" 1 5 "p1 has Q" { "raise" "pass" } 0 p "" 2 5 "p2 r A" { "call " "pass" } 0 t "" 4 "KrAc" { -1, 3 } t "" 2 "ArKp" { 2, 0 } p "" 2 6 "p1pA" { "raise" "pass" } 0 p "QpAr" 1 6 "p2rQ" { "call" "pass" } 0 t "" 4 "KrAc" { -1, 3 } t "" 3 "ApKrAp" { 0, 2 } t "" 3 "ApKrAp" { 0, 2 } p "" 1 5 "p1 has Q" { "raise" "pass" } 0 p "" 2 1 "p2 r K" { "call" "pass" } 0 t "" 4 "KrAc" { -1, 3 } t "" 2 "ArKp" { 2, 0 } p "" 2 2 "p1pK" { "raise" "pass" } 0 p "" 1 6 "p2rQ" { "call" "pass" } 0 t "" 4 "KrAc" { -1, 3 } t "" 3 "ApKrAp" { 0, 2 } t "" 3 "ApKrAp" { 0, 2 } gambit-0.2010.09.01/contrib/games/cent2.efg0000644000076500007650000000217311350032206014665 00000000000000EFG 2 R "Centipede game. Two inning, with probability of altruists. " { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "1=rational" 19/20 "1=altruist" 1/20 } 0 c "" 2 "(0,2)" { "2=rational" 19/20 "2=altruist" 1/20 } 0 p "" 1 1 "(1,1)" { "t" "p" } 0 t "" 1 "Outcome 1" { .80, .20 } p "" 2 1 "(2,1)" { "t" "p" } 0 t "" 2 "Outcome 2" { .40, 1.60 } p "" 1 2 "(1,2)" { "t" "p" } 0 t "" 3 "Outcome 3" { 3.20, .80 } p "" 2 2 "(2,2)" { "t" "p" } 0 t "" 4 "Outcome 4" { 1.60, 6.40 } t "" 5 "Outcome 5" { 12.80, 3.20 } p "" 1 1 "(1,1)" { "t" "p" } 0 t "" 6 "Outcome 11" { .80, .20 } p "" 2 3 "(2,3)" { "p" } 0 p "" 1 2 "(1,2)" { "t" "p" } 0 t "" 7 "Outcome 13" { 3.20, .80 } p "" 2 4 "(2,4)" { "p" } 0 t "" 5 "Outcome 5" { 12.80, 3.20 } c "" 3 "(0,3)" { "2=rational" 19/20 "2=altruist" 1/20 } 0 p "" 1 3 "(1,3)" { "p" } 0 p "" 2 1 "(2,1)" { "t" "p" } 0 t "" 8 "Outcome 22" { .40, 1.60 } p "" 1 4 "(1,4)" { "p" } 0 p "" 2 2 "(2,2)" { "t" "p" } 0 t "" 9 "Outcome 24" { 1.60, 6.40 } t "" 5 "Outcome 5" { 12.80, 3.20 } p "" 1 3 "(1,3)" { "p" } 0 p "" 2 3 "(2,3)" { "p" } 0 p "" 1 4 "(1,4)" { "p" } 0 p "" 2 4 "(2,4)" { "p" } 0 t "" 5 "Outcome 5" { 12.80, 3.20 } gambit-0.2010.09.01/contrib/games/cent2.nfg0000644000076500007650000000061711350032206014677 00000000000000NFG 1 R "Centipede game. Two inning, with probability of altruists" { "Player 1" "Player 2" } { { "1*11" "2111" "2211" } { "1*11" "2111" "2211" } } { { "" 0.811000 0.274000 } { "" 0.868000 0.502000 } { "" 1.400000 0.350000 } { "" 0.564000 1.566000 } { "" 3.148000 1.072000 } { "" 3.680000 0.920000 } { "" 1.020000 1.680000 } { "" 2.160000 6.240000 } { "" 12.800000 3.200000 } } 1 4 7 2 5 8 3 6 9 gambit-0.2010.09.01/contrib/games/cent3.efg0000644000076500007650000000300611350032206014662 00000000000000EFG 2 R "Centipede game. Three inning with probability of altruism. " { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "1=rational" 99/100 "1=altruist" 1/100 } 0 c "" 2 "(0,2)" { "2=rational" 99/100 "2=altruist" 1/100 } 0 p "" 1 1 "(1,1)" { "t" "p" } 0 t "" 1 "Outcome 1" { .80, .20 } p "" 2 1 "(2,1)" { "t" "p" } 0 t "" 2 "Outcome 2" { .40, 1.60 } p "" 1 2 "(1,3)" { "t" "p" } 0 t "" 3 "Outcome 3" { 3.20, .80 } p "" 2 2 "(2,4)" { "t" "p" } 0 t "" 4 "Outcome 4" { 1.60, 6.40 } p "" 1 3 "(1,5)" { "t" "p" } 0 t "" 5 "Outcome 5" { 12.80, 3.20 } p "" 2 3 "(2,5)" { "t" "p" } 0 t "" 6 "Outcome 6" { 6.40, 25.60 } t "" 7 "Outcome 7" { 51.20, 12.80 } p "" 1 1 "(1,1)" { "t" "p" } 0 t "" 8 "Outcome 11" { .80, .20 } p "" 2 4 "(2,2)" { "p" } 0 p "" 1 2 "(1,3)" { "t" "p" } 0 t "" 9 "Outcome 13" { 3.20, 0.80 } p "" 2 5 "(2,3)" { "p" } 0 p "" 1 3 "(1,5)" { "t" "p" } 0 t "" 10 "Outcome 15" { 12.80, 3.20 } p "" 2 6 "(2,6)" { "p" } 0 t "" 11 "Outcome 17" { 51.20, 12.80 } c "" 3 "(0,3)" { "2=rational" 99/100 "2=altruist" 1/100 } 0 p "" 1 4 "(1,2)" { "p" } 0 p "" 2 1 "(2,1)" { "t" "p" } 0 t "" 12 "Outcome 22" { .40, 1.60 } p "" 1 5 "(1,4)" { "p" } 0 p "" 2 2 "(2,4)" { "t" "p" } 0 t "" 13 "Outcome 24" { 1.60, 6.40 } p "" 1 6 "(1,6)" { "p" } 0 p "" 2 3 "(2,5)" { "t" "p" } 0 t "" 14 "Outcome 26" { 6.40, 25.60 } t "" 15 "Outcome 27" { 51.20, 12.80 } p "" 1 4 "(1,2)" { "p" } 0 p "" 2 4 "(2,2)" { "p" } 0 p "" 1 5 "(1,4)" { "p" } 0 p "" 2 5 "(2,3)" { "p" } 0 p "" 1 6 "(1,6)" { "p" } 0 p "" 2 6 "(2,6)" { "p" } 0 t "" 16 "Outcome 37" { 51.20, 12.80 } gambit-0.2010.09.01/contrib/games/cent4.efg0000644000076500007650000000057611350032206014674 00000000000000EFG 2 R "Centipede game, 4 move" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "TAKE" "PASS" } 0 t "" 1 "Outcome 1" { 0.80, 0.20 } p "" 2 1 "(2,1)" { "TAKE" "PASS" } 0 t "" 2 "Outcome 2" { 0.40, 1.60 } p "" 1 2 "(1,2)" { "TAKE" "PASS" } 0 t "" 3 "Outcome 3" { 3.20, 0.80 } p "" 2 2 "(2,2)" { "TAKE" "PASS" } 0 t "" 4 "Outcome 4" { 1.60, 6.40 } t "" 5 "Outcome 5" { 12.80, 3.20 } gambit-0.2010.09.01/contrib/games/cent6.efg0000644000076500007650000000101711350032206014665 00000000000000EFG 2 R "Centipede game, 6 move" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "TAKE" "PASS" } 0 t "" 1 "Outcome 1" { 0.80, 0.20 } p "" 2 1 "(2,1)" { "TAKE" "PASS" } 0 t "" 2 "Outcome 2" { 0.40, 1.60 } p "" 1 2 "(1,2)" { "TAKE" "PASS" } 0 t "" 3 "Outcome 3" { 3.20, 0.80 } p "" 2 2 "(2,2)" { "TAKE" "PASS" } 0 t "" 4 "Outcome 4" { 1.60, 6.40 } p "" 1 3 "(1,3)" { "TAKE" "PASS" } 0 t "" 5 "Outcome 5" { 12.80, 3.20 } p "" 2 3 "(2,3)" { "TAKE" "PASS" } 0 t "" 6 "Outcome 6" { 6.40, 25.60 } t "" 7 "Outcome 7" { 51.20, 12.80 } gambit-0.2010.09.01/contrib/games/centcs10.efg0000644000076500007650000000146011350032206015270 00000000000000EFG 2 R "Centipede game, 10 move constant sum" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "TAKE" "PASS" } 0 t "" 1 "Outcome 1" { 1.60, 1.60 } p "" 2 1 "(2,1)" { "TAKE" "PASS" } 0 t "" 2 "Outcome 2" { 1.20, 2.00 } p "" 1 2 "(1,2)" { "TAKE" "PASS" } 0 t "" 3 "Outcome 3" { 2.30, .90 } p "" 2 2 "(2,2)" { "TAKE" "PASS" } 0 t "" 4 "Outcome 4" { .68, 2.52 } p "" 1 3 "(1,3)" { "TAKE" "PASS" } 0 t "" 5 "Outcome 5" { 2.69, .51 } p "" 2 3 "(2,3)" { "TAKE" "PASS" } 0 t "" 6 "Outcome 6" { .38, 2.82 } p "" 1 4 "(1,4)" { "TAKE" "PASS" } 0 t "" 7 "Outcome 7" { 2.92, .28 } p "" 2 4 "(2,4)" { "TAKE" "PASS" } 0 t "" 8 "Outcome 8" { .21, 2.99 } p "" 1 5 "(1,5)" { "TAKE" "PASS" } 0 t "" 9 "Outcome 9" { 3.04, .16 } p "" 2 5 "(2,5)" { "TAKE" "PASS" } 0 t "" 10 "Outcome 10" { .12, 3.08 } t "" 11 "Outcome 11" { 3.11, .09 } gambit-0.2010.09.01/contrib/games/centcs6.efg0000644000076500007650000000102311350032206015210 00000000000000EFG 2 R "Centipede game, 6 move constant sum" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "TAKE" "PASS" } 0 t "" 1 "Outcome 1" { 1.60, 1.60 } p "" 2 1 "(2,1)" { "TAKE" "PASS" } 0 t "" 2 "Outcome 2" { 1.20, 2.00 } p "" 1 2 "(1,2)" { "TAKE" "PASS" } 0 t "" 3 "Outcome 3" { 2.30, .90 } p "" 2 2 "(2,2)" { "TAKE" "PASS" } 0 t "" 4 "Outcome 4" { .68, 2.52 } p "" 1 3 "(1,3)" { "TAKE" "PASS" } 0 t "" 5 "Outcome 5" { 2.69, .51 } p "" 2 3 "(2,3)" { "TAKE" "PASS" } 0 t "" 6 "Outcome 6" { .38, 2.82 } t "" 7 "Outcome 7" { 2.92, .28 } gambit-0.2010.09.01/contrib/games/condjury.efg0000644000076500007650000002337111350032206015512 00000000000000EFG 2 R "Feddersen-Pesendorfer, three person Condorcet jury game" { "Player 1" "Player 2" "Player 3" } "" c "" 1 "" { "Guilty" 1/2 "Innocent" 1/2 } 0 c "" 2 "" { "Signal Guilty" 3/4 "Signal Innocent" 1/4 } 0 c "" 3 "" { "Signal Guilty" 3/4 "Signal Innocent" 1/4 } 0 c "" 4 "" { "Signal Guilty" 3/4 "Signal Innocent" 1/4 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 5 "" { "Signal Guilty" 3/4 "Signal Innocent" 1/4 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 6 "" { "Signal Guilty" 3/4 "Signal Innocent" 1/4 } 0 c "" 7 "" { "Signal Guilty" 3/4 "Signal Innocent" 1/4 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 8 "" { "Signal Guilty" 3/4 "Signal Innocent" 1/4 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 9 "" { "Signal Guilty" 1/4 "Signal Innocent" 3/4 } 0 c "" 10 "" { "Signal Guilty" 1/4 "Signal Innocent" 3/4 } 0 c "" 11 "" { "Signal Guilty" 1/4 "Signal Innocent" 3/4 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } c "" 12 "" { "Signal Guilty" 1/4 "Signal Innocent" 3/4 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } c "" 13 "" { "Signal Guilty" 1/4 "Signal Innocent" 3/4 } 0 c "" 14 "" { "Signal Guilty" 1/4 "Signal Innocent" 3/4 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } c "" 15 "" { "Signal Guilty" 1/4 "Signal Innocent" 3/4 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } gambit-0.2010.09.01/contrib/games/coord2.efg0000644000076500007650000000043311350032206015037 00000000000000EFG 2 R "Two person 2x2 game coordination game" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "A" "B" } 0 p "" 2 1 "(2,1)" { "A" "B" } 0 t "" 1 "Outcome 1" { 3, 2 } t "" 2 "Outcome 4" { 0, 0 } p "" 2 1 "(2,1)" { "A" "B" } 0 t "" 2 "Outcome 4" { 0, 0 } t "" 3 "Outcome 2" { 2, 2 } gambit-0.2010.09.01/contrib/games/coord2.nfg0000644000076500007650000000021311350032206015044 00000000000000NFG 1 R "Two person 2x2 coordination game with 3 Nash equilibria" { "Player 1" "Player 2" } { { "1" "2" } { "1" "2" } } 3 2 0 0 0 0 2 2 gambit-0.2010.09.01/contrib/games/coord2ts.efg0000644000076500007650000000076111350032206015412 00000000000000EFG 2 R "Two stage 2x2 game -- 3 Nash equilibria in stage game" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "A" "B" } 0 p "" 2 1 "(2,1)" { "A" "B" } 0 p "" 1 2 "(1,1)" { "A" "B" } 1 "Outcome 1" { 3, 2 } p "" 2 2 "(2,1)" { "A" "B" } 0 t "" 1 "Outcome 1" { 3, 2 } t "" 2 "Outcome 4" { 0, 0 } p "" 2 2 "(2,1)" { "A" "B" } 0 t "" 2 "Outcome 4" { 0, 0 } t "" 3 "Outcome 2" { 2, 2 } t "" 2 "Outcome 4" { 0, 0 } p "" 2 1 "(2,1)" { "A" "B" } 0 t "" 2 "Outcome 4" { 0, 0 } t "" 3 "Outcome 2" { 2, 2 } gambit-0.2010.09.01/contrib/games/coord3.efg0000644000076500007650000000075511350032206015047 00000000000000EFG 2 R "Two person 3 x 3 coordination problem with 7 Nash equilibria" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "A" "B" "C" } 0 p "" 2 1 "(2,1)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 3, 2 } t "" 2 "Outcome 4" { 0, 0 } t "" 2 "Outcome 4" { 0, 0 } p "" 2 1 "(2,1)" { "A" "B" "C" } 0 t "" 2 "Outcome 4" { 0, 0 } t "" 3 "Outcome 2" { 2, 2 } t "" 2 "Outcome 4" { 0, 0 } p "" 2 1 "(2,1)" { "A" "B" "C" } 0 t "" 2 "Outcome 4" { 0, 0 } t "" 2 "Outcome 4" { 0, 0 } t "" 4 "Outcome 3" { 1, 4 } gambit-0.2010.09.01/contrib/games/coord3.nfg0000644000076500007650000000037511350032206015056 00000000000000NFG 1 R "3x3 coordination game with 7 Nash equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" } { "1" "2" "3" } } "" { { "" 3, 2 } { "" 0, 0 } { "" 0, 0 } { "" 0, 0 } { "" 2, 2 } { "" 0, 0 } { "" 0, 0 } { "" 0, 0 } { "" 1, 4 } } 1 2 3 4 5 6 7 8 9 gambit-0.2010.09.01/contrib/games/coord333.nfg0000644000076500007650000000130011350032206015211 00000000000000NFG 1 R "Three player 3x3x3 coordination game" { "Player 1" "Player 2" "Player 3" } { { "1" "2" "3" } { "1" "2" "3" } { "1" "2" "3" } } "" { { "111" 1, 1, 1 } { "112" 0, 0, 0 } { "113" 0, 0, 0 } { "121" 0, 0, 0 } { "122" 0, 0, 0 } { "123" 0, 0, 0 } { "131" 0, 0, 0 } { "132" 0, 0, 0 } { "133" 0, 0, 0 } { "211" 0, 0, 0 } { "212" 0, 0, 0 } { "213" 0, 0, 0 } { "221" 0, 0, 0 } { "222" 1, 1, 1 } { "223" 0, 0, 0 } { "231" 0, 0, 0 } { "232" 0, 0, 0 } { "233" 0, 0, 0 } { "311" 0, 0, 0 } { "312" 0, 0, 0 } { "313" 0, 0, 0 } { "321" 0, 0, 0 } { "322" 0, 0, 0 } { "323" 0, 0, 0 } { "331" 0, 0, 0 } { "332" 0, 0, 0 } { "333" 1, 1, 1 } } 1 10 19 4 13 22 7 16 25 2 11 20 5 14 23 8 17 26 3 12 21 6 15 24 9 18 27 gambit-0.2010.09.01/contrib/games/coord4.efg0000644000076500007650000000135111350032206015041 00000000000000EFG 2 R "Two person 4 x 4 coordination problem with 15 Nash equilibria" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "A" "B" "C" "D" } 0 p "" 2 1 "(2,1)" { "A" "B" "C" "D" } 0 t "" 1 "Outcome 1" { 3, 2 } t "" 2 "Outcome 5" { 0, 0 } t "" 2 "Outcome 5" { 0, 0 } t "" 2 "Outcome 5" { 0, 0 } p "" 2 1 "(2,1)" { "A" "B" "C" "D" } 0 t "" 2 "Outcome 5" { 0, 0 } t "" 3 "Outcome 2" { 2, 2 } t "" 2 "Outcome 5" { 0, 0 } t "" 2 "Outcome 5" { 0, 0 } p "" 2 1 "(2,1)" { "A" "B" "C" "D" } 0 t "" 2 "Outcome 5" { 0, 0 } t "" 2 "Outcome 5" { 0, 0 } t "" 4 "Outcome 3" { 1, 4 } t "" 2 "Outcome 5" { 0, 0 } p "" 2 1 "(2,1)" { "A" "B" "C" "D" } 0 t "" 2 "Outcome 5" { 0, 0 } t "" 2 "Outcome 5" { 0, 0 } t "" 2 "Outcome 5" { 0, 0 } t "" 5 "Outcome 4" { 4, 7 } gambit-0.2010.09.01/contrib/games/coord4.nfg0000644000076500007650000000055711350032206015061 00000000000000NFG 1 R "4x4 coordination game with 15 Nash equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" "4" } { "1" "2" "3" "4" } } "" { { "" 3, 2 } { "" 0, 0 } { "" 0, 0 } { "" 0, 0 } { "" 0, 0 } { "" 2, 2 } { "" 0, 0 } { "" 0, 0 } { "" 0, 0 } { "" 0, 0 } { "" 1, 4 } { "" 0, 0 } { "" 0, 0 } { "" 0, 0 } { "" 0, 0 } { "" 4, 7 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 gambit-0.2010.09.01/contrib/games/cross.efg0000644000076500007650000000056411350032206015005 00000000000000EFG 2 R "Criss-crossing infosets" { "Player 1" "Player 2" } "" p "ROOT" 1 1 "" { "1" "2" } 0 p "" 2 1 "" { "1" "2" } 0 p "" 1 2 "" { "1" "2" } 0 p "" 2 2 "" { "1" "2" } 0 t "" 0 t "" 0 t "" 0 p "" 1 2 "" { "1" "2" } 0 t "" 0 t "" 0 p "" 2 2 "" { "1" "2" } 0 p "" 1 3 "" { "1" "2" } 0 p "" 2 1 "" { "1" "2" } 0 t "" 0 t "" 0 t "" 0 p "" 1 3 "" { "1" "2" } 0 t "" 0 t "" 0 gambit-0.2010.09.01/contrib/games/cs.efg0000644000076500007650000001076511350032206014265 00000000000000EFG 2 R "Chain store paradox, with three entrants" { "Incumbent" "Entrant1" "Entrant2" "Entrant3" } "" c "" 1 "Chance move" { "Strong" 1/2 "Weak" 1/2 } 0 p "" 2 1 "" { "Enter" "Out" } 0 p "" 1 1 "" { "Fight" "Aquiesce" } 0 p "" 3 1 "" { "Enter" "Out" } 1 "" { 0, -1/2, 0, 0 } p "" 1 2 "" { "Fight" "Aquiesce" } 0 p "" 4 1 "" { "Enter" "Out" } 2 "" { 0, 0, -1/2, 0 } p "" 1 3 "" { "Fight" "Aquiesce" } 0 t "" 3 "" { 0, 0, 0, -1/2 } t "" 4 "" { -1, 0, 0, 1/2 } p "" 1 4 "" { "" } 0 t "" 5 "" { 1/2, 0, 0, 0 } p "" 4 2 "" { "Enter" "Out" } 6 "" { -1, 0, 1/2, 0 } p "" 1 5 "" { "Fight" "Aquiesce" } 0 t "" 7 "" { 0, 0, 0, -1/2 } t "" 8 "" { -1, 0, 0, 1/2 } p "" 1 6 "" { "" } 0 t "" 9 "" { 1/2, 0, 0, 0 } p "" 1 7 "" { "" } 0 p "" 4 3 "" { "Enter" "Out" } 10 "" { 1/2, 0, 0, 0 } p "" 1 8 "" { "Fight" "Aquiesce" } 0 t "" 11 "" { 0, 0, 0, -1/2 } t "" 12 "" { -1, 0, 0, 1/2 } p "" 1 9 "" { "" } 0 t "" 13 "" { 1/2, 0, 0, 0 } p "" 3 2 "" { "Enter" "Out" } 14 "" { -1, 1/2, 0, 0 } p "" 1 10 "" { "Fight" "Aquiesce" } 0 p "" 4 4 "" { "Enter" "Out" } 15 "" { 0, 0, -1/2, 0 } p "" 1 11 "" { "Fight" "Aquiesce" } 0 t "" 16 "" { 0, 0, 0, -1/2 } t "" 17 "" { -1, 0, 0, 1/2 } p "" 1 12 "" { "" } 0 t "" 18 "" { 1/2, 0, 0, 0 } p "" 4 5 "" { "Enter" "Out" } 19 "" { -1, 0, 1/2, 0 } p "" 1 13 "" { "Fight" "Aquiesce" } 0 t "" 20 "" { 0, 0, 0, -1/2 } t "" 21 "" { -1, 0, 0, 1/2 } p "" 1 14 "" { "" } 0 t "" 22 "" { 1/2, 0, 0, 0 } p "" 1 15 "" { "" } 0 p "" 4 6 "" { "Enter" "Out" } 23 "" { 1/2, 0, 0, 0 } p "" 1 16 "" { "Fight" "Aquiesce" } 0 t "" 24 "" { 0, 0, 0, -1/2 } t "" 25 "" { -1, 0, 0, 1/2 } p "" 1 17 "" { "" } 0 t "" 26 "" { 1/2, 0, 0, 0 } p "" 1 18 "" { "" } 0 p "" 3 3 "" { "Enter" "Out" } 27 "" { 1/2, 0, 0, 0 } p "" 1 19 "" { "Fight" "Aquiesce" } 0 p "" 4 7 "" { "Enter" "Out" } 28 "" { 0, 0, -1/2, 0 } p "" 1 20 "" { "Fight" "Aquiesce" } 0 t "" 29 "" { 0, 0, 0, -1/2 } t "" 30 "" { -1, 0, 0, 1/2 } p "" 1 21 "" { "" } 0 t "" 31 "" { 1/2, 0, 0, 0 } p "" 4 8 "" { "Enter" "Out" } 32 "" { -1, 0, 1/2, 0 } p "" 1 22 "" { "Fight" "Aquiesce" } 0 t "" 33 "" { 0, 0, 0, -1/2 } t "" 34 "" { -1, 0, 0, 1/2 } p "" 1 23 "" { "" } 0 t "" 35 "" { 1/2, 0, 0, 0 } p "" 1 24 "" { "" } 0 p "" 4 9 "" { "Enter" "Out" } 36 "" { 1/2, 0, 0, 0 } p "" 1 25 "" { "Fight" "Aquiesce" } 0 t "" 37 "" { 0, 0, 0, -1/2 } t "" 38 "" { -1, 0, 0, 1/2 } p "" 1 26 "" { "" } 0 t "" 39 "" { 1/2, 0, 0, 0 } p "" 2 1 "" { "Enter" "Out" } 0 p "" 1 27 "" { "Fight" "Aquiesce" } 0 p "" 3 1 "" { "Enter" "Out" } 40 "" { -1, -1/2, 0, 0 } p "" 1 28 "" { "Fight" "Aquiesce" } 0 p "" 4 1 "" { "Enter" "Out" } 41 "" { -1, 0, -1/2, 0 } p "" 1 29 "" { "Fight" "Aquiesce" } 0 t "" 42 "" { -1, 0, 0, -1/2 } t "" 43 "" { 0, 0, 0, 1/2 } p "" 1 30 "" { "" } 0 t "" 44 "" { 1/2, 0, 0, 0 } p "" 4 2 "" { "Enter" "Out" } 45 "" { 0, 0, 1/2, 0 } p "" 1 31 "" { "Fight" "Aquiesce" } 0 t "" 46 "" { -1, 0, 0, -1/2 } t "" 47 "" { 0, 0, 0, 1/2 } p "" 1 32 "" { "" } 0 t "" 48 "" { 1/2, 0, 0, 0 } p "" 1 33 "" { "" } 0 p "" 4 3 "" { "Enter" "Out" } 49 "" { 1/2, 0, 0, 0 } p "" 1 34 "" { "Fight" "Aquiesce" } 0 t "" 50 "" { -1, 0, 0, -1/2 } t "" 51 "" { 0, 0, 0, 1/2 } p "" 1 35 "" { "" } 0 t "" 52 "" { 1/2, 0, 0, 0 } p "" 3 2 "" { "Enter" "Out" } 53 "" { 0, 1/2, 0, 0 } p "" 1 36 "" { "Fight" "Aquiesce" } 0 p "" 4 4 "" { "Enter" "Out" } 54 "" { -1, 0, -1/2, 0 } p "" 1 37 "" { "Fight" "Aquiesce" } 0 t "" 55 "" { -1, 0, 0, -1/2 } t "" 56 "" { 0, 0, 0, 1/2 } p "" 1 38 "" { "" } 0 t "" 57 "" { 1/2, 0, 0, 0 } p "" 4 5 "" { "Enter" "Out" } 58 "" { 0, 0, 1/2, 0 } p "" 1 39 "" { "Fight" "Aquiesce" } 0 t "" 59 "" { -1, 0, 0, -1/2 } t "" 60 "" { 0, 0, 0, 1/2 } p "" 1 40 "" { "" } 0 t "" 61 "" { 1/2, 0, 0, 0 } p "" 1 41 "" { "" } 0 p "" 4 6 "" { "Enter" "Out" } 62 "" { 1/2, 0, 0, 0 } p "" 1 42 "" { "Fight" "Aquiesce" } 0 t "" 63 "" { -1, 0, 0, -1/2 } t "" 64 "" { 0, 0, 0, 1/2 } p "" 1 43 "" { "" } 0 t "" 65 "" { 1/2, 0, 0, 0 } p "" 1 44 "" { "" } 0 p "" 3 3 "" { "Enter" "Out" } 66 "" { 1/2, 0, 0, 0 } p "" 1 45 "" { "Fight" "Aquiesce" } 0 p "" 4 7 "" { "Enter" "Out" } 67 "" { -1, 0, -1/2, 0 } p "" 1 46 "" { "Fight" "Aquiesce" } 0 t "" 68 "" { -1, 0, 0, -1/2 } t "" 69 "" { 0, 0, 0, 1/2 } p "" 1 47 "" { "" } 0 t "" 70 "" { 1/2, 0, 0, 0 } p "" 4 8 "" { "Enter" "Out" } 71 "" { 0, 0, 1/2, 0 } p "" 1 48 "" { "Fight" "Aquiesce" } 0 t "" 72 "" { -1, 0, 0, -1/2 } t "" 73 "" { 0, 0, 0, 1/2 } p "" 1 49 "" { "" } 0 t "" 74 "" { 1/2, 0, 0, 0 } p "" 1 50 "" { "" } 0 p "" 4 9 "" { "Enter" "Out" } 75 "" { 1/2, 0, 0, 0 } p "" 1 51 "" { "Fight" "Aquiesce" } 0 t "" 76 "" { -1, 0, 0, -1/2 } t "" 77 "" { 0, 0, 0, 1/2 } p "" 1 52 "" { "" } 0 t "" 78 "" { 1/2, 0, 0, 0 } gambit-0.2010.09.01/contrib/games/csg1.nfg0000644000076500007650000000041111350032206014511 00000000000000NFG 1 R "2x2 constant sum game with a continuum of equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" } { "1" "2" "3" } } "" { { "" 0, 0 } { "" -1, 1 } { "" 0, 0 } { "" 1, -1 } { "" 0, 0 } { "" 1, -1 } { "" 0, 0 } { "" -1, 1 } { "" 0, 0 } } 1 2 3 4 5 6 7 8 9 gambit-0.2010.09.01/contrib/games/csg2.nfg0000644000076500007650000000062111350032206014515 00000000000000NFG 1 R "Two person 4x4 constant sum game with a continuum of equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" "4" } { "1" "2" "3" "4" } } "" { { "" 1, -1 } { "" -1, 1 } { "" 2, -2 } { "" -2, 2 } { "" -1, 1 } { "" 1, -1 } { "" -2, 2 } { "" 2, -2 } { "" 2, -2 } { "" -2, 2 } { "" 1, -1 } { "" -1, 1 } { "" -2, 2 } { "" 2, -2 } { "" -1, 1 } { "" 1, -1 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 gambit-0.2010.09.01/contrib/games/csg3.nfg0000644000076500007650000000042511350032206014520 00000000000000NFG 1 R "Two person constant sum game with a continuum of equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" } { "1" "2" "3" } } "" { { "" 1, -1 } { "" 3, -3 } { "" 2, -2 } { "" 3, -3 } { "" 1, -1 } { "" 2, -2 } { "" 2, -2 } { "" 2, -2 } { "" 2, -2 } } 1 2 3 4 5 6 7 8 9 gambit-0.2010.09.01/contrib/games/csg4.nfg0000644000076500007650000000060111350032206014515 00000000000000NFG 1 R "Two person 4x4 constant sum game with a continuum of equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" "4" } { "1" "2" "3" "4" } } "" { { "" 3, 1 } { "" 1, 3 } { "" 2, 2 } { "" 2, 2 } { "" 1, 3 } { "" 3, 1 } { "" 2, 2 } { "" 2, 2 } { "" 2, 2 } { "" 2, 2 } { "" 1, 3 } { "" 3, 1 } { "" 2, 2 } { "" 2, 2 } { "" 3, 1 } { "" 1, 3 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 gambit-0.2010.09.01/contrib/games/deg1.nfg0000644000076500007650000000034611350032206014503 00000000000000NFG 1 R "Degenerate 3x3 game 1" { "Player 1" "Player 2" } { { "1" "2" "3" } { "1" "2" "3" } } "" { { "" 1, 1 } { "" 2, 3 } { "" 3, 2 } { "" 3, 2 } { "" 2, 2 } { "" 1, 2 } { "" 2, 3 } { "" 2, 1 } { "" 2, 2 } } 1 2 3 4 5 6 7 8 9 gambit-0.2010.09.01/contrib/games/deg2.nfg0000644000076500007650000000034611350032206014504 00000000000000NFG 1 R "Degenerate 3x3 game 2" { "Player 1" "Player 2" } { { "1" "2" "3" } { "1" "2" "3" } } "" { { "" 1, 2 } { "" 2, 1 } { "" 3, 3 } { "" 3, 2 } { "" 2, 2 } { "" 1, 2 } { "" 2, 2 } { "" 2, 3 } { "" 2, 1 } } 1 2 3 4 5 6 7 8 9 gambit-0.2010.09.01/contrib/games/e01.efg0000644000076500007650000000054611350032206014241 00000000000000EFG 2 R "Selten (IJGT, 75), Figure 1" { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "(1,1)" { "R" "L" } 0 p "" 2 1 "(2,1)" { "R" "L" } 0 t "" 1 "Outcome 1" { 1, 1, 1 } p "" 3 1 "(3,1)" { "R" "L" } 0 t "" 2 "Outcome 2" { 4, 4, 0 } t "" 3 "Outcome 3" { 0, 0, 1 } p "" 3 1 "(3,1)" { "R" "L" } 0 t "" 4 "Outcome 4" { 3, 2, 2 } t "" 5 "Outcome 5" { 0, 0, 0 } gambit-0.2010.09.01/contrib/games/e01.nfg0000644000076500007650000000026311350032206014246 00000000000000NFG 1 R "Selten (IJGT, 75), Figure 1, normal form" { "Player 1" "Player 2" "Player 3" } { { "1" "2" } { "1" "2" } { "1" "2" } } 1 1 1 3 2 2 4 4 0 3 2 2 1 1 1 0 0 0 0 0 1 0 0 0 gambit-0.2010.09.01/contrib/games/e02.efg0000644000076500007650000000042111350032206014232 00000000000000EFG 2 R "Selten (IJGT, 75), Figure 2" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "R" "L" } 0 t "" 1 "Outcome 1" { 1, 1 } p "" 2 1 "(2,1)" { "R" "L" } 0 t "" 2 "Outcome 2" { 0, 2 } p "" 1 2 "(1,2)" { "r" "l" } 0 t "" 3 "Outcome 3" { 0, 3 } t "" 4 "Outcome 4" { 2, 0 } gambit-0.2010.09.01/contrib/games/e02.nfg0000644000076500007650000000015711350032206014251 00000000000000NFG 1 R "Selten (IJGT, 75), Figure 2, normal form" { "Player 1" "Player 2" } { 3 2 } 1 1 0 2 0 2 1 1 0 3 2 0 gambit-0.2010.09.01/contrib/games/e03.efg0000644000076500007650000000064411350032206014242 00000000000000EFG 2 R "Selten (IJGT, 75), Figure 3" { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "(1,1)" { "R" "L" } 0 p "" 3 1 "(3,1)" { "R" "L" } 0 t "" 1 "Outcome 1" { 3, 0, 3 } t "" 2 "Outcome 2" { 0, 0, 0 } p "" 2 1 "(2,1)" { "R" "L" } 0 p "" 1 2 "(1,2)" { "R" "L" } 0 p "" 3 1 "(3,1)" { "R" "L" } 0 t "" 3 "Outcome 3" { 4, 4, 0 } t "" 4 "Outcome 4" { 0, 0, 5 } t "" 5 "Outcome 5" { 2, 0, 0 } t "" 6 "Outcome 6" { 1, 3, 0 } gambit-0.2010.09.01/contrib/games/e04.efg0000644000076500007650000000052111350032206014235 00000000000000EFG 2 R "Kreps-Wilson (Econometrica, 85), Figures 1,4,9, and 14" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "A" "R" "L" } 0 t "" 1 "Outcome 1" { 0, 0 } p "" 2 1 "(2,1)" { "R" "L" } 0 t "" 2 "Outcome 2" { -1, 2 } t "" 3 "Outcome 3" { -1, 0 } p "" 2 1 "(2,1)" { "R" "L" } 0 t "" 4 "Outcome 4" { -2, -2 } t "" 5 "Outcome 5" { 3, -1 } gambit-0.2010.09.01/contrib/games/e04.nfg0000644000076500007650000000033611350032206014252 00000000000000NFG 1 D "Kreps-Wilson (Econometrica, 85), Figures 1,4,9,14, normal form" { "Player 1" "Player 2" } { 3 2 } 0.000000 0.000000 -1.000000 2.000000 -2.000000 -2.000000 0.000000 0.000000 -1.000000 0.000000 3.000000 -1.000000 gambit-0.2010.09.01/contrib/games/e05.efg0000644000076500007650000000106511350032206014242 00000000000000EFG 2 R "Kreps, Wilson (Econometrica, 85), Figure 8" { "Player 1" "Player 2" "Player 3" } "" c "" 1 "(0,1)" { "A" 1/2 "B" 1/2 } 0 p "" 3 1 "(3,1)" { "R" "L" } 0 p "" 2 1 "(2,1)" { "R" "L" } 0 p "" 1 1 "(1,1)" { "R" "L" } 0 t "" 1 "Outcome 1" { 2, 1, 2 } t "" 1 "Outcome 1" { 2, 1, 2 } t "" 2 "Outcome 2" { 2, 0, 0 } t "" 3 "Outcome 3" { 1, 2, 1 } p "" 1 1 "(1,1)" { "R" "L" } 0 p "" 2 1 "(2,1)" { "R" "L" } 0 p "" 3 1 "(3,1)" { "R" "L" } 0 t "" 1 "Outcome 1" { 2, 1, 2 } t "" 1 "Outcome 1" { 2, 1, 2 } t "" 4 "Outcome 4" { 0, 0, 2 } t "" 3 "Outcome 3" { 1, 2, 1 } gambit-0.2010.09.01/contrib/games/e06.efg0000644000076500007650000000113411350032206014240 00000000000000EFG 2 R "Kreps Wilson (Econometrica, 85), Figure 11" { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "(1,1)" { "A" "R" "L" } 0 t "" 1 "Outcome 1" { 1, 2, 2 } p "" 2 1 "(2,1)" { "R" "L" } 0 p "" 3 1 "(3,1)" { "R" "L" } 0 t "" 2 "Outcome 2" { 0, 0, 0 } t "" 3 "Outcome 3" { 2.1, 0, 1 } p "" 3 1 "(3,1)" { "R" "L" } 0 t "" 4 "Outcome 4" { 0, 0, 0 } t "" 5 "Outcome 5" { 2.1, 1, 1 } p "" 2 1 "(2,1)" { "R" "L" } 0 p "" 3 1 "(3,1)" { "R" "L" } 0 t "" 6 "Outcome 6" { -0.1, 1, 0 } t "" 7 "Outcome 7" { 2, 0, 1 } p "" 3 1 "(3,1)" { "R" "L" } 0 t "" 8 "Outcome 8" { -0.1, 0, 1 } t "" 9 "Outcome 9" { 2, 1, 0 } gambit-0.2010.09.01/contrib/games/e07.efg0000644000076500007650000000210011350032206014233 00000000000000EFG 2 R "Harsanyi (Managment Sci, 68), Table 1" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "a1" 1/2 "a2" 1/2 } 0 c "" 2 "(0,2)" { "b1" 4/5 "b2" 1/5 } 0 p "" 1 1 "(1,1)" { "y1" "y2" } 0 p "" 2 1 "(2,1)" { "z1" "z2" } 0 t "" 1 "Outcome 1" { 2, -2 } t "" 2 "Outcome 2" { 5, -5 } p "" 2 1 "(2,1)" { "z1" "z2" } 0 t "" 3 "Outcome 3" { -1, 1 } t "" 4 "Outcome 4" { 20, -20 } p "" 1 1 "(1,1)" { "y1" "y2" } 0 p "" 2 2 "(2,2)" { "z1" "z2" } 0 t "" 5 "Outcome 5" { -24, 24 } t "" 6 "Outcome 6" { -36, 36 } p "" 2 2 "(2,2)" { "z1" "z2" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 24, -24 } c "" 3 "(0,3)" { "b1" 2/5 "b2" 3/5 } 0 p "" 1 2 "(1,2)" { "y1" "y2" } 0 p "" 2 1 "(2,1)" { "z1" "z2" } 0 t "" 9 "Outcome 9" { 28, -28 } t "" 10 "Outcome 10" { 15, -15 } p "" 2 1 "(2,1)" { "z1" "z2" } 0 t "" 11 "Outcome 11" { 40, -40 } t "" 12 "Outcome 12" { 4, -4 } p "" 1 2 "(1,2)" { "y1" "y2" } 0 p "" 2 2 "(2,2)" { "z1" "z2" } 0 t "" 13 "Outcome 13" { 12, -12 } t "" 14 "Outcome 14" { 20, -20 } p "" 2 2 "(2,2)" { "z1" "z2" } 0 t "" 15 "Outcome 15" { 2, -2 } t "" 16 "Outcome 16" { 13, -13 } gambit-0.2010.09.01/contrib/games/e07.nfg0000644000076500007650000000061611350032206014256 00000000000000NFG 1 D "Harsanyi (Managment Sci, 68), Table 1" { "Player 1" "Player 2" } { 4 4 } 7.600000 -7.600000 8.800000 -8.800000 7.000000 -7.000000 8.200000 -8.200000 6.200000 -6.200000 14.600000 -14.600000 1.000000 -1.000000 9.400000 -9.400000 8.800000 -8.800000 13.600000 -13.600000 9.100000 -9.100000 13.900000 -13.900000 7.400000 -7.400000 19.400000 -19.400000 3.100000 -3.100000 15.100000 -15.100000 gambit-0.2010.09.01/contrib/games/e08.efg0000644000076500007650000000256711350032206014255 00000000000000EFG 2 R "Plurality Voting, Three alternatives, simultaneous vote" { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "(1,1)" { "C" "B" "A" } 0 p "" 2 1 "(2,1)" { "C" "B" "A" } 0 p "" 3 1 "(3,1)" { "C" "B" "A" } 0 t "" 1 "Outcome 3" { 1, 1, 3 } t "" 1 "Outcome 3" { 1, 1, 3 } t "" 1 "Outcome 3" { 1, 1, 3 } p "" 3 1 "(3,1)" { "C" "B" "A" } 0 t "" 1 "Outcome 3" { 1, 1, 3 } t "" 2 "Outcome 2" { 2, 3, 2 } t "" 1 "Outcome 3" { 1, 1, 3 } p "" 3 1 "(3,1)" { "C" "B" "A" } 0 t "" 1 "Outcome 3" { 1, 1, 3 } t "" 1 "Outcome 3" { 1, 1, 3 } t "" 3 "Outcome 1" { 3, 2, 1 } p "" 2 1 "(2,1)" { "C" "B" "A" } 0 p "" 3 1 "(3,1)" { "C" "B" "A" } 0 t "" 1 "Outcome 3" { 1, 1, 3 } t "" 2 "Outcome 2" { 2, 3, 2 } t "" 2 "Outcome 2" { 2, 3, 2 } p "" 3 1 "(3,1)" { "C" "B" "A" } 0 t "" 2 "Outcome 2" { 2, 3, 2 } t "" 2 "Outcome 2" { 2, 3, 2 } t "" 2 "Outcome 2" { 2, 3, 2 } p "" 3 1 "(3,1)" { "C" "B" "A" } 0 t "" 2 "Outcome 2" { 2, 3, 2 } t "" 2 "Outcome 2" { 2, 3, 2 } t "" 3 "Outcome 1" { 3, 2, 1 } p "" 2 1 "(2,1)" { "C" "B" "A" } 0 p "" 3 1 "(3,1)" { "C" "B" "A" } 0 t "" 1 "Outcome 3" { 1, 1, 3 } t "" 3 "Outcome 1" { 3, 2, 1 } t "" 3 "Outcome 1" { 3, 2, 1 } p "" 3 1 "(3,1)" { "C" "B" "A" } 0 t "" 3 "Outcome 1" { 3, 2, 1 } t "" 2 "Outcome 2" { 2, 3, 2 } t "" 3 "Outcome 1" { 3, 2, 1 } p "" 3 1 "(3,1)" { "C" "B" "A" } 0 t "" 3 "Outcome 1" { 3, 2, 1 } t "" 3 "Outcome 1" { 3, 2, 1 } t "" 3 "Outcome 1" { 3, 2, 1 } gambit-0.2010.09.01/contrib/games/e09.efg0000644000076500007650000000437311350032206014253 00000000000000EFG 2 R "Binary voting, Successive procedure, no recall" { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "(1,1)" { "1" "0" } 0 p "" 2 1 "(2,1)" { "1" "0" } 0 p "" 3 1 "(3,1)" { "1" "0" } 0 p "" 1 2 "(1,2)" { "1" "0" } 0 p "" 2 2 "(2,2)" { "1" "0" } 0 p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 1 "Outcome 3" { 1, 2, 3 } p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 2 2 "(2,2)" { "1" "0" } 0 p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 2 "Outcome 2" { 2, 3, 1 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 1 2 "(1,2)" { "1" "0" } 0 p "" 2 2 "(2,2)" { "1" "0" } 0 p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 1 "Outcome 3" { 1, 2, 3 } p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 2 2 "(2,2)" { "1" "0" } 0 p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 2 "Outcome 2" { 2, 3, 1 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 3 1 "(3,1)" { "1" "0" } 0 p "" 1 2 "(1,2)" { "1" "0" } 0 p "" 2 2 "(2,2)" { "1" "0" } 0 p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 1 "Outcome 3" { 1, 2, 3 } p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 2 2 "(2,2)" { "1" "0" } 0 p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 2 "Outcome 2" { 2, 3, 1 } t "" 2 "Outcome 2" { 2, 3, 1 } t "" 3 "Outcome 1" { 3, 1, 2 } p "" 2 1 "(2,1)" { "1" "0" } 0 p "" 3 1 "(3,1)" { "1" "0" } 0 p "" 1 2 "(1,2)" { "1" "0" } 0 p "" 2 2 "(2,2)" { "1" "0" } 0 p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 1 "Outcome 3" { 1, 2, 3 } p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 2 2 "(2,2)" { "1" "0" } 0 p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 1 "Outcome 3" { 1, 2, 3 } t "" 2 "Outcome 2" { 2, 3, 1 } p "" 3 2 "(3,2)" { "1" "0" } 0 t "" 2 "Outcome 2" { 2, 3, 1 } t "" 2 "Outcome 2" { 2, 3, 1 } t "" 3 "Outcome 1" { 3, 1, 2 } p "" 3 1 "(3,1)" { "1" "0" } 0 t "" 3 "Outcome 1" { 3, 1, 2 } t "" 3 "Outcome 1" { 3, 1, 2 } gambit-0.2010.09.01/contrib/games/e10.efg0000644000076500007650000000121711350032206014235 00000000000000EFG 2 R "Nim with 5 stones" { "Player 1" "Player 2" } "" p "5 left" 1 1 "(1,1)" { "Take 1" "Take 2" } 0 p "4 left" 2 1 "(2,1)" { "Take 1" "Take 2" } 0 p "3 left" 1 2 "(1,2)" { "Take 1" "Take 2" } 0 p "2 left" 2 2 "(2,2)" { "Take 1" "Take 2" } 0 t "1 left" 1 "Red Win" { 1, -1 } t "0 left" 2 "Blue Win" { -1, 1 } t "1 left" 2 "Blue Win" { -1, 1 } p "2 left" 1 3 "(1,3)" { "Take 1" "Take 2" } 0 t "1 left" 2 "Blue Win" { -1, 1 } t "0 left" 1 "Red Win" { 1, -1 } p "3 left" 2 3 "(2,3)" { "Take 1" "Take 2" } 0 p "2 left" 1 4 "(1,4)" { "Take 1" "Take 2" } 0 t "1 left" 2 "Blue Win" { -1, 1 } t "0 left" 1 "Red Win" { 1, -1 } t "1 left" 1 "Red Win" { 1, -1 } gambit-0.2010.09.01/contrib/games/e10a.efg0000644000076500007650000000154011350032206014375 00000000000000EFG 2 R "Nim with 5 stones" { "Player 1" "Player 2" } "" p "5 left" 1 1 "Infoset2" { "take 1" "take 2" } 0 p "4 left" 2 1 "Infoset3" { "take 1" "take 2" } 0 p "3 left" 1 2 "Infoset3" { "take 1" "take 2" } 0 p "2 left" 2 2 "Infoset6" { "take 1" "take 2" } 0 p "1 left" 1 3 "Infoset6" { "take 1" } 0 t "0 left" 1 "Red Win" { 1, -1 } t "0 left" 2 "Blue Win" { -1, 1 } p "1 left" 2 3 "Infoset7" { "take 1" } 0 t "0 left" 2 "Blue Win" { -1, 1 } p "2 left" 1 4 "Infoset4" { "take 1" "take 2" } 0 p "1 left" 2 4 "Infoset8" { "take 1" } 0 t "0 left" 2 "Blue Win" { -1, 1 } t "0 left" 1 "Red Win" { 1, -1 } p "3 left" 2 5 ":1" { "take 1" "take 2" } 0 p "2 left" 1 5 "Infoset5" { "take 1" "take 2" } 0 p "1 left" 2 6 "Infoset10" { "take 1" } 0 t "0 left" 2 "Blue Win" { -1, 1 } t "0 left" 1 "Red Win" { 1, -1 } p "1 left" 1 6 "" { "1" } 0 t "0 left" 2 "Blue Win" { -1, 1 } gambit-0.2010.09.01/contrib/games/e13.efg0000644000076500007650000000205211350032206014236 00000000000000EFG 2 R "Two Stage Prisoners' Dilemma" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "C" "D" } 0 p "" 2 1 "(2,1)" { "C" "D" } 0 p "" 1 2 "(1,2)" { "C" "D" } 1 "Outcome 1" { 3, 3 } p "" 2 2 "(2,2)" { "C" "D" } 0 t "" 1 "Outcome 1" { 3, 3 } t "" 2 "Outcome 2" { 0, 4 } p "" 2 2 "(2,2)" { "C" "D" } 0 t "" 3 "Outcome 3" { 4, 0 } t "" 4 "Outcome 4" { 1, 1 } p "" 1 3 "(1,3)" { "C" "D" } 2 "Outcome 2" { 0, 4 } p "" 2 3 "(2,3)" { "C" "D" } 0 t "" 1 "Outcome 1" { 3, 3 } t "" 2 "Outcome 2" { 0, 4 } p "" 2 3 "(2,3)" { "C" "D" } 0 t "" 3 "Outcome 3" { 4, 0 } t "" 4 "Outcome 4" { 1, 1 } p "" 2 1 "(2,1)" { "C" "D" } 0 p "" 1 4 "(1,4)" { "C" "D" } 3 "Outcome 3" { 4, 0 } p "" 2 4 "(2,4)" { "C" "D" } 0 t "" 1 "Outcome 1" { 3, 3 } t "" 2 "Outcome 2" { 0, 4 } p "" 2 4 "(2,4)" { "C" "D" } 0 t "" 3 "Outcome 3" { 4, 0 } t "" 4 "Outcome 4" { 1, 1 } p "" 1 5 "(1,5)" { "C" "D" } 4 "Outcome 4" { 1, 1 } p "" 2 5 "(2,5)" { "C" "D" } 0 t "" 1 "Outcome 1" { 3, 3 } t "" 2 "Outcome 2" { 0, 4 } p "" 2 5 "(2,5)" { "C" "D" } 0 t "" 3 "Outcome 3" { 4, 0 } t "" 4 "Outcome 4" { 1, 1 } gambit-0.2010.09.01/contrib/games/e16.efg0000644000076500007650000000325611350032206014250 00000000000000EFG 2 R "Peter's Game" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "a" "b" } 0 p "" 2 1 "(2,1)" { "a" "b" } 0 p "" 1 2 "(1,2)" { "a" "b" } 0 p "" 2 2 "(2,2)" { "a" "b" } 0 t "" 1 "Outcome 1" { 0, 4 } t "" 2 "Outcome 2" { 0, 2 } p "" 2 2 "(2,2)" { "a" "b" } 0 t "" 3 "Outcome 3" { 4, 2 } t "" 4 "Outcome 4" { 1, 1 } c "" 1 "(0,1)" { "a" 1/2 "b" 1/2 } 0 p "" 1 3 "(1,3)" { "a" "b" } 0 p "" 2 3 "(2,3)" { "a" "b" } 0 t "" 5 "Outcome 5" { 1, 3 } t "" 6 "Outcome 6" { 2, 1 } p "" 2 3 "(2,3)" { "a" "b" } 0 t "" 7 "Outcome 7" { 4, 3 } t "" 8 "Outcome 8" { 3, 2 } p "" 1 4 "(1,4)" { "a" "b" } 0 p "" 2 4 "(2,4)" { "a" "b" } 0 t "" 9 "Outcome 9" { 1, 5 } t "" 10 "Outcome 10" { 6, 0 } p "" 2 4 "(2,4)" { "a" "b" } 0 t "" 11 "Outcome 11" { 5, 1 } t "" 12 "Outcome 12" { 2, 4 } p "" 2 1 "(2,1)" { "a" "b" } 0 c "" 2 "(0,2)" { "a" 1/2 "b" 1/2 } 0 p "" 1 5 "(1,5)" { "a" "b" } 0 p "" 2 5 "(2,5)" { "a" "b" } 0 t "" 5 "Outcome 5" { 1, 3 } t "" 6 "Outcome 6" { 2, 1 } p "" 2 5 "(2,5)" { "a" "b" } 0 t "" 7 "Outcome 7" { 4, 3 } t "" 8 "Outcome 8" { 3, 2 } p "" 1 6 "(1,6)" { "a" "b" } 0 p "" 2 6 "(2,6)" { "a" "b" } 0 t "" 9 "Outcome 9" { 1, 5 } t "" 10 "Outcome 10" { 6, 0 } p "" 2 6 "(2,6)" { "a" "b" } 0 t "" 11 "Outcome 11" { 5, 1 } t "" 12 "Outcome 12" { 2, 4 } c "" 3 "(0,3)" { "a" 1/2 "b" 1/2 } 0 p "" 1 7 "(1,7)" { "a" "b" } 0 p "" 2 7 "(2,7)" { "a" "b" } 0 t "" 5 "Outcome 5" { 1, 3 } t "" 6 "Outcome 6" { 2, 1 } p "" 2 7 "(2,7)" { "a" "b" } 0 t "" 7 "Outcome 7" { 4, 3 } t "" 8 "Outcome 8" { 3, 2 } p "" 1 8 "(1,8)" { "a" "b" } 0 p "" 2 8 "(2,8)" { "a" "b" } 0 t "" 9 "Outcome 9" { 1, 5 } t "" 10 "Outcome 10" { 6, 0 } p "" 2 8 "(2,8)" { "a" "b" } 0 t "" 11 "Outcome 11" { 5, 1 } t "" 12 "Outcome 12" { 2, 4 } gambit-0.2010.09.01/contrib/games/e17.efg0000644000076500007650000000111411350032206014240 00000000000000EFG 2 R "Cho-Kreps (QJE 87) Fig 1, Beer-Quiche Game" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "wimp" 1/10 "surly" 9/10 } 0 p "" 1 1 "Infoset3" { "beer" "quiche" } 0 p "" 2 1 "(2,1)" { "duel" "don't" } 0 t "" 1 "Outcome 1" { 0, 1 } t "" 2 "Outcome 2" { 2, 0 } p "" 2 2 "(2,2)" { "duel" "don't" } 0 t "" 3 "Outcome 3" { 1, 1 } t "" 4 "Outcome 4" { 3, 0 } p "" 1 2 "(1,2):1" { "beer" "quiche" } 0 p "" 2 1 "(2,1)" { "duel" "don't" } 0 t "" 5 "Outcome 5" { 1, 0 } t "" 6 "Outcome 6" { 3, 1 } p "" 2 2 "(2,2)" { "duel" "don't" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 2, 1 } gambit-0.2010.09.01/contrib/games/e18.efg0000644000076500007650000000102611350032206014243 00000000000000EFG 2 R "Banks-Sobel, Example 1" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "t1" 1/3 "t2" 2/3 } 0 p "" 1 1 "(1,1)" { "m1" "m2" } 0 p "" 2 1 "(2,1)" { "a1" "a2" } 0 t "" 1 "Outcome 1" { -3, 3 } t "" 2 "Outcome 2" { -6, 0 } p "" 2 2 "(2,2)" { "a1" "a2" } 0 t "" 3 "Outcome 3" { -5, 5 } t "" 4 "Outcome 4" { -6, 0 } p "" 1 2 "(1,2)" { "m1" "m2" } 0 p "" 2 1 "(2,1)" { "a1" "a2" } 0 t "" 5 "Outcome 5" { -3, 3 } t "" 6 "Outcome 6" { -11, 5 } p "" 2 2 "(2,2)" { "a1" "a2" } 0 t "" 7 "Outcome 7" { -5, 5 } t "" 8 "Outcome 8" { -11, 5 } gambit-0.2010.09.01/contrib/games/g1.efg0000644000076500007650000000114311350032206014155 00000000000000EFG 2 R "van der Laan et al. Three person, 2 x 2 x 2 example with no pure Nash " { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "(1,1)" { "1" "2" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 3 1 "(3,1)" { "1" "2" } 0 t "" 1 "Outcome 1" { -1, -4, -4 } t "" 2 "Outcome 2" { -2, -2, -8 } p "" 3 1 "(3,1)" { "1" "2" } 0 t "" 3 "Outcome 3" { -8, -2, -1 } t "" 4 "Outcome 4" { -5, -6, -8 } p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 3 1 "(3,1)" { "1" "2" } 0 t "" 5 "Outcome 5" { -8, -2, -4 } t "" 6 "Outcome 6" { -8, -1, -2 } p "" 3 1 "(3,1)" { "1" "2" } 0 t "" 7 "Outcome 7" { -2, -1, -2 } t "" 8 "Outcome 8" { -2, -3, -1 } gambit-0.2010.09.01/contrib/games/g1.nfg0000644000076500007650000000064311350032206014172 00000000000000NFG 1 D "van der Laan et al. Three person, 2x2x2 example with no pure, 1 totally mixed equilibria" { "Player 1" "Player 2" "Player 3" } { { "1" "2" } { "1" "2" } { "1" "2" } } -1.000000 -4.000000 -4.000000 -8.000000 -2.000000 -4.000000 -8.000000 -2.000000 -1.000000 -2.000000 -1.000000 -2.000000 -2.000000 -2.000000 -8.000000 -8.000000 -1.000000 -2.000000 -5.000000 -6.000000 -8.000000 -2.000000 -3.000000 -1.000000 gambit-0.2010.09.01/contrib/games/g2.efg0000644000076500007650000000277111350032206014166 00000000000000EFG 2 R "van der Laan et al. Three person 3 x 3 x 3 example with no pure Nash" { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "(1,1)" { "1" "2" "3" } 0 p "" 2 1 "(2,1)" { "1" "2" "3" } 0 p "" 3 1 "(3,1)" { "1" "2" "3" } 0 t "" 1 "Outcome 1" { -2, -5, -1 } t "" 2 "Outcome 2" { -3, -6, -2 } t "" 3 "Outcome 3" { -4, -7, -5 } p "" 3 1 "(3,1)" { "1" "2" "3" } 0 t "" 4 "Outcome 4" { -2, -1, -3 } t "" 5 "Outcome 5" { -3, -1, -6 } t "" 6 "Outcome 6" { -3, -3, -2 } p "" 3 1 "(3,1)" { "1" "2" "3" } 0 t "" 7 "Outcome 7" { -4, -2, -5 } t "" 8 "Outcome 8" { -1, -3, -5 } t "" 9 "Outcome 9" { -5, -6, -2 } p "" 2 1 "(2,1)" { "1" "2" "3" } 0 p "" 3 1 "(3,1)" { "1" "2" "3" } 0 t "" 10 "Outcome 10" { -1, -4, -1 } t "" 11 "Outcome 11" { -1, -8, -3 } t "" 12 "Outcome 12" { -4, -9, -4 } p "" 3 1 "(3,1)" { "1" "2" "3" } 0 t "" 13 "Outcome 13" { -3, -3, -6 } t "" 14 "Outcome 14" { -4, -2, -3 } t "" 15 "Outcome 15" { -1, -1, -6 } p "" 3 1 "(3,1)" { "1" "2" "3" } 0 t "" 16 "Outcome 16" { -6, -5, -2 } t "" 17 "Outcome 17" { -8, -3, -7 } t "" 18 "Outcome 18" { -2, -6, -5 } p "" 2 1 "(2,1)" { "1" "2" "3" } 0 p "" 3 1 "(3,1)" { "1" "2" "3" } 0 t "" 19 "Outcome 19" { -4, -3, -1 } t "" 20 "Outcome 20" { -7, -5, -8 } t "" 21 "Outcome 21" { -2, -1, -8 } p "" 3 1 "(3,1)" { "1" "2" "3" } 0 t "" 22 "Outcome 22" { -4, -2, -2 } t "" 23 "Outcome 23" { -5, -2, -5 } t "" 24 "Outcome 24" { -5, -4, -1 } p "" 3 1 "(3,1)" { "1" "2" "3" } 0 t "" 25 "Outcome 25" { -3, -7, -4 } t "" 26 "Outcome 26" { -6, -5, -5 } t "" 27 "Outcome 27" { -4, -8, -3 } gambit-0.2010.09.01/contrib/games/g2.nfg0000644000076500007650000000174711350032206014201 00000000000000NFG 1 D "van der Laan et al. Three person 3x3x3 example with no pure, and one mixed equilibrium" { "Player 1" "Player 2" "Player 3" } { { "1" "2" "3" } { "1" "2" "3" } { "1" "2" "3" } } -2.000000 -5.000000 -1.000000 -1.000000 -4.000000 -1.000000 -4.000000 -3.000000 -1.000000 -2.000000 -1.000000 -3.000000 -3.000000 -3.000000 -6.000000 -4.000000 -2.000000 -2.000000 -4.000000 -2.000000 -5.000000 -6.000000 -5.000000 -2.000000 -3.000000 -7.000000 -4.000000 -3.000000 -6.000000 -2.000000 -1.000000 -8.000000 -3.000000 -7.000000 -5.000000 -8.000000 -3.000000 -1.000000 -6.000000 -4.000000 -2.000000 -3.000000 -5.000000 -2.000000 -5.000000 -1.000000 -3.000000 -5.000000 -8.000000 -3.000000 -7.000000 -6.000000 -5.000000 -5.000000 -4.000000 -7.000000 -5.000000 -4.000000 -9.000000 -4.000000 -2.000000 -1.000000 -8.000000 -3.000000 -3.000000 -2.000000 -1.000000 -1.000000 -6.000000 -5.000000 -4.000000 -1.000000 -5.000000 -6.000000 -2.000000 -2.000000 -6.000000 -5.000000 -4.000000 -8.000000 -3.000000 gambit-0.2010.09.01/contrib/games/g3.efg0000644000076500007650000000230711350032206014162 00000000000000EFG 2 R "van der Laan et al. Four person, 2 x 2 x 2 x 2 example with no Pure Nash." { "Player 1" "Player 2" "Player 3" "Player 4" } "" p "" 1 1 "(1,1)" { "1" "2" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 3 1 "(3,1)" { "1" "2" } 0 p "" 4 1 "(4,1)" { "1" "2" } 0 t "" 1 "Outcome 1" { -3, -4, -1, -6 } t "" 2 "Outcome 2" { -3, -6, -6, -2 } p "" 4 1 "(4,1)" { "1" "2" } 0 t "" 3 "Outcome 3" { -4, -2, -2, -3 } t "" 4 "Outcome 4" { -2, -4, -2, -6 } p "" 3 1 "(3,1)" { "1" "2" } 0 p "" 4 1 "(4,1)" { "1" "2" } 0 t "" 5 "Outcome 5" { -3, -5, -3, -5 } t "" 6 "Outcome 6" { -3, -2, -3, -5 } p "" 4 1 "(4,1)" { "1" "2" } 0 t "" 7 "Outcome 7" { -4, -7, -6, -1 } t "" 8 "Outcome 8" { -1, -4, -5, -3 } p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 3 1 "(3,1)" { "1" "2" } 0 p "" 4 1 "(4,1)" { "1" "2" } 0 t "" 9 "Outcome 9" { -4, -5, -3, -3 } t "" 10 "Outcome 10" { -1, -3, -3, -4 } p "" 4 1 "(4,1)" { "1" "2" } 0 t "" 11 "Outcome 11" { -4, -3, -4, -2 } t "" 12 "Outcome 12" { -3, -6, -6, -7 } p "" 3 1 "(3,1)" { "1" "2" } 0 p "" 4 1 "(4,1)" { "1" "2" } 0 t "" 13 "Outcome 13" { -1, -8, -3, -3 } t "" 14 "Outcome 14" { -1, -6, -2, -1 } p "" 4 1 "(4,1)" { "1" "2" } 0 t "" 15 "Outcome 15" { -6, -3, -1, -2 } t "" 16 "Outcome 16" { -8, -5, -5, -5 } gambit-0.2010.09.01/contrib/games/g3.nfg0000644000076500007650000000151211350032206014170 00000000000000NFG 1 D "van der Laan et al. Four person, 2x2x2x2 example with no pure, and five mixed equilibria" { "Player 1" "Player 2" "Player 3" "Player 4" } { { "1" "2" } { "1" "2" } { "1" "2" } { "1" "2" } } -3.000000 -4.000000 -1.000000 -6.000000 -4.000000 -5.000000 -3.000000 -3.000000 -3.000000 -5.000000 -3.000000 -5.000000 -1.000000 -8.000000 -3.000000 -3.000000 -4.000000 -2.000000 -2.000000 -3.000000 -4.000000 -3.000000 -4.000000 -2.000000 -4.000000 -7.000000 -6.000000 -1.000000 -6.000000 -3.000000 -1.000000 -2.000000 -3.000000 -6.000000 -6.000000 -2.000000 -1.000000 -3.000000 -3.000000 -4.000000 -3.000000 -2.000000 -3.000000 -5.000000 -1.000000 -6.000000 -2.000000 -1.000000 -2.000000 -4.000000 -2.000000 -6.000000 -3.000000 -6.000000 -6.000000 -7.000000 -1.000000 -4.000000 -5.000000 -3.000000 -8.000000 -5.000000 -5.000000 -5.000000 gambit-0.2010.09.01/contrib/games/holdout.efg0000644000076500007650000000676211350032206015340 00000000000000EFG 2 R "McKelvey-Palfrey (JET 77), 7 stage version of holdout game" { "Player 1" "Player 2" } "" c "" 1 "Choose 1's type" { "High" 1/2 "Low" 1/2 } 0 c "" 2 "Choose 2's type" { "High" 3/5 "Low" 2/5 } 0 p "" 1 1 "" { "H" "G" } 0 p "" 2 1 "" { "H" "G" } 0 c "" 3 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 2 "" { "H" "G" } 0 p "" 2 2 "" { "H" "G" } 0 c "" 4 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 3 "" { "H" "G" } 0 p "" 2 3 "" { "H" "G" } 0 c "" 5 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 4 "" { "H" "G" } 0 p "" 2 4 "" { "H" "G" } 0 c "" 6 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 5 "" { "H" "G" } 0 p "" 2 5 "" { "H" "G" } 0 c "" 7 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 6 "" { "H" "G" } 0 p "" 2 6 "" { "H" "G" } 0 c "" 8 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 7 "" { "H" "G" } 0 p "" 2 7 "" { "H" "G" } 0 t "" 1 "" { 0, 0 } t "" 2 "" { 1, 1/2 } p "" 2 7 "" { "H" "G" } 0 t "" 3 "" { 1/2, 1 } t "" 4 "" { 1/2, 1/2 } t "" 2 "" { 1, 1/2 } p "" 2 6 "" { "H" "G" } 0 t "" 3 "" { 1/2, 1 } t "" 4 "" { 1/2, 1/2 } t "" 2 "" { 1, 1/2 } p "" 2 5 "" { "H" "G" } 0 t "" 3 "" { 1/2, 1 } t "" 4 "" { 1/2, 1/2 } t "" 2 "" { 1, 1/2 } p "" 2 4 "" { "H" "G" } 0 t "" 3 "" { 1/2, 1 } t "" 4 "" { 1/2, 1/2 } t "" 2 "" { 1, 1/2 } p "" 2 3 "" { "H" "G" } 0 t "" 3 "" { 1/2, 1 } t "" 4 "" { 1/2, 1/2 } t "" 2 "" { 1, 1/2 } p "" 2 2 "" { "H" "G" } 0 t "" 3 "" { 1/2, 1 } t "" 4 "" { 1/2, 1/2 } t "" 2 "" { 1, 1/2 } p "" 2 1 "" { "H" "G" } 0 t "" 3 "" { 1/2, 1 } t "" 4 "" { 1/2, 1/2 } p "" 1 1 "" { "H" "G" } 0 p "" 2 8 "" { "H" } 0 c "" 9 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 2 "" { "H" "G" } 0 p "" 2 8 "" { "H" } 0 c "" 10 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 3 "" { "H" "G" } 0 p "" 2 8 "" { "H" } 0 c "" 11 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 4 "" { "H" "G" } 0 p "" 2 8 "" { "H" } 0 c "" 12 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 5 "" { "H" "G" } 0 p "" 2 8 "" { "H" } 0 c "" 13 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 6 "" { "H" "G" } 0 p "" 2 8 "" { "H" } 0 c "" 14 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 7 "" { "H" "G" } 0 p "" 2 8 "" { "H" } 0 t "" 1 "" { 0, 0 } p "" 2 8 "" { "H" } 0 t "" 3 "" { 1/2, 1 } p "" 2 8 "" { "H" } 0 t "" 3 "" { 1/2, 1 } p "" 2 8 "" { "H" } 0 t "" 3 "" { 1/2, 1 } p "" 2 8 "" { "H" } 0 t "" 3 "" { 1/2, 1 } p "" 2 8 "" { "H" } 0 t "" 3 "" { 1/2, 1 } p "" 2 8 "" { "H" } 0 t "" 3 "" { 1/2, 1 } p "" 2 8 "" { "H" } 0 t "" 3 "" { 1/2, 1 } c "" 15 "Choose 2's type" { "High" 3/5 "Low" 2/5 } 0 p "" 1 8 "" { "H" } 0 p "" 2 1 "" { "H" "G" } 0 c "" 16 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 8 "" { "H" } 0 p "" 2 2 "" { "H" "G" } 0 c "" 17 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 8 "" { "H" } 0 p "" 2 3 "" { "H" "G" } 0 c "" 18 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 8 "" { "H" } 0 p "" 2 4 "" { "H" "G" } 0 c "" 19 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 8 "" { "H" } 0 p "" 2 5 "" { "H" "G" } 0 c "" 20 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 8 "" { "H" } 0 p "" 2 6 "" { "H" "G" } 0 c "" 21 "Discount" { "" 1/10 "" 9/10 } 1 "" { 0, 0 } t "" 0 p "" 1 8 "" { "H" } 0 p "" 2 7 "" { "H" "G" } 0 t "" 1 "" { 0, 0 } t "" 2 "" { 1, 1/2 } t "" 2 "" { 1, 1/2 } t "" 2 "" { 1, 1/2 } t "" 2 "" { 1, 1/2 } t "" 2 "" { 1, 1/2 } t "" 2 "" { 1, 1/2 } t "" 2 "" { 1, 1/2 } p "" 1 8 "" { "H" } 0 p "" 2 8 "" { "H" } 0 t "" 1 "" { 0, 0 } gambit-0.2010.09.01/contrib/games/holdout7.efg0000644000076500007650000001006211350032206015413 00000000000000EFG 2 R "McKelvey-Palfrey (JET 77), 7 stage version of holdout game" { "Player 1" "Player 2" } "" c "ROOT" 1 "(0,1)" { "1 LO" 3/10 "1 HI" 7/10 } 0 c "" 2 "(0,2)" { "2 LO" 18/1000 "2 HI" 82/100 } 0 p "" 1 1 "(1,1)" { "G" "H" } 0 p "" 2 1 "(2,1)" { "G" "H" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 1/2, 1 } p "" 2 1 "(2,1)" { "G" "H" } 0 t "" 3 "Outcome 3" { 1, 1/2 } c "" 3 "(0,3)" { "1" 9/10 "2" 1/10 } 4 "Outcome 4" { 0, 0 } p "" 1 2 "(1,2)" { "G" "H" } 0 p "" 2 2 "(2,2)" { "G" "H" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 1/2, 1 } p "" 2 2 "(2,2)" { "G" "H" } 0 t "" 3 "Outcome 3" { 1, 1/2 } c "" 4 "(0,4)" { "1" 9/10 "2" 1/10 } 4 "Outcome 4" { 0, 0 } p "" 1 3 "(1,3)" { "G" "H" } 0 p "" 2 3 "(2,3)" { "G" "H" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 1/2, 1 } p "" 2 3 "(2,3)" { "G" "H" } 0 t "" 3 "Outcome 3" { 1, 1/2 } c "" 5 "(0,5)" { "1" 9/10 "2" 1/10 } 4 "Outcome 4" { 0, 0 } p "" 1 4 "(1,4)" { "G" "H" } 0 p "" 2 4 "(2,4)" { "G" "H" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 1/2, 1 } p "" 2 4 "(2,4)" { "G" "H" } 0 t "" 3 "Outcome 3" { 1, 1/2 } c "" 6 "(0,6)" { "1" 9/10 "2" 1/10 } 4 "Outcome 4" { 0, 0 } p "" 1 5 "(1,5)" { "G" "H" } 0 p "" 2 5 "(2,5)" { "G" "H" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 1/2, 1 } p "" 2 5 "(2,5)" { "G" "H" } 0 t "" 3 "Outcome 3" { 1, 1/2 } c "" 7 "(0,7)" { "1" 9/10 "2" 1/10 } 4 "Outcome 4" { 0, 0 } p "" 1 6 "(1,6)" { "G" "H" } 0 p "" 2 6 "(2,6)" { "G" "H" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 1/2, 1 } p "" 2 6 "(2,6)" { "G" "H" } 0 t "" 3 "Outcome 3" { 1, 1/2 } c "" 8 "(0,8)" { "1" 9/10 "2" 1/10 } 4 "Outcome 4" { 0, 0 } p "" 1 7 "(1,7)" { "G" "H" } 0 p "" 2 7 "(2,7)" { "G" "H" } 0 t "" 1 "Outcome 1" { 1/2, 1/2 } t "" 2 "Outcome 2" { 1/2, 1 } p "" 2 7 "(2,7)" { "G" "H" } 0 t "" 3 "Outcome 3" { 1, 1/2 } t "" 4 "Outcome 4" { 0, 0 } t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 1 1 "(1,1)" { "G" "H" } 0 t "" 5 "Outcome 6" { 1/2, 1/2 } c "" 9 "(0,9)" { "H" 1 } 0 c "" 10 "(0,10)" { "1" 9/10 "2" 1/10 } 6 "Outcome 8" { 0, 0 } p "" 1 2 "(1,2)" { "G" "H" } 0 t "" 5 "Outcome 6" { 1/2, 1/2 } c "" 11 "(0,11)" { "H" 1 } 0 c "" 12 "(0,12)" { "1" 9/10 "2" 1/10 } 6 "Outcome 8" { 0, 0 } p "" 1 3 "(1,3)" { "G" "H" } 0 t "" 5 "Outcome 6" { 1/2, 1/2 } c "" 13 "(0,13)" { "H" 1 } 0 c "" 14 "(0,14)" { "1" 9/10 "2" 1/10 } 6 "Outcome 8" { 0, 0 } p "" 1 4 "(1,4)" { "G" "H" } 0 t "" 5 "Outcome 6" { 1/2, 1/2 } c "" 15 "(0,15)" { "H" 1 } 0 c "" 16 "(0,16)" { "1" 9/10 "2" 1/10 } 6 "Outcome 8" { 0, 0 } p "" 1 5 "(1,5)" { "G" "H" } 0 t "" 5 "Outcome 6" { 1/2, 1/2 } c "" 17 "(0,17)" { "H" 1 } 0 c "" 18 "(0,18)" { "1" 9/10 "2" 1/10 } 6 "Outcome 8" { 0, 0 } p "" 1 6 "(1,6)" { "G" "H" } 0 t "" 5 "Outcome 6" { 1/2, 1/2 } c "" 19 "(0,19)" { "H" 1 } 0 c "" 20 "(0,20)" { "1" 9/10 "2" 1/10 } 6 "Outcome 8" { 0, 0 } p "" 1 7 "(1,7)" { "G" "H" } 0 t "" 5 "Outcome 6" { 1/2, 1/2 } c "" 21 "(0,21)" { "H" 1 } 0 t "" 6 "Outcome 8" { 0, 0 } t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 c "" 22 "(0,22)" { "2 LO" 18/1000 "2 HI" 82/100 } 0 c "" 23 "(0,23)" { "H" 1 } 0 p "" 2 1 "(2,1)" { "G" "H" } 0 t "" 7 "Outcome 11" { 1, 1/2 } c "" 24 "(0,24)" { "1" 9/10 "2" 1/10 } 8 "Outcome c" { 0, 0 } c "" 25 "(0,25)" { "H" 1 } 0 p "" 2 2 "(2,2)" { "G" "H" } 0 t "" 7 "Outcome 11" { 1, 1/2 } c "" 26 "(0,26)" { "1" 9/10 "2" 1/10 } 8 "Outcome c" { 0, 0 } c "" 27 "(0,27)" { "H" 1 } 0 p "" 2 3 "(2,3)" { "G" "H" } 0 t "" 7 "Outcome 11" { 1, 1/2 } c "" 28 "(0,28)" { "1" 9/10 "2" 1/10 } 8 "Outcome c" { 0, 0 } c "" 29 "(0,29)" { "H" 1 } 0 p "" 2 4 "(2,4)" { "G" "H" } 0 t "" 7 "Outcome 11" { 1, 1/2 } c "" 30 "(0,30)" { "1" 9/10 "2" 1/10 } 8 "Outcome c" { 0, 0 } c "" 31 "(0,31)" { "H" 1 } 0 p "" 2 5 "(2,5)" { "G" "H" } 0 t "" 7 "Outcome 11" { 1, 1/2 } c "" 32 "(0,32)" { "1" 9/10 "2" 1/10 } 8 "Outcome c" { 0, 0 } c "" 33 "(0,33)" { "H" 1 } 0 p "" 2 6 "(2,6)" { "G" "H" } 0 t "" 7 "Outcome 11" { 1, 1/2 } c "" 34 "(0,34)" { "1" 9/10 "2" 1/10 } 8 "Outcome c" { 0, 0 } c "" 35 "(0,35)" { "H" 1 } 0 p "" 2 7 "(2,7)" { "G" "H" } 0 t "" 7 "Outcome 11" { 1, 1/2 } t "" 9 "Outcome 12" { 0, 0 } t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 gambit-0.2010.09.01/contrib/games/hs1.efg0000644000076500007650000000140511350032206014342 00000000000000EFG 2 R "Harsanyi, Selten (1988): example reanalyzed by Dickhaut Kaplan " { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "1" "2" "3" "4" } 0 p "" 2 1 "(2,1)" { "1" "2" "3" "4" } 0 t "" 1 "Outcome 1" { -1, -1 } t "" 2 "Outcome 2" { -1, -1 } t "" 3 "Outcome 3" { 1, 1 } t "" 4 "Outcome 4" { -1, -1 } p "" 2 1 "(2,1)" { "1" "2" "3" "4" } 0 t "" 5 "Outcome 5" { -1, -1 } t "" 6 "Outcome 6" { -1, -1 } t "" 7 "Outcome 7" { 0, 2 } t "" 8 "Outcome 8" { 0, 2 } p "" 2 1 "(2,1)" { "1" "2" "3" "4" } 0 t "" 9 "Outcome 9" { 0, 2 } t "" 10 "Outcome 10" { 0, 2 } t "" 11 "Outcome 11" { 1, 1 } t "" 12 "Outcome 12" { -1, -1 } p "" 2 1 "(2,1)" { "1" "2" "3" "4" } 0 t "" 13 "Outcome 13" { 0, 2 } t "" 14 "Outcome 14" { 0, 2 } t "" 15 "Outcome 15" { 0, 2 } t "" 16 "Outcome 16" { 0, 2 } gambit-0.2010.09.01/contrib/games/jury_mr.efg0000644000076500007650000002336611350032206015350 00000000000000EFG 2 R "Jury game, majority rule" { "Player 1" "Player 2" "Player 3" } "" c "" 1 "" { "Guilty" 1/2 "Innocent" 1/2 } 0 c "" 2 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 c "" 3 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 c "" 4 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 5 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 6 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 c "" 7 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 8 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 1 "Convict-Guilty" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 9 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 c "" 10 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 c "" 11 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } c "" 12 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } c "" 13 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 c "" 14 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } c "" 15 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 3 "Convict-Innocent" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } gambit-0.2010.09.01/contrib/games/jury_un.efg0000644000076500007650000002332011350032206015342 00000000000000EFG 2 R "Jury game, unanimous vote required" { "Player 1" "Player 2" "Player 3" } "" c "" 1 "" { "Guilty" 1/2 "Innocent" 1/2 } 0 c "" 2 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 c "" 3 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 c "" 4 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 5 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 6 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 c "" 7 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 8 "" { "Signal Guilty" 7/10 "Signal Innocent" 3/10 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 1 "Convict-Guilty" { 1, 1, 1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 2 "Acquit-Guilty" { -1, -1, -1 } t "" 2 "Acquit-Guilty" { -1, -1, -1 } c "" 9 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 c "" 10 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 c "" 11 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } c "" 12 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 1 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } c "" 13 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 c "" 14 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 1 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } c "" 15 "" { "Signal Guilty" 3/10 "Signal Innocent" 7/10 } 0 p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 1 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 1 2 "" { "Convict" "Acquit" } 0 p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 3 "Convict-Innocent" { -1, -1, -1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 2 2 "" { "Convict" "Acquit" } 0 p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } p "" 3 2 "" { "Convict" "Acquit" } 0 t "" 4 "Acquit-Innocent" { 1, 1, 1 } t "" 4 "Acquit-Innocent" { 1, 1, 1 } gambit-0.2010.09.01/contrib/games/km1.efg0000644000076500007650000000046111350032206014340 00000000000000EFG 2 R "Kohlberg Mertens, Example 1" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "1" "2" "3" } 0 t "" 1 "Outcome 1" { 2, 2 } p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 2 "Outcome 2" { 3, 3 } t "" 3 "Outcome 3" { 1, 0 } p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 4 "Outcome 4" { 0, 0 } t "" 5 "Outcome 5" { 1, 1 } gambit-0.2010.09.01/contrib/games/km2.efg0000644000076500007650000000046211350032206014342 00000000000000EFG 2 R "Kohlberg, Mertens, Example 2" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "1" "2" "3" } 0 t "" 1 "Outcome 1" { 2, 2 } p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 2 "Outcome 2" { 3, 3 } t "" 3 "Outcome 3" { 1, 0 } p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 4 "Outcome 4" { 0, 0 } t "" 5 "Outcome 5" { 1, 1 } gambit-0.2010.09.01/contrib/games/km3.efg0000644000076500007650000000051511350032206014342 00000000000000EFG 2 R "Kohlberg, Mertens, Example 3" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "T" "I" } 0 t "" 1 "Outcome 1" { 2, 2 } p "" 1 2 "(1,2)" { "M" "B" } 0 p "" 2 1 "(2,1)" { "L" "R" } 0 t "" 2 "Outcome 2" { 3, 3 } t "" 3 "Outcome 3" { 1, 0 } p "" 2 1 "(2,1)" { "L" "R" } 0 t "" 4 "Outcome 4" { 0, 0 } t "" 5 "Outcome 5" { 1, 1 } gambit-0.2010.09.01/contrib/games/km6.efg0000644000076500007650000000102711350032206014344 00000000000000EFG 2 R "Kohlberg, Mertens, Example 6" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "T" "I" } 0 t "" 1 "Outcome 1" { 2, 2 } p "" 1 2 "(1,2)" { "M" "B" } 0 p "" 2 1 "(2,1)" { "L" "R" } 0 t "" 2 "Outcome 2" { 3, 3 } t "" 3 "Outcome 3" { 1, 0 } p "" 2 1 "(2,1)" { "L" "R" } 0 p "" 1 3 "(1,3)" { "1" "2" } 4 "Outcome 4" { 0, 0 } p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 5 "Outcome 6" { 4, -4 } t "" 6 "Outcome 7" { -4, 4 } p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 6 "Outcome 7" { -4, 4 } t "" 5 "Outcome 6" { 4, -4 } t "" 7 "Outcome 5" { 1, 1 } gambit-0.2010.09.01/contrib/games/loopback.nfg0000644000076500007650000000044511350032206015455 00000000000000NFG 1 R "Backward-bending principal logit branch" { "Player 1" "Player 2" } { { "1" "2" } { "1" "2" } } "This game has a backwards bend in the principal branch of the logit quantal response equilibrium correspondence." { { "11" 6, 7 } { "12" 6, 7 } { "21" 7.32, 6 } { "22" 1, 4 } } 1 3 2 4 gambit-0.2010.09.01/contrib/games/mixdom.nfg0000644000076500007650000000057611350032206015165 00000000000000NFG 1 R "Two person 4x4 game needing mixed domination" { "Player 1" "Player 2" } { { "1" "2" "3" "4" } { "1" "2" "3" "4" } } "" { { "" 6, -6 } { "" 7, -7 } { "" 5, -5 } { "" 1, -1 } { "" 2, -2 } { "" 1, -1 } { "" 4, -4 } { "" 3, -3 } { "" 1, -1 } { "" 2, -2 } { "" 6, -6 } { "" 7, -7 } { "" 4, -4 } { "" 5, -5 } { "" 7, -7 } { "" 2, -2 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 gambit-0.2010.09.01/contrib/games/mixdom2.nfg0000644000076500007650000000057611350032206015247 00000000000000NFG 1 R "Two person 4x4 game needing mixed domination" { "Player 1" "Player 2" } { { "1" "2" "3" "4" } { "1" "2" "3" "4" } } "" { { "" 4, -4 } { "" 6, -6 } { "" 7, -7 } { "" 5, -5 } { "" 1, -1 } { "" 5, -5 } { "" 2, -2 } { "" 7, -7 } { "" 2, -2 } { "" 7, -7 } { "" 4, -4 } { "" 1, -1 } { "" 3, -3 } { "" 2, -2 } { "" 1, -1 } { "" 6, -6 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 gambit-0.2010.09.01/contrib/games/montyhal.efg0000644000076500007650000000453311350032206015507 00000000000000EFG 2 R "The Monty Hall 'Lets make a deal' problem" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "DOOR A" 1/3 "DOOR B" 1/3 "DOOR C" 1/3 } 0 p "" 1 1 "(1,1)" { "DOOR A" "DOOR B" "DOOR C" } 0 p "" 2 1 "(2,1)" { "DOOR B" "DOOR C" } 0 p "" 1 2 "(1,2)" { "STAY" "SWITCH" } 0 t "" 1 "Outcome 1" { 100, 1 } t "" 2 "Outcome 2" { 0, 1 } p "" 1 3 "(1,3)" { "STAY" "SWITCH" } 0 t "" 1 "Outcome 1" { 100, 1 } t "" 2 "Outcome 2" { 0, 1 } p "" 2 2 "(2,4)" { "DOOR A" "DOOR C" } 0 p "" 1 4 "(1,4)" { "STAY" "SWITCH" } 0 t "" 3 "Outcome 3" { 0, 0 } t "" 3 "Outcome 3" { 0, 0 } p "" 1 5 "(1,5)" { "STAY" "SWITCH" } 0 t "" 2 "Outcome 2" { 0, 1 } t "" 1 "Outcome 1" { 100, 1 } p "" 2 3 "(2,7)" { "DOOR A" "DOOR B" } 0 p "" 1 6 "(1,6)" { "STAY" "SWITCH" } 0 t "" 3 "Outcome 3" { 0, 0 } t "" 3 "Outcome 3" { 0, 0 } p "" 1 7 "(1,7)" { "STAY" "SWITCH" } 0 t "" 2 "Outcome 2" { 0, 1 } t "" 1 "Outcome 1" { 100, 1 } p "" 1 1 "(1,1)" { "DOOR A" "DOOR B" "DOOR C" } 0 p "" 2 4 "(2,2)" { "DOOR B" "DOOR C" } 0 p "" 1 2 "(1,2)" { "STAY" "SWITCH" } 0 t "" 3 "Outcome 3" { 0, 0 } t "" 3 "Outcome 3" { 0, 0 } p "" 1 3 "(1,3)" { "STAY" "SWITCH" } 0 t "" 2 "Outcome 2" { 0, 1 } t "" 1 "Outcome 1" { 100, 1 } p "" 2 5 "(2,6)" { "DOOR A" "DOOR C" } 0 p "" 1 4 "(1,4)" { "STAY" "SWITCH" } 0 t "" 1 "Outcome 1" { 100, 1 } t "" 2 "Outcome 2" { 0, 1 } p "" 1 5 "(1,5)" { "STAY" "SWITCH" } 0 t "" 1 "Outcome 1" { 100, 1 } t "" 2 "Outcome 2" { 0, 1 } p "" 2 6 "(2,9)" { "DOOR A" "DOOR B" } 0 p "" 1 6 "(1,6)" { "STAY" "SWITCH" } 0 t "" 2 "Outcome 2" { 0, 1 } t "" 1 "Outcome 1" { 100, 1 } p "" 1 7 "(1,7)" { "STAY" "SWITCH" } 0 t "" 3 "Outcome 3" { 0, 0 } t "" 3 "Outcome 3" { 0, 0 } p "" 1 1 "(1,1)" { "DOOR A" "DOOR B" "DOOR C" } 0 p "" 2 7 "(2,3)" { "DOOR B" "DOOR C" } 0 p "" 1 2 "(1,2)" { "STAY" "SWITCH" } 0 t "" 2 "Outcome 2" { 0, 1 } t "" 1 "Outcome 1" { 100, 1 } p "" 1 3 "(1,3)" { "STAY" "SWITCH" } 0 t "" 3 "Outcome 3" { 0, 0 } t "" 3 "Outcome 3" { 0, 0 } p "" 2 8 "(2,5)" { "DOOR A" "DOOR C" } 0 p "" 1 4 "(1,4)" { "STAY" "SWITCH" } 0 t "" 2 "Outcome 2" { 0, 1 } t "" 1 "Outcome 1" { 100, 1 } p "" 1 5 "(1,5)" { "STAY" "SWITCH" } 0 t "" 3 "Outcome 3" { 0, 0 } t "" 3 "Outcome 3" { 0, 0 } p "" 2 9 "(2,8)" { "DOOR A" "DOOR B" } 0 p "" 1 6 "(1,6)" { "STAY" "SWITCH" } 0 t "" 1 "Outcome 1" { 100, 1 } t "" 2 "Outcome 2" { 0, 1 } p "" 1 7 "(1,7)" { "STAY" "SWITCH" } 0 t "" 1 "Outcome 1" { 100, 1 } t "" 2 "Outcome 2" { 0, 1 } gambit-0.2010.09.01/contrib/games/my_2-1.efg0000644000076500007650000000110511350032206014650 00000000000000EFG 2 R "Myerson (Game Theory), Exercise 2.1" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "High Cost" 1/2 "Low Cost" 1/2 } 0 p "" 1 1 "(1,1)" { "Build" "Not" } 0 p "" 2 1 "(2,1)" { "Enter" "Not" } 0 t "" 1 "Outcome 1" { -10, 2 } t "" 2 "Outcome 2" { -4, 0 } p "" 2 2 "(2,2)" { "Enter" "Not" } 0 t "" 3 "Outcome 3" { -6, 2 } t "" 4 "Outcome 4" { 0, 0 } p "" 1 2 "(1,2)" { "Build" "Not" } 0 p "" 2 1 "(2,1)" { "Enter" "Not" } 0 t "" 5 "Outcome 5" { 0, -4 } t "" 6 "Outcome 6" { 6, 0 } p "" 2 2 "(2,2)" { "Enter" "Not" } 0 t "" 7 "Outcome 7" { -2, -4 } t "" 8 "Outcome 8" { 4, 0 } gambit-0.2010.09.01/contrib/games/my_2-4.efg0000644000076500007650000000063511350032206014662 00000000000000EFG 2 R "Myerson (Game Theory), Exercise 2.4" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "1" 2/3 "2" 1/3 } 0 p "" 1 1 "(1,1)" { "W1" "X1" } 0 p "" 2 1 "(2,1)" { "a1" "b1" } 0 t "" 1 "Outcome 1" { 9, 5 } t "" 2 "Outcome 2" { 0, 3 } t "" 3 "Outcome 3" { 5, 6 } p "" 1 2 "(1,2)" { "Y1" "Z1" } 0 p "" 2 1 "(2,1)" { "a1" "b1" } 0 t "" 4 "Outcome 4" { 9, 0 } t "" 5 "Outcome 5" { 0, 3 } t "" 6 "Outcome 6" { 2, 6 } gambit-0.2010.09.01/contrib/games/my_2-8.efg0000644000076500007650000000365111350032206014667 00000000000000EFG 2 R "Myerson (Game Theory), Exercise 2.8" { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "(1,1)" { "A" "B" "C" } 0 p "" 2 1 "(2,1)" { "A" "B" "C" } 0 p "" 3 1 "(3,1)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } t "" 1 "Outcome 1" { 8, 0, 4 } t "" 1 "Outcome 1" { 8, 0, 4 } p "" 3 1 "(3,1)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } t "" 2 "Outcome 2" { 4, 8, 0 } p "" 1 2 "(1,2)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } t "" 2 "Outcome 2" { 4, 8, 0 } t "" 3 "Outcome 3" { 0, 4, 8 } p "" 3 1 "(3,1)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } p "" 1 2 "(1,2)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } t "" 2 "Outcome 2" { 4, 8, 0 } t "" 3 "Outcome 3" { 0, 4, 8 } t "" 3 "Outcome 3" { 0, 4, 8 } p "" 2 1 "(2,1)" { "A" "B" "C" } 0 p "" 3 1 "(3,1)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } t "" 2 "Outcome 2" { 4, 8, 0 } p "" 1 3 "(1,3)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } t "" 2 "Outcome 2" { 4, 8, 0 } t "" 3 "Outcome 3" { 0, 4, 8 } p "" 3 1 "(3,1)" { "A" "B" "C" } 0 t "" 2 "Outcome 2" { 4, 8, 0 } t "" 2 "Outcome 2" { 4, 8, 0 } t "" 2 "Outcome 2" { 4, 8, 0 } p "" 3 1 "(3,1)" { "A" "B" "C" } 0 p "" 1 3 "(1,3)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } t "" 2 "Outcome 2" { 4, 8, 0 } t "" 3 "Outcome 3" { 0, 4, 8 } t "" 2 "Outcome 2" { 4, 8, 0 } t "" 3 "Outcome 3" { 0, 4, 8 } p "" 2 1 "(2,1)" { "A" "B" "C" } 0 p "" 3 1 "(3,1)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } p "" 1 4 "(1,4)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } t "" 2 "Outcome 2" { 4, 8, 0 } t "" 3 "Outcome 3" { 0, 4, 8 } t "" 3 "Outcome 3" { 0, 4, 8 } p "" 3 1 "(3,1)" { "A" "B" "C" } 0 p "" 1 4 "(1,4)" { "A" "B" "C" } 0 t "" 1 "Outcome 1" { 8, 0, 4 } t "" 2 "Outcome 2" { 4, 8, 0 } t "" 3 "Outcome 3" { 0, 4, 8 } t "" 2 "Outcome 2" { 4, 8, 0 } t "" 3 "Outcome 3" { 0, 4, 8 } p "" 3 1 "(3,1)" { "A" "B" "C" } 0 t "" 3 "Outcome 3" { 0, 4, 8 } t "" 3 "Outcome 3" { 0, 4, 8 } t "" 3 "Outcome 3" { 0, 4, 8 } gambit-0.2010.09.01/contrib/games/my_3-3a.efg0000644000076500007650000000044011350032206015015 00000000000000EFG 2 R "Myerson (Game Theory), Exercise 3.3a" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "x1" "y1" } 0 p "" 2 1 "(2,1)" { "x2" "y2" } 0 t "" 1 "Outcome 1" { 2, 1 } t "" 2 "Outcome 2" { 1, 2 } p "" 2 1 "(2,1)" { "x2" "y2" } 0 t "" 3 "Outcome 3" { 1, 5 } t "" 4 "Outcome 4" { 2, 1 } gambit-0.2010.09.01/contrib/games/my_3-3b.efg0000644000076500007650000000044011350032206015016 00000000000000EFG 2 R "Myerson (Game Theory), Exercise 3.3b" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "x1" "y1" } 0 p "" 2 1 "(2,1)" { "x2" "y2" } 0 t "" 1 "Outcome 1" { 3, 7 } t "" 2 "Outcome 2" { 6, 6 } p "" 2 1 "(2,1)" { "x2" "y2" } 0 t "" 3 "Outcome 3" { 2, 2 } t "" 4 "Outcome 4" { 7, 3 } gambit-0.2010.09.01/contrib/games/my_3-3c.efg0000644000076500007650000000044011350032206015017 00000000000000EFG 2 R "Myerson (Game Theory), Exercise 3.3c" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "x1" "y1" } 0 p "" 2 1 "(2,1)" { "x2" "y2" } 0 t "" 1 "Outcome 1" { 7, 3 } t "" 2 "Outcome 2" { 6, 6 } p "" 2 1 "(2,1)" { "x2" "y2" } 0 t "" 3 "Outcome 3" { 2, 2 } t "" 4 "Outcome 4" { 3, 7 } gambit-0.2010.09.01/contrib/games/my_3-3d.efg0000644000076500007650000000054211350032206015023 00000000000000EFG 2 R "Myerson (Game Theory), Exercise 3.3d" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "x1" "y1" } 0 p "" 2 1 "(2,1)" { "x2" "y2" "z2" } 0 t "" 1 "Outcome 1" { 0, 4 } t "" 2 "Outcome 2" { 5, 6 } t "" 3 "Outcome 3" { 8, 7 } p "" 2 1 "(2,1)" { "x2" "y2" "z2" } 0 t "" 4 "Outcome 4" { 2, 9 } t "" 5 "Outcome 5" { 6, 5 } t "" 6 "Outcome 6" { 5, 1 } gambit-0.2010.09.01/contrib/games/my_3-3e.efg0000644000076500007650000000074011350032206015024 00000000000000EFG 2 R "Myerson (Game Theory), Exercise 3.3e" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "x1" "y1" "3" } 0 p "" 2 1 "(2,1)" { "x2" "y2" "z2" } 0 t "" 1 "Outcome 1" { 0, 0 } t "" 2 "Outcome 2" { 5, 4 } t "" 3 "Outcome 3" { 4, 5 } p "" 2 1 "(2,1)" { "x2" "y2" "z2" } 0 t "" 4 "Outcome 4" { 4, 5 } t "" 5 "Outcome 5" { 0, 0 } t "" 6 "Outcome 6" { 5, 4 } p "" 2 1 "(2,1)" { "x2" "y2" "z2" } 0 t "" 7 "Outcome 7" { 5, 4 } t "" 8 "Outcome 8" { 4, 5 } t "" 9 "Outcome 9" { 0, 0 } gambit-0.2010.09.01/contrib/games/my_3-4.efg0000644000076500007650000000106611350032206014662 00000000000000EFG 2 R "Myerson (Game Theory), Exercise 3.4" { "Player 1" "Player 2" "Player 3" } "" p "" 1 1 "(1,1)" { "x1" "y1" } 0 p "" 2 1 "(2,1)" { "x2" "y2" } 0 p "" 3 1 "(3,1)" { "x3" "y3" } 0 t "" 1 "Outcome 1" { 0, 0, 0 } t "" 2 "Outcome 2" { 6, 5, 4 } p "" 3 1 "(3,1)" { "x3" "y3" } 0 t "" 3 "Outcome 3" { 5, 4, 6 } t "" 4 "Outcome 4" { 0, 0, 0 } p "" 2 1 "(2,1)" { "x2" "y2" } 0 p "" 3 1 "(3,1)" { "x3" "y3" } 0 t "" 5 "Outcome 5" { 4, 6, 5 } t "" 6 "Outcome 6" { 0, 0, 0 } p "" 3 1 "(3,1)" { "x3" "y3" } 0 t "" 7 "Outcome 7" { 0, 0, 0 } t "" 8 "Outcome 8" { 0, 0, 0 } gambit-0.2010.09.01/contrib/games/myerson.efg0000644000076500007650000000065211350032206015346 00000000000000EFG 2 R "Myerson - Game with no solution in behavioral strategies" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "1" "2" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 1 "Outcome 1" { -1, 1 } p "" 1 2 "(1,2)" { "1" "2" } 0 t "" 2 "Outcome 2" { 1, -1 } t "" 1 "Outcome 1" { -1, 1 } p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 1 2 "(1,2)" { "1" "2" } 0 t "" 1 "Outcome 1" { -1, 1 } t "" 2 "Outcome 2" { 1, -1 } t "" 1 "Outcome 1" { -1, 1 } gambit-0.2010.09.01/contrib/games/nim.efg0000644000076500007650000000123011350032206014426 00000000000000EFG 2 R "Nim, starting with Five Stones." { "Player 1" "Player 2" } p "5 left" 1 1 "(1,1)" { "TAKE 1" "TAKE 2" } 0 p "4 left" 2 1 "(2,1)" { "TAKE 1" "TAKE 2" } 0 p "3 left" 1 2 "(1,2)" { "TAKE 1" "TAKE 2" } 0 p "2 left" 2 2 "(2,3)" { "TAKE 1" "TAKE 2" } 0 t "1 left" 1 "Outcome 1" { 1 -1 } t "0 left" 2 "Outcome 2" { -1 1 } t "1 left" 2 "Outcome 2" { -1 1 } p "2 left" 1 3 "(1,3)" { "TAKE 1" "TAKE 2" } 0 t "1 left" 2 "Outcome 2" { -1 1 } t "0 left" 1 "Outcome 1" { 1 -1 } p "" 2 3 "(2,2)" { "TAKE 1" "TAKE 2" } 0 p "2 left" 1 4 "(1,4)" { "TAKE 1" "TAKE 2" } 0 t "1 left" 2 "Outcome 2" { -1 1 } t "0 left" 1 "Outcome 1" { 1 -1 } t "1 left" 2 "Outcome 2" { -1 1 } gambit-0.2010.09.01/contrib/games/nim7.efg0000644000076500007650000000326511350032206014527 00000000000000EFG 2 R "Nim, starting with Seven Stones." { "Player 1" "Player 2" } p "7 left" 2 1 "(2,4)" { "take 2" "take 1" } 0 p "5 left" 1 1 "(1,1)" { "take_2" "take_1" } 0 p "3_left" 2 2 "(2,1)" { "take_2" "take_1" } 0 t "1_left" 1 "Outcome 1" { 1 -1 } p "2_left" 1 2 "(1,2)" { "take_2" "take_1" } 0 t "0_left" 1 "Outcome 1" { 1 -1 } t "1_left" 2 "Outcome 2" { -1 1 } p "4_left" 2 3 "(2,2)" { "take_2" "take_1" } 0 p "2_left" 1 3 "(1,3)" { "take_2" "take_1" } 0 t "0_left" 1 "Outcome 1" { 1 -1 } t "1_left" 2 "Outcome 2" { -1 1 } p "3_left" 1 4 "(1,4)" { "take_2" "take_1" } 0 t "1_left" 2 "Outcome 2" { -1 1 } p "2_left" 2 4 "(2,3)" { "take_2" "take_1" } 0 t "0_left" 2 "Outcome 2" { -1 1 } t "1_left" 1 "Outcome 1" { 1 -1 } p "6 left" 1 5 "(1,5)" { "take 2" "2" } 0 p "4 left" 2 5 "(2,5)" { "take_2" "take_1" } 0 p "2_left" 1 6 "(1,6)" { "take_2" "take_1" } 0 t "0_left" 1 "Outcome 1" { 1 -1 } t "1_left" 2 "Outcome 2" { -1 1 } p "3_left" 1 7 "(1,7)" { "take_2" "take_1" } 0 t "1_left" 2 "Outcome 2" { -1 1 } p "2_left" 2 6 "(2,6)" { "take_2" "take_1" } 0 t "0_left" 2 "Outcome 2" { -1 1 } t "1_left" 1 "Outcome 1" { 1 -1 } p "" 2 7 "(2,7)" { "take_2" "take_1" } 0 p "3_left" 1 8 "(1,8)" { "take_2" "take_1" } 0 t "1_left" 2 "Outcome 2" { -1 1 } p "2_left" 2 8 "(2,8)" { "take_2" "take_1" } 0 t "0_left" 2 "Outcome 2" { -1 1 } t "1_left" 1 "Outcome 1" { 1 -1 } p "4_left" 1 9 "(1,9)" { "take_2" "take_1" } 0 p "2_left" 2 9 "(2,9)" { "take_2" "take_1" } 0 t "0_left" 2 "Outcome 2" { -1 1 } t "1_left" 1 "Outcome 1" { 1 -1 } p "3_left" 2 10 "(2,10)" { "take_2" "take_1" } 0 t "1_left" 1 "Outcome 1" { 1 -1 } p "2_left" 1 10 "(1,10)" { "take_2" "take_1" } 0 t "0_left" 1 "Outcome 1" { 1 -1 } t "1_left" 2 "Outcome 2" { -1 1 } gambit-0.2010.09.01/contrib/games/oneill.nfg0000644000076500007650000000055711350032206015151 00000000000000NFG 1 R "Oneill's (1987 Proc NAS) game" { "Player 1" "Player 2" } { { "1" "2" "3" "4" } { "1" "2" "3" "4" } } "" { { "" 1, -1 } { "" -1, 1 } { "" -1, 1 } { "" -1, 1 } { "" -1, 1 } { "" -1, 1 } { "" 1, -1 } { "" 1, -1 } { "" -1, 1 } { "" 1, -1 } { "" -1, 1 } { "" 1, -1 } { "" -1, 1 } { "" 1, -1 } { "" 1, -1 } { "" -1, 1 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 gambit-0.2010.09.01/contrib/games/palf.efg0000644000076500007650000000202211350032206014565 00000000000000EFG 2 R "McKelvey-Palfrey: one stage mixed strategy learning game" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "1" 1/2 "2" 1/2 } 0 c "" 2 "(0,2)" { "1" 1/2 "2" 1/2 } 0 p "" 1 1 "(1,1)" { "1" "2" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 1 "Outcome 1" { 2, 2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 3 "Outcome 3" { 5, 0 } t "" 4 "Outcome 4" { 1, 4 } p "" 1 1 "(1,1)" { "1" "2" } 0 p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 5 "Outcome 5" { 2, 4 } t "" 6 "Outcome 6" { 3, 0 } p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 7 "Outcome 7" { 5, 0 } t "" 8 "Outcome 8" { 1, 2 } c "" 3 "(0,3)" { "1" 1/2 "2" 1/2 } 0 p "" 1 2 "(1,2)" { "1" "2" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 9 "Outcome 9" { 1, 2 } t "" 10 "Outcome 10" { 5, 0 } p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 11 "Outcome 11" { 3, 0 } t "" 12 "Outcome 12" { 2, 4 } p "" 1 2 "(1,2)" { "1" "2" } 0 p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 13 "Outcome 13" { 1, 4 } t "" 14 "Outcome 14" { 5, 0 } p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 15 "Outcome 15" { 3, 0 } t "" 16 "Outcome 16" { 2, 2 } gambit-0.2010.09.01/contrib/games/palf2.efg0000644000076500007650000001026011350032206014652 00000000000000EFG 2 R "McKelvey-Palfrey: two stage mixed strategy learning game" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "1" 1/2 "2" 1/2 } 0 c "" 2 "(0,2)" { "1" 1/2 "2" 1/2 } 0 p "" 1 1 "(1,1)" { "1" "2" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 1 2 "(1,3)" { "1" "2" } 1 "Outcome 1" { 2, 2 } p "" 2 2 "(2,3)" { "1" "2" } 0 t "" 1 "Outcome 1" { 2, 2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 2 "(2,3)" { "1" "2" } 0 t "" 3 "Outcome 3" { 5, 0 } t "" 4 "Outcome 4" { 1, 4 } p "" 1 3 "(1,4)" { "1" "2" } 2 "Outcome 2" { 3, 0 } p "" 2 3 "(2,4)" { "1" "2" } 0 t "" 1 "Outcome 1" { 2, 2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 3 "(2,4)" { "1" "2" } 0 t "" 3 "Outcome 3" { 5, 0 } t "" 4 "Outcome 4" { 1, 4 } p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 1 4 "(1,5)" { "1" "2" } 3 "Outcome 3" { 5, 0 } p "" 2 4 "(2,5)" { "1" "2" } 0 t "" 1 "Outcome 1" { 2, 2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 4 "(2,5)" { "1" "2" } 0 t "" 3 "Outcome 3" { 5, 0 } t "" 4 "Outcome 4" { 1, 4 } p "" 1 5 "(1,6)" { "1" "2" } 4 "Outcome 4" { 1, 4 } p "" 2 5 "(2,6)" { "1" "2" } 0 t "" 1 "Outcome 1" { 2, 2 } t "" 2 "Outcome 2" { 3, 0 } p "" 2 5 "(2,6)" { "1" "2" } 0 t "" 3 "Outcome 3" { 5, 0 } t "" 4 "Outcome 4" { 1, 4 } p "" 1 1 "(1,1)" { "1" "2" } 0 p "" 2 6 "(2,2)" { "1" "2" } 0 p "" 1 2 "(1,3)" { "1" "2" } 5 "Outcome 5" { 2, 4 } p "" 2 7 "(2,7)" { "1" "2" } 0 t "" 5 "Outcome 5" { 2, 4 } t "" 6 "Outcome 6" { 3, 0 } p "" 2 7 "(2,7)" { "1" "2" } 0 t "" 7 "Outcome 7" { 5, 0 } t "" 8 "Outcome 8" { 1, 2 } p "" 1 3 "(1,4)" { "1" "2" } 6 "Outcome 6" { 3, 0 } p "" 2 8 "(2,8)" { "1" "2" } 0 t "" 5 "Outcome 5" { 2, 4 } t "" 6 "Outcome 6" { 3, 0 } p "" 2 8 "(2,8)" { "1" "2" } 0 t "" 7 "Outcome 7" { 5, 0 } t "" 8 "Outcome 8" { 1, 2 } p "" 2 6 "(2,2)" { "1" "2" } 0 p "" 1 4 "(1,5)" { "1" "2" } 7 "Outcome 7" { 5, 0 } p "" 2 9 "(2,9)" { "1" "2" } 0 t "" 5 "Outcome 5" { 2, 4 } t "" 6 "Outcome 6" { 3, 0 } p "" 2 9 "(2,9)" { "1" "2" } 0 t "" 7 "Outcome 7" { 5, 0 } t "" 8 "Outcome 8" { 1, 2 } p "" 1 5 "(1,6)" { "1" "2" } 8 "Outcome 8" { 1, 2 } p "" 2 10 "(2,10)" { "1" "2" } 0 t "" 5 "Outcome 5" { 2, 4 } t "" 6 "Outcome 6" { 3, 0 } p "" 2 10 "(2,10)" { "1" "2" } 0 t "" 7 "Outcome 7" { 5, 0 } t "" 8 "Outcome 8" { 1, 2 } c "" 3 "(0,3)" { "1" 1/2 "2" 1/2 } 0 p "" 1 6 "(1,2)" { "1" "2" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 1 7 "(1,7)" { "1" "2" } 9 "Outcome 9" { 1, 2 } p "" 2 2 "(2,3)" { "1" "2" } 0 t "" 9 "Outcome 9" { 1, 2 } t "" 10 "Outcome 10" { 2, 2 } p "" 2 2 "(2,3)" { "1" "2" } 0 t "" 11 "Outcome 11" { 3, 0 } t "" 12 "Outcome 12" { 2, 4 } p "" 1 8 "(1,8)" { "1" "2" } 13 "Outcome a" { 5, 0 } p "" 2 3 "(2,4)" { "1" "2" } 0 t "" 9 "Outcome 9" { 1, 2 } t "" 10 "Outcome 10" { 2, 2 } p "" 2 3 "(2,4)" { "1" "2" } 0 t "" 11 "Outcome 11" { 3, 0 } t "" 12 "Outcome 12" { 2, 4 } p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 1 9 "(1,9)" { "1" "2" } 14 "Outcome b" { 3, 0 } p "" 2 4 "(2,5)" { "1" "2" } 0 t "" 9 "Outcome 9" { 1, 2 } t "" 10 "Outcome 10" { 2, 2 } p "" 2 4 "(2,5)" { "1" "2" } 0 t "" 11 "Outcome 11" { 3, 0 } t "" 12 "Outcome 12" { 2, 4 } p "" 1 10 "(1,10)" { "1" "2" } 15 "Outcome c" { 2, 4 } p "" 2 5 "(2,6)" { "1" "2" } 0 t "" 9 "Outcome 9" { 1, 2 } t "" 10 "Outcome 10" { 2, 2 } p "" 2 5 "(2,6)" { "1" "2" } 0 t "" 11 "Outcome 11" { 3, 0 } t "" 12 "Outcome 12" { 2, 4 } p "" 1 6 "(1,2)" { "1" "2" } 0 p "" 2 6 "(2,2)" { "1" "2" } 0 p "" 1 7 "(1,7)" { "1" "2" } 16 "Outcome d" { 1, 4 } p "" 2 7 "(2,7)" { "1" "2" } 0 t "" 17 "Outcome 13" { 1, 4 } t "" 18 "Outcome 14" { 5, 0 } p "" 2 7 "(2,7)" { "1" "2" } 0 t "" 19 "Outcome 15" { 3, 0 } t "" 20 "Outcome 16" { 2, 2 } p "" 1 8 "(1,8)" { "1" "2" } 21 "Outcome e" { 5, 0 } p "" 2 8 "(2,8)" { "1" "2" } 0 t "" 17 "Outcome 13" { 1, 4 } t "" 18 "Outcome 14" { 5, 0 } p "" 2 8 "(2,8)" { "1" "2" } 0 t "" 19 "Outcome 15" { 3, 0 } t "" 20 "Outcome 16" { 2, 2 } p "" 2 6 "(2,2)" { "1" "2" } 0 p "" 1 9 "(1,9)" { "1" "2" } 22 "Outcome f" { 3, 0 } p "" 2 9 "(2,9)" { "1" "2" } 0 t "" 17 "Outcome 13" { 1, 4 } t "" 18 "Outcome 14" { 5, 0 } p "" 2 9 "(2,9)" { "1" "2" } 0 t "" 19 "Outcome 15" { 3, 0 } t "" 20 "Outcome 16" { 2, 2 } p "" 1 10 "(1,10)" { "1" "2" } 10 "Outcome 10" { 2, 2 } p "" 2 10 "(2,10)" { "1" "2" } 0 t "" 17 "Outcome 13" { 1, 4 } t "" 18 "Outcome 14" { 5, 0 } p "" 2 10 "(2,10)" { "1" "2" } 0 t "" 19 "Outcome 15" { 3, 0 } t "" 20 "Outcome 16" { 2, 2 } gambit-0.2010.09.01/contrib/games/palf3.efg0000644000076500007650000000412711350032206014660 00000000000000EFG 2 R "Palfrey one sided incomplete info game with both types mixing" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "1" 3/8 "2" 5/8 } 0 p "" 1 1 "(1,1)" { "1" "2" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 1 2 "(1,2)" { "1" "2" } 1 "Outcome 1" { 4, 0 } p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 1 "Outcome 1" { 4, 0 } t "" 2 "Outcome 2" { 1, 1 } p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 3 "Outcome 3" { 2, 1 } t "" 4 "Outcome 4" { 0, 0 } p "" 1 3 "(1,3)" { "1" "2" } 2 "Outcome 2" { 1, 1 } p "" 2 3 "(2,3)" { "1" "2" } 0 t "" 1 "Outcome 1" { 4, 0 } t "" 2 "Outcome 2" { 1, 1 } p "" 2 3 "(2,3)" { "1" "2" } 0 t "" 3 "Outcome 3" { 2, 1 } t "" 4 "Outcome 4" { 0, 0 } p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 1 4 "(1,4)" { "1" "2" } 3 "Outcome 3" { 2, 1 } p "" 2 4 "(2,4)" { "1" "2" } 0 t "" 1 "Outcome 1" { 4, 0 } t "" 2 "Outcome 2" { 1, 1 } p "" 2 4 "(2,4)" { "1" "2" } 0 t "" 3 "Outcome 3" { 2, 1 } t "" 4 "Outcome 4" { 0, 0 } p "" 1 5 "(1,5)" { "1" "2" } 4 "Outcome 4" { 0, 0 } p "" 2 5 "(2,5)" { "1" "2" } 0 t "" 1 "Outcome 1" { 4, 0 } t "" 2 "Outcome 2" { 1, 1 } p "" 2 5 "(2,5)" { "1" "2" } 0 t "" 3 "Outcome 3" { 2, 1 } t "" 4 "Outcome 4" { 0, 0 } p "" 1 6 "(1,6)" { "1" "2" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 1 7 "(1,7)" { "1" "2" } 5 "Outcome 5" { 0, 0 } p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 5 "Outcome 5" { 0, 0 } t "" 6 "Outcome 6" { 2, 1 } p "" 2 2 "(2,2)" { "1" "2" } 0 t "" 7 "Outcome 7" { 1, 1 } t "" 8 "Outcome 8" { 4, 0 } p "" 1 8 "(1,8)" { "1" "2" } 6 "Outcome 6" { 2, 1 } p "" 2 3 "(2,3)" { "1" "2" } 0 t "" 5 "Outcome 5" { 0, 0 } t "" 6 "Outcome 6" { 2, 1 } p "" 2 3 "(2,3)" { "1" "2" } 0 t "" 7 "Outcome 7" { 1, 1 } t "" 8 "Outcome 8" { 4, 0 } p "" 2 1 "(2,1)" { "1" "2" } 0 p "" 1 9 "(1,9)" { "1" "2" } 7 "Outcome 7" { 1, 1 } p "" 2 4 "(2,4)" { "1" "2" } 0 t "" 5 "Outcome 5" { 0, 0 } t "" 6 "Outcome 6" { 2, 1 } p "" 2 4 "(2,4)" { "1" "2" } 0 t "" 7 "Outcome 7" { 1, 1 } t "" 8 "Outcome 8" { 4, 0 } p "" 1 10 "(1,10)" { "1" "2" } 8 "Outcome 8" { 4, 0 } p "" 2 5 "(2,5)" { "1" "2" } 0 t "" 5 "Outcome 5" { 0, 0 } t "" 6 "Outcome 6" { 2, 1 } p "" 2 5 "(2,5)" { "1" "2" } 0 t "" 7 "Outcome 7" { 1, 1 } t "" 8 "Outcome 8" { 4, 0 } gambit-0.2010.09.01/contrib/games/pd.nfg0000644000076500007650000000024711350032206014266 00000000000000NFG 1 R "Two person Prisoner's Dilemma game" { "Player 1" "Player 2" } { { "1" "2" } { "1" "2" } } "" { { "" 9, 9 } { "" 10, 0 } { "" 0, 10 } { "" 1, 1 } } 1 2 3 4 gambit-0.2010.09.01/contrib/games/perfect1.nfg0000644000076500007650000000044311350032206015372 00000000000000NFG 1 R "Game with no dominated strategies, and dominated equilibrium" { "Player 1" "Player 2" } { { "1" "2" "3" } { "1" "2" "3" } } "" { { "11" 3, 1 } { "12" 0, 0 } { "13" 0, 1 } { "21" 3/2, 1 } { "22" 2, 2 } { "23" 3/2, 1 } { "31" 0, 1 } { "32" 0, 0 } { "33" 3, 1 } } 1 4 7 2 5 8 3 6 9 gambit-0.2010.09.01/contrib/games/perfect2.nfg0000644000076500007650000000045411350032206015375 00000000000000NFG 1 R "Game with no dominated pure strategies but with dominated Nash equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" } { "1" "2" "3" } } "" { { "11" 4, 0 } { "12" 0, 0 } { "13" 0, 4 } { "21" 2, 1 } { "22" 3, 3 } { "23" 2, 1 } { "31" 0, 4 } { "32" 0, 0 } { "33" 4, 0 } } 1 4 7 2 5 8 3 6 9 gambit-0.2010.09.01/contrib/games/perfect3.nfg0000644000076500007650000000047211350032206015376 00000000000000NFG 1 R "Three person version of perfect2" { "Player 1" "Player 2" "Player 3" } { { "1" "2" "3" } { "1" "2" "3" } { "1" } } "" { { "111" 4, 0, 1 } { "121" 0, 0, 1 } { "131" 0, 4, 1 } { "211" 2, 1, 1 } { "221" 3, 3, 1 } { "231" 2, 1, 1 } { "311" 0, 4, 1 } { "321" 0, 0, 1 } { "331" 4, 0, 1 } } 1 4 7 2 5 8 3 6 9 gambit-0.2010.09.01/contrib/games/poker.efg0000644000076500007650000000065511350032206014775 00000000000000EFG 2 R "A simple Poker game" { "Fred" "Alice" } "This is a simple game of one-card poker from Myerson (1991)." c "" 1 "" { "Red" 1/2 "Black" 1/2 } 0 p "" 1 1 "" { "Raise" "Fold" } 0 p "" 2 1 "" { "Meet" "Pass" } 0 t "" 1 "Win Big" { 2, -2 } t "" 2 "Win" { 1, -1 } t "" 2 "Win" { 1, -1 } p "" 1 2 "" { "Raise" "Fold" } 0 p "" 2 1 "" { "Meet" "Pass" } 0 t "" 3 "Lose Big" { -2, 2 } t "" 2 "Win" { 1, -1 } t "" 4 "Lose" { -1, 1 } gambit-0.2010.09.01/contrib/games/poker.nfg0000644000076500007650000000040711350032206015001 00000000000000NFG 1 R "A simple two person poker game in normal form" { "Player 1" "Player 2" } { { "1" "2" "3" "4" } { "1" "2" } } "" { { "" -1, 1 } { "" -0.5, 0.5 } { "" -0.5, 0.5 } { "" 0, 0 } { "" -1, 1 } { "" 0.5, -0.5 } { "" -2.5, 2.5 } { "" -1, 1 } } 1 2 3 4 5 6 7 8 gambit-0.2010.09.01/contrib/games/poker2.efg0000644000076500007650000000074011350032206015052 00000000000000EFG 2 R "A Simple Poker Game with an initial ante" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "RED" 0.500000 "BLACK" 0.500000 } 1 "Outcome 3" { -1, 1 } p "" 1 1 "(1,1)" { "RAISE" "FOLD" } 0 p "" 2 1 "(2,1)" { "MEET" "PASS" } 0 t "" 2 "Outcome 2" { 2, -2 } t "" 3 "Outcome 1" { 1, -1 } t "" 1 "Outcome 3" { -1, 1 } p "" 1 2 "(1,2)" { "RAISE" "FOLD" } 0 p "" 2 1 "(2,1)" { "MEET" "PASS" } 0 t "" 4 "Outcome 4" { -2, 2 } t "" 3 "Outcome 1" { 1, -1 } t "" 1 "Outcome 3" { -1, 1 } gambit-0.2010.09.01/contrib/games/pvw.efg0000644000076500007650000000121611350032206014463 00000000000000EFG 2 R "Game from van Winden" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "White" 2/3 "Black" 1/3 } 0 p "" 1 1 "(1,1)" { "White" "Black" "No message" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 1 "1" { 3/2, 3 } t "" 2 "2" { 7/2, 1 } p "" 2 2 "(2,3)" { "1" "2" } 0 t "" 1 "1" { 3/2, 3 } t "" 2 "2" { 7/2, 1 } p "" 2 3 "(2,2)" { "1" "2" } 0 t "" 3 "3" { 2, 3 } t "" 4 "4" { 4, 1 } p "" 1 2 "(1,2)" { "White" "Black" "No message" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 5 "5" { 1/2, 0 } t "" 6 "6" { 13/2, 1 } p "" 2 2 "(2,3)" { "1" "2" } 0 t "" 5 "5" { 1/2, 0 } t "" 6 "6" { 13/2, 1 } p "" 2 3 "(2,2)" { "1" "2" } 0 t "" 7 "7" { 1, 0 } t "" 8 "8" { 7, 1 } gambit-0.2010.09.01/contrib/games/pvw2.efg0000644000076500007650000000122011350032206014540 00000000000000EFG 2 R "Game 2 from van Winden" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "White" 1/2 "Black" 1/2 } 0 p "" 1 1 "(1,1)" { "White" "Black" "No message" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 1 "1" { 3/2, 4 } t "" 2 "2" { 7/2, 0 } p "" 2 2 "(2,3)" { "1" "2" } 0 t "" 1 "1" { 3/2, 4 } t "" 2 "2" { 7/2, 0 } p "" 2 3 "(2,2)" { "1" "2" } 0 t "" 3 "3" { 2, 4 } t "" 4 "4" { 4, 0 } p "" 1 2 "(1,2)" { "White" "Black" "No message" } 0 p "" 2 1 "(2,1)" { "1" "2" } 0 t "" 5 "5" { 1/2, 0 } t "" 6 "6" { 13/2, 3 } p "" 2 2 "(2,3)" { "1" "2" } 0 t "" 5 "5" { 1/2, 0 } t "" 6 "6" { 13/2, 3 } p "" 2 3 "(2,2)" { "1" "2" } 0 t "" 7 "7" { 1, 0 } t "" 8 "8" { 7, 3 } gambit-0.2010.09.01/contrib/games/sh3.efg0000644000076500007650000000077411350032206014354 00000000000000EFG 2 R "Wilson's example of inaccessible equilibria (Shapley, 1974, Math Prog Stud)" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "1" "2" "3" } 0 p "" 2 1 "(2,1)" { "1" "2" "3" } 0 t "" 1 "Outcome 1" { 0, 0 } t "" 2 "Outcome 2" { 3, 2 } t "" 3 "Outcome 3" { 0, 3 } p "" 2 1 "(2,1)" { "1" "2" "3" } 0 t "" 4 "Outcome 4" { 2, 3 } t "" 5 "Outcome 5" { 2, 2 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 1 "(2,1)" { "1" "2" "3" } 0 t "" 7 "Outcome 7" { 3, 0 } t "" 8 "Outcome 8" { 0, 0 } t "" 9 "Outcome 9" { 1, 1 } gambit-0.2010.09.01/contrib/games/sh3.nfg0000644000076500007650000000047111350032206014357 00000000000000NFG 1 D "Wilson's example of inaccessible equilibria (Shapley, 1974, Math Prog Stud)" { "Player 1" "Player 2" } { { "1" "2" "3" } { "1" "2" "3" } } 0.000000 0.000000 2.000000 3.000000 3.000000 0.000000 3.000000 2.000000 2.000000 2.000000 0.000000 0.000000 0.000000 3.000000 0.000000 0.000000 1.000000 1.000000 gambit-0.2010.09.01/contrib/games/stengel.nfg0000644000076500007650000000120611350032206015320 00000000000000NFG 1 R "von Stengel's two person 6 x 6 game with 75 equilibria" { "1" "2" } { { "1" "2" "3" "4" "5" "6" } { "1" "2" "3" "4" "5" "6" } } 9504 72336 -111771 -461736 397584 1227336 171204 -1718376 1303104 1303104 737154 -453420 -660 48081 31680 -300036 -113850 774576 -45936 -1039236 -453420 737154 -227040 -227040 19976 29216 -130944 -178761 451176 451176 208626 -586476 1227336 397584 774576 -113850 -20526 14124 168124 -84436 -586476 208626 -263076 -263076 -1718376 171204 -1039236 -45936 1776 1776 -8514 -8976 29216 19976 14124 -20526 72336 9504 48081 -660 -8976 -8514 52764 52764 -178761 -130944 -84436 168124 -461736 -111771 -300036 31680 gambit-0.2010.09.01/contrib/games/sww1.efg0000644000076500007650000000034211350032206014547 00000000000000EFG 2 R "Schotter-Weigelt-Wilson (GEB 94), Fig 1" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "R" "L" } 0 p "" 2 1 "(2,1)" { "R" "L" } 0 t "" 1 "Outcome 1" { 6, 3 } t "" 2 "Outcome 2" { 0, 1 } t "" 3 "Outcome 3" { 4, 4 } gambit-0.2010.09.01/contrib/games/sww1.nfg0000644000076500007650000000023011350032206014554 00000000000000NFG 1 D "Schotter-Weigelt-Wilson Fig 1 game in normal form" { "" "" } { 2 2 } 4.000000 3.000000 0.000000 0.000000 4.000000 3.000000 6.000000 2.000000 gambit-0.2010.09.01/contrib/games/sww2.efg0000644000076500007650000000062311350032206014552 00000000000000EFG 2 R "Schotter-Weigelt-Wilson (GEB 94), Fig 2" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "R" "L" } 0 p "" 2 1 "(2,1)" { "L" "R" } 0 p "" 1 2 "(1,2)" { "T" "B" } 0 p "" 2 2 "(2,2)" { "T" "B" } 0 t "" 1 "Outcome 4" { 7, 0 } t "" 2 "Outcome 5" { 5, 6 } p "" 2 2 "(2,2)" { "T" "B" } 0 t "" 3 "Outcome 6" { 5, 6 } t "" 4 "Outcome 7" { 7, 0 } t "" 5 "Outcome 2" { 0, 1 } t "" 6 "Outcome 3" { 4, 4 } gambit-0.2010.09.01/contrib/games/sww3.efg0000644000076500007650000000062311350032206014553 00000000000000EFG 2 R "Schotter-Weigelt-Wilson (GEB 94), Fig 3" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "R" "L" } 0 p "" 2 1 "(2,1)" { "R" "L" } 0 p "" 1 2 "(1,2)" { "T" "B" } 0 p "" 2 2 "(2,2)" { "T" "B" } 0 t "" 1 "Outcome 7" { 6, 3 } t "" 2 "Outcome 5" { 0, 0 } p "" 2 2 "(2,2)" { "T" "B" } 0 t "" 3 "Outcome 6" { 0, 0 } t "" 4 "Outcome 4" { 3, 6 } t "" 5 "Outcome 2" { 0, 1 } t "" 6 "Outcome 3" { 4, 4 } gambit-0.2010.09.01/contrib/games/tim.efg0000644000076500007650000000336111350032206014443 00000000000000EFG 2 R "Game from Tim Feddersen" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "o_1 = 1" 0.490000 "o_1 = 0" 0.510000 } 0 p "" 1 1 "(1,1)" { "Specialize" "Not" } 0 p "" 1 2 "(1,2)" { "Hearing" "No Hearing" } 1 "Outcome 5" { -1/100, 0 } c "" 2 "(0,2)" { "o_2 = 1" 0.600000 "o_2 = 0" 0.400000 } 0 p "" 2 1 "(2,3)" { "1" "0" } 0 t "" 2 "Outcome 1" { -10, 0 } t "" 3 "Outcome 2" { -11, -1 } p "" 2 2 "(2,4)" { "1" "0" } 0 t "" 2 "Outcome 1" { -10, 0 } t "" 3 "Outcome 2" { -11, -1 } p "" 2 3 "(2,1)" { "1" "0" } 0 t "" 2 "Outcome 1" { -10, 0 } t "" 3 "Outcome 2" { -11, -1 } p "" 1 3 "(1,4)" { "Hearing" "No Hearing" } 0 c "" 3 "(0,3)" { "o_2 = 1" 0.600000 "o_2 = 0" 0.400000 } 0 p "" 2 4 "(2,5)" { "1" "0" } 0 t "" 2 "Outcome 1" { -10, 0 } t "" 3 "Outcome 2" { -11, -1 } p "" 2 5 "(2,6)" { "1" "0" } 0 t "" 2 "Outcome 1" { -10, 0 } t "" 3 "Outcome 2" { -11, -1 } p "" 2 6 "(2,2)" { "1" "0" } 0 t "" 2 "Outcome 1" { -10, 0 } t "" 3 "Outcome 2" { -11, -1 } p "" 1 1 "(1,1)" { "Specialize" "Not" } 0 p "" 1 4 "(1,3)" { "Hearing" "No Hearing" } 1 "Outcome 5" { -1/100, 0 } c "" 4 "(0,4)" { "o_2 = 1" 0.550000 "o_2 = 0" 0.450000 } 0 p "" 2 1 "(2,3)" { "1" "0" } 0 t "" 4 "Outcome 3" { -9, -1 } t "" 5 "Outcome 4" { -10, 0 } p "" 2 2 "(2,4)" { "1" "0" } 0 t "" 4 "Outcome 3" { -9, -1 } t "" 5 "Outcome 4" { -10, 0 } p "" 2 3 "(2,1)" { "1" "0" } 0 t "" 4 "Outcome 3" { -9, -1 } t "" 5 "Outcome 4" { -10, 0 } p "" 1 3 "(1,4)" { "Hearing" "No Hearing" } 0 c "" 5 "(0,5)" { "o_2 = 1" 0.550000 "o_2 = 0" 0.450000 } 0 p "" 2 4 "(2,5)" { "1" "0" } 0 t "" 4 "Outcome 3" { -9, -1 } t "" 5 "Outcome 4" { -10, 0 } p "" 2 5 "(2,6)" { "1" "0" } 0 t "" 4 "Outcome 3" { -9, -1 } t "" 5 "Outcome 4" { -10, 0 } p "" 2 6 "(2,2)" { "1" "0" } 0 t "" 4 "Outcome 3" { -9, -1 } t "" 5 "Outcome 4" { -10, 0 } gambit-0.2010.09.01/contrib/games/todd1.nfg0000644000076500007650000000055411350032206014677 00000000000000NFG 1 R "Todd's (incorrect) example of incaccessible equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" "4" "5" } { "1" "2" "3" } } "" { { "" 8, 4 } { "" 6, 0 } { "" 12, 0 } { "" 0, 0 } { "" 0, 0 } { "" -4, 0 } { "" 3, 0 } { "" 0, 4 } { "" 0, 4 } { "" 4, 1 } { "" 8, 0 } { "" 6, 4 } { "" 0, 0 } { "" 12, 0 } { "" 0, 0 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 gambit-0.2010.09.01/contrib/games/todd2.nfg0000644000076500007650000000055411350032206014700 00000000000000NFG 1 R "Todd's (corrected) example of incaccessible equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" "4" "5" } { "1" "2" "3" } } "" { { "" 8, 4 } { "" 6, 0 } { "" 12, 0 } { "" 0, 0 } { "" 0, 0 } { "" -4, 0 } { "" 1, 0 } { "" 0, 4 } { "" 0, 4 } { "" 4, 1 } { "" 8, 0 } { "" 6, 4 } { "" 0, 0 } { "" 12, 0 } { "" 0, 0 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 gambit-0.2010.09.01/contrib/games/todd3.nfg0000644000076500007650000000112311350032206014672 00000000000000NFG 1 R "Todd's second example of incaccessible equilibria" { "Player 1" "Player 2" } { { "1" "2" "3" "4" "5" "6" "7" } { "1" "2" "3" "4" } } "" { { "" 1, 1 } { "" 0, 1 } { "" 0, 1 } { "" 0, 1 } { "" 2/7, 0 } { "" 3/19, 0 } { "" 7/38, 0 } { "" 0, 0 } { "" 1, 0 } { "" 0, 0 } { "" 0, 0 } { "" 2/7, 1 } { "" 6/19, 0 } { "" 7/38, 0 } { "" 0, 0 } { "" 0, 0 } { "" 1, 0 } { "" 0, 0 } { "" 2/7, 0 } { "" 6/19, 1 } { "" 7/19, 0 } { "" 0, 0 } { "" 0, 0 } { "" 0, 0 } { "" 1, 0 } { "" 2/7, 0 } { "" 6/19, 0 } { "" 7/19, 1 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 gambit-0.2010.09.01/contrib/games/ttt.efg0000644000076500007650000001326611350032206014472 00000000000000EFG 2 R "Tic Tac Toe (Not finished yet)" { "Player 1" "Player 2" } "" p "ROOT" 1 1 "(1,1)" { "x-- --- ---" "-x- --- ---" "--- -x- ---" } 0 p "" 2 1 "(2,1)" { "xo- --- ---" "x-o --- ---" "x-- -o- ---" "x-- --0 ---" "x-- --- --0" } 0 p "" 1 2 "(1,2)" { "xox --- ---" "xo- x-- ---" "xo- -x- ---" "xo- --x ---" "xo- --- x--" "xo- --- -x-" "xo- --- --x" } 0 p "" 2 2 "(2,4)" { "xox o-- ---" "xox -o- ---" "xox --- o--" "xox --- -o-" } 0 t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } p "" 2 3 "(2,5)" { "xoo --x ---" "xo- o-x ---" "xo- -ox ---" "xo- --x o--" "xo- --x -o-" "xo- --x --o" } 0 t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } p "" 2 4 "(2,6)" { "xoo --- -x-" "xo- o-- -x-" "xo- -o- -x-" "xo- --o -x-" "xo- --- ox-" "xo- --- -xo" } 0 t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 2 "Outcome 3" { 0, 0 } t "" 2 "Outcome 3" { 0, 0 } p "" 1 3 "(1,3)" { "xxo --- ---" "x-o x-- ---" "x-o -x- ---" "x-o --x ---" "x-o --- x--" "x-o --- -x-" "x-o --- --x" } 0 p "" 2 5 "(2,7)" { "xxo o-- ---" "xxo -o- ---" "xxo --o ---" "xxo --- o--" "xxo --- -o-" "xxo --- --o" } 0 t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 3 "Outcome 2" { -1, 1 } t "" 1 "Outcome 1" { 1, -1 } p "" 1 4 "(1,13)" { "xxo --- xo-" "xxo --- -ox" "xxo +++ -o-" } 0 t "" 2 "Outcome 3" { 0, 0 } t "" 2 "Outcome 3" { 0, 0 } t "" 3 "Outcome 2" { -1, 1 } t "" 3 "Outcome 2" { -1, 1 } t "" 3 "Outcome 2" { -1, 1 } t "" 1 "Outcome 1" { 1, -1 } p "" 2 6 "(2,8)" { "xoo --x ---" "x-o o-x ---" "x-o -ox ---" "x-o --x o--" "x-o --x -o-" "x-o --x --o" } 0 t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } p "" 2 7 "(2,9)" { "xoo --- -x-" "x-o o-- -x-" "x-o -o- -x-" "x-o --o -x-" "x-o --- ox-" "x-o --- -xo" } 0 t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } p "" 1 5 "(1,14)" { "xx- -o- ---" "x-x -o- ---" "x-- -ox ---" "x-- -o- --x" } 0 t "" 2 "Outcome 3" { 0, 0 } t "" 2 "Outcome 3" { 0, 0 } p "" 2 8 "(2,10)" { "xo- -ox ---" "x-o -ox ---" "x-- oox ---" "x-- -ox o--" "x-- -ox -o-" "x-- -ox --o" } 0 t "" 2 "Outcome 3" { 0, 0 } t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } p "" 1 6 "(1,15)" { "x-- xox --o" "x++ -ox ++o" } 0 t "" 3 "Outcome 2" { -1, 1 } t "" 2 "Outcome 3" { 0, 0 } p "" 2 9 "(2,11)" { "xo- -o- --x" "x-o -o- --x" } 0 t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } p "" 1 7 "(1,4)" { "xx- --o ---" "x-x --o ---" "x-- x-o ---" "x-- -xo ---" "x-- --o x--" "x-- --o -x-" "x-- --o --x" } 0 t "" 3 "Outcome 2" { -1, 1 } t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } p "" 2 10 "(2,12)" { "xo- --o -x-" "x-o --o -x-" "x-- o-o -x-" "x-- -oo -x-" "x-- --o ox-" "x-- --o -xo" } 0 t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } p "" 1 8 "(1,5)" { "xx- --- --o" "x-x --- --o" "x-- -x- --o" "x-- --x --o" } 0 t "" 3 "Outcome 2" { -1, 1 } t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } p "" 2 11 "(2,13)" { "xo- --x --o" "x-o --x --o" "x-- o-x --o" "x-- -ox --o" "x-- --x o-o" "x-- --x -oo" } 0 t "" 1 "Outcome 1" { 1, -1 } t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } p "" 1 9 "(1,16)" { "x-- xox --o" "x++ -ox ++o" } 0 t "" 3 "Outcome 2" { -1, 1 } t "" 2 "Outcome 3" { 0, 0 } p "" 1 10 "(1,17)" { "x-- --x oxo" } 0 p "" 2 12 "(2,14)" { "x-+ +-x oxo" "x+- -+x oxo" } 0 t "" 1 "Outcome 1" { 1, -1 } t "" 2 "Outcome 3" { 0, 0 } t "" 1 "Outcome 1" { 1, -1 } p "" 2 13 "(2,2)" { "ox- --- ---" "-x- o-- ---" "-x- -o- ---" "-x- --- o--" "-x- --- -o-" } 0 p "" 1 11 "(1,6)" { "oxx --- ---" "ox- x-- ---" "ox- -x- ---" "ox- --x ---" "ox- --- x--" "ox- --- -x-" "ox- --- --x" } 0 p "" 2 14 "(2,15)" { "oxx o-- ---" "oxx -o- ---" "oxx --o ---" "oxx --- o--" "oxx --- -o-" "oxx --- --o" } 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 2 15 "(2,16)" { "oxo x-- ---" "ox- xo- ---" "ox- x-o ---" "ox- x-- --o" } 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 2 16 "(2,17)" { "oxo -x- ---" "ox- ox- ---" "ox- -xo ---" "ox- -x- o--" "ox- -x- -o-" "ox- -x- --o" } 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 2 17 "(2,18)" { "1" "2" "3" "4" "5" "6" } 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 1 12 "(1,7)" { "xx- o-- ---" "-xx o-- ---" "-x- ox- ---" "-x- o-x ---" "-x- o-- x--" "-x- o-- -x-" "-x- o-- --x" } 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 1 13 "(1,8)" { "xx- -o- ---" "-x- xo- ---" "-x- -o- x--" "-x- -o- -x-" } 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 1 14 "(1,9)" { "xx- --- o--" "-xx --- o--" "-x- x-- o--" "-x- -x- o--" "-x- --x o--" "-x- --- ox-" "-x- --- o-x" } 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 1 15 "(1,10)" { "xx- --- -o-" "-x- x-- -o-" "-x- -x- -o-" "-x- --- xo-" } 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 2 18 "(2,3)" { "o-- -x- ---" "-o- -x- ---" } 0 p "" 1 16 "(1,11)" { "ox- -x- ---" "o-x -x- ---" "o-- -xo ---" "o-- -x- --x" } 0 t "" 0 t "" 0 t "" 0 t "" 0 p "" 1 17 "(1,12)" { "xo- -x- ---" "-o- xx- ---" "-o- -x- x--" "-o- -x- -x-" } 0 t "" 0 t "" 0 t "" 0 t "" 0 gambit-0.2010.09.01/contrib/games/vd.efg0000644000076500007650000000076411350032206014267 00000000000000EFG 2 R "Van Damme's Game" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "W" "K" } 0 p "" 1 2 "(1,2)" { "A" "B" } 0 p "" 2 1 "(2,1)" { "a" "b" } 0 t "" 1 "Outcome 1" { 2, 1 } t "" 2 "Outcome 2" { -1, 0 } p "" 2 1 "(2,1)" { "a" "b" } 0 t "" 3 "Outcome 3" { -1, 0 } t "" 4 "Outcome 4" { 0, 3 } p "" 1 3 "(1,3)" { "A" "B" } 0 p "" 2 2 "(2,2)" { "a" "b" } 0 t "" 5 "Outcome 5" { 3, 1 } t "" 6 "Outcome 6" { 0, 0 } p "" 2 2 "(2,2)" { "a" "b" } 0 t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 1, 3 } gambit-0.2010.09.01/contrib/games/vd.nfg0000644000076500007650000000064511350032206014276 00000000000000NFG 1 D "Van Damme's burning a dollar Game" { "Player 1" "Player 2" } { { "11*" "12*" "2*1" "2*2" } { "11" "12" "21" "22" } } 2.000000 1.000000 -1.000000 0.000000 3.000000 1.000000 0.000000 0.000000 2.000000 1.000000 -1.000000 0.000000 0.000000 0.000000 1.000000 3.000000 -1.000000 0.000000 0.000000 3.000000 3.000000 1.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 3.000000 0.000000 0.000000 1.000000 3.000000 gambit-0.2010.09.01/contrib/games/w_ex1.efg0000644000076500007650000000047711350032206014702 00000000000000EFG 2 R "Wilson's ex1" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "Out" "2" } 0 t "" 1 "Outcome 1" { 2, 2 } p "" 1 2 "(1,2)" { "A" "B" } 0 p "" 2 1 "(2,1)" { "a" "b" } 0 t "" 2 "Outcome 4" { 0, 0 } t "" 3 "Outcome 2" { 1, 3 } p "" 2 1 "(2,1)" { "a" "b" } 0 t "" 4 "Outcome 3" { 3, 1 } t "" 2 "Outcome 4" { 0, 0 } gambit-0.2010.09.01/contrib/games/w_ex2.efg0000644000076500007650000000211711350032206014674 00000000000000EFG 2 R "Wilson's ex2: Two stage battle of the sexes" { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "A" "B" } 1 "Outcome 5" { 1, 1 } p "" 2 1 "(2,1)" { "A" "B" } 0 p "" 1 2 "(1,2)" { "A" "B" } 2 "Outcome 1" { 0, 0 } p "" 2 2 "(2,2)" { "A" "B" } 0 t "" 2 "Outcome 1" { 0, 0 } t "" 3 "Outcome 2" { 1, 3 } p "" 2 2 "(2,2)" { "A" "B" } 0 t "" 4 "Outcome 3" { 3, 1 } t "" 5 "Outcome 4" { 0, 0 } p "" 1 3 "(1,3)" { "A" "B" } 3 "Outcome 2" { 1, 3 } p "" 2 3 "(2,3)" { "A" "B" } 0 t "" 2 "Outcome 1" { 0, 0 } t "" 3 "Outcome 2" { 1, 3 } p "" 2 3 "(2,3)" { "A" "B" } 0 t "" 4 "Outcome 3" { 3, 1 } t "" 5 "Outcome 4" { 0, 0 } p "" 2 1 "(2,1)" { "A" "B" } 0 p "" 1 4 "(1,4)" { "A" "B" } 4 "Outcome 3" { 3, 1 } p "" 2 4 "(2,4)" { "A" "B" } 0 t "" 2 "Outcome 1" { 0, 0 } t "" 3 "Outcome 2" { 1, 3 } p "" 2 4 "(2,4)" { "A" "B" } 0 t "" 4 "Outcome 3" { 3, 1 } t "" 5 "Outcome 4" { 0, 0 } p "" 1 5 "(1,5)" { "A" "B" } 5 "Outcome 4" { 0, 0 } p "" 2 5 "(2,5)" { "A" "B" } 0 t "" 2 "Outcome 1" { 0, 0 } t "" 3 "Outcome 2" { 1, 3 } p "" 2 5 "(2,5)" { "A" "B" } 0 t "" 4 "Outcome 3" { 3, 1 } t "" 5 "Outcome 4" { 0, 0 } gambit-0.2010.09.01/contrib/games/wilson1.efg0000644000076500007650000000063611350032206015250 00000000000000EFG 2 R "Wilson (1991): a game with two weakly stable sets." { "Player 1" "Player 2" } "" p "" 1 1 "(1,1)" { "a" "2" } 0 t "" 1 "Outcome 1" { 3, 6 } p "" 2 1 "(2,1)" { "d" "2" } 0 t "" 2 "Outcome 2" { 4, 3 } p "" 1 2 "(1,2)" { "b" "c" } 0 p "" 2 2 "(2,2)" { "e" "f" } 0 t "" 3 "Outcome 3" { 2, 1 } t "" 4 "Outcome 4" { 1, 4 } p "" 2 2 "(2,2)" { "e" "f" } 0 t "" 5 "Outcome 5" { 1, 4 } t "" 6 "Outcome 6" { 2, 1 } gambit-0.2010.09.01/contrib/games/wink3.nfg0000644000076500007650000000020411350032206014707 00000000000000NFG 1 R "Simple example where CBFS != AllNash" { "1" "2" } { { "1" "2" "3"} { "1" "2" "3"} } 1 3 1 2 0 4 3 4 3 1 2 3 4 2 2 1 3 3 gambit-0.2010.09.01/contrib/games/winkels.nfg0000644000076500007650000000027311350032206015336 00000000000000NFG 1 R "Winkels, 1979 degenerate game with 12 extreme equilibria" { "1" "2" } { { "1" "2" "3" "4" "5" "6" } { "1" "2" } } 1 1 1 0 3 -2 3 4 5/2 -1 5/2 6 3 2 3 -1 1 2 1 -1 5/2 6 5/2 -1 gambit-0.2010.09.01/contrib/games/work1.efg0000644000076500007650000000070611350032206014715 00000000000000EFG 2 R "Employer - Employee problem, one stage" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "HW" 1/2 "L" 1/2 } 0 p "" 1 1 "(1,1)" { "F" "H" } 0 t "" 1 "Outcome 1" { 0, 0 } p "" 2 1 "(2,1)" { "Q" "W" } 2 "Outcome 2" { -2, 2 } t "" 3 "Outcome 3" { 0, 0 } t "" 4 "Outcome 4" { 3, 1 } p "" 1 1 "(1,1)" { "F" "H" } 0 t "" 5 "Outcome 5" { 0, 0 } p "" 2 2 "(2,2)" { "Q" "W" } 6 "Outcome 6" { -2, 2 } t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 3, -1 } gambit-0.2010.09.01/contrib/games/work2.efg0000644000076500007650000000141211350032206014711 00000000000000EFG 2 R "Employer - Employee problem, two stages" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "HW" 1/2 "L" 1/2 } 0 p "" 1 1 "(1,1)" { "F" "H" } 0 t "" 1 "Outcome 1" { 0, 0 } p "" 2 1 "(2,1)" { "Q" "W" } 2 "Outcome 2" { -2, 2 } t "" 3 "Outcome 3" { 0, 0 } p "" 1 2 "(1,2)" { "F" "H" } 4 "Outcome 4" { 3, 1 } t "" 1 "Outcome 1" { 0, 0 } p "" 2 2 "(2,3)" { "Q" "W" } 2 "Outcome 2" { -2, 2 } t "" 3 "Outcome 3" { 0, 0 } t "" 4 "Outcome 4" { 3, 1 } p "" 1 1 "(1,1)" { "F" "H" } 0 t "" 5 "Outcome 5" { 0, 0 } p "" 2 3 "(2,2)" { "Q" "W" } 6 "Outcome 6" { -2, 2 } t "" 7 "Outcome 7" { 0, 0 } p "" 1 2 "(1,2)" { "F" "H" } 8 "Outcome 8" { 3, -1 } t "" 1 "Outcome 1" { 0, 0 } p "" 2 4 "(2,4)" { "Q" "W" } 2 "Outcome 2" { -2, 2 } t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 3, -1 } gambit-0.2010.09.01/contrib/games/work3.efg0000644000076500007650000000211711350032206014715 00000000000000EFG 2 R "Employer - Employee problem, three stages" { "Player 1" "Player 2" } "" c "" 1 "(0,1)" { "HW" 1/2 "L" 1/2 } 0 p "" 1 1 "(1,1)" { "F" "H" } 0 t "" 1 "Outcome 1" { 0, 0 } p "" 2 1 "(2,1)" { "Q" "W" } 2 "Outcome 2" { -2, 2 } t "" 3 "Outcome 3" { 0, 0 } p "" 1 2 "(1,2)" { "F" "H" } 4 "Outcome 4" { 3, 1 } t "" 1 "Outcome 1" { 0, 0 } p "" 2 2 "(2,3)" { "Q" "W" } 2 "Outcome 2" { -2, 2 } t "" 3 "Outcome 3" { 0, 0 } p "" 1 3 "(1,3)" { "F" "H" } 4 "Outcome 4" { 3, 1 } t "" 1 "Outcome 1" { 0, 0 } p "" 2 3 "(2,5)" { "Q" "W" } 2 "Outcome 2" { -2, 2 } t "" 3 "Outcome 3" { 0, 0 } t "" 4 "Outcome 4" { 3, 1 } p "" 1 1 "(1,1)" { "F" "H" } 0 t "" 5 "Outcome 5" { 0, 0 } p "" 2 4 "(2,2)" { "Q" "W" } 6 "Outcome 6" { -2, 2 } t "" 7 "Outcome 7" { 0, 0 } p "" 1 2 "(1,2)" { "F" "H" } 8 "Outcome 8" { 3, -1 } t "" 1 "Outcome 1" { 0, 0 } p "" 2 5 "(2,4)" { "Q" "W" } 2 "Outcome 2" { -2, 2 } t "" 7 "Outcome 7" { 0, 0 } p "" 1 3 "(1,3)" { "F" "H" } 8 "Outcome 8" { 3, -1 } t "" 1 "Outcome 1" { 0, 0 } p "" 2 6 "(2,6)" { "Q" "W" } 2 "Outcome 2" { -2, 2 } t "" 7 "Outcome 7" { 0, 0 } t "" 8 "Outcome 8" { 3, -1 } gambit-0.2010.09.01/contrib/games/yamamoto.nfg0000644000076500007650000000020411350032206015502 00000000000000NFG 1 R "Example game from Yamamoto (IJGT, 1993)" { "Player 1" "Player 2" } { 3 3 } 1 1 0 0 -9 -9 0 0 0 0 -7 -6 -9 -9 -7 -7 -7 -7 gambit-0.2010.09.01/contrib/games/zero.nfg0000644000076500007650000000022411350032206014635 00000000000000NFG 1 D "Two person 2 x 2 game with all zero payoffs" { "1" "2" } { 2 2 } 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 gambit-0.2010.09.01/contrib/mac/0000777000076500007650000000000011441457127012732 500000000000000gambit-0.2010.09.01/contrib/mac/Info.plist0000644000076500007650000000221111352541425014606 00000000000000 CFBundleInfoDictionaryVersion 6.0 CFBundleIdentifier org.gambit-project.gambit CFBundleDevelopmentRegion English CFBundleExecutable gambit CFBundleIconFile wxmac.icns CFBundleName Gambit CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 0.2010.03.21 CFBundleShortVersionString 0.2010.03.21 CFBundleGetInfoString Gambit version 0.2010.03.21, (c) 1995-2010 The Gambit Project CFBundleLongVersionString 0.2010.03.21, (c) 1995-2010 The Gambit Project NSHumanReadableCopyright Copyright 1995-2010 The Gambit Project LSRequiresCarbon CSResourcesFileMapped gambit-0.2010.09.01/contrib/Makefile.am0000644000076500007650000000164511435216077014150 00000000000000## ## This file is part of Gambit ## Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) ## ## FILE: contrib/Makefile.am ## automake input file for contrib subdirectory ## ## 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. ## SUBDIRS = scripts gambit-0.2010.09.01/contrib/Makefile.in0000644000076500007650000003430211441456740014155 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ install-recursive installcheck-recursive installdirs-recursive \ pdf-recursive ps-recursive uninstall-info-recursive \ uninstall-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENUMPOLY_PROGS = @ENUMPOLY_PROGS@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GREP = @GREP@ GUI_PROGS = @GUI_PROGS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ RC_OBJECT = @RC_OBJECT@ RC_OBJECT_PATH = @RC_OBJECT_PATH@ REZFLAGS = @REZFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WITH_ENUMPOLY_FALSE = @WITH_ENUMPOLY_FALSE@ WITH_ENUMPOLY_TRUE = @WITH_ENUMPOLY_TRUE@ WITH_GUI_FALSE = @WITH_GUI_FALSE@ WITH_GUI_TRUE = @WITH_GUI_TRUE@ WX_CFLAGS = @WX_CFLAGS@ WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ WX_CONFIG_PATH = @WX_CONFIG_PATH@ WX_CPPFLAGS = @WX_CPPFLAGS@ WX_CXXFLAGS = @WX_CXXFLAGS@ WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ WX_LIBS = @WX_LIBS@ WX_LIBS_STATIC = @WX_LIBS_STATIC@ WX_RESCOMP = @WX_RESCOMP@ WX_VERSION = @WX_VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = scripts all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu contrib/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(mkdir_p) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ clean clean-generic clean-libtool clean-recursive ctags \ ctags-recursive distclean distclean-generic distclean-libtool \ distclean-recursive distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive \ mostlyclean mostlyclean-generic mostlyclean-libtool \ mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gambit-0.2010.09.01/contrib/scripts/0000777000076500007650000000000011441457133013656 500000000000000gambit-0.2010.09.01/contrib/scripts/enumpoly/0000777000076500007650000000000011441457133015526 500000000000000gambit-0.2010.09.01/contrib/scripts/enumpoly/countsupport.py0000644000076500007650000000233611350032206020572 00000000000000 import random import enumphc import randomnfg if __name__ == '__main__': import sys, os #os.system("rm game-*.nfg") argv = sys.argv solve = True if argv[1] == '-e': solve = False argv = [ argv[0] ] + argv[2:] game = randomnfg.CreateNfg([int(x) for x in argv[2:]]) strategies = [ strategy for player in game.Players() for strategy in player.Strategies() ] print "ownuser,ownsystem,childuser,childsystem,supports,singular,nash,nonnash" for iter in xrange(int(argv[1])): randomnfg.RandomizeGame(game, lambda: random.normalvariate(0, 1)) #file("game-%04d.nfg" % iter, "w").write(game.AsNfgFile()) logger = enumphc.CountLogger() startTime = os.times() enumphc.EnumViaPHC(game, "blek", logger, solve=solve) endTime = os.times() print ("%f,%f,%f,%f,%d,%d,%d,%d" % (endTime[0] - startTime[0], endTime[1] - startTime[1], endTime[2] - startTime[2], endTime[3] - startTime[3], logger.candidates, logger.singulars, logger.nash, logger.nonnash)) sys.stdout.flush() gambit-0.2010.09.01/contrib/scripts/enumpoly/enumpoly.py0000644000076500007650000004570211437713632017700 00000000000000# # Compute all equilibria of a strategic game using support enumeration. # # This program enumerates all "admissible" supports in a strategic game. # The main function, Enumerate(), does the enumeration, and hands off # each nontrivial admissible support to the Solve() method of the # solver object provided it. # # This program currently offers three solver objects: # (1) A "null" solver object (so, for instance, one can just count supports) # (2) A "PHCSolve" solver object, which solves the implied system using # PHCpack (external binary required) # (3) A "Bertini" solver object, which solves the implied system using # Bertini (external binary required) # import gambit import phc import time, os ############################################################################# # Generate polynomial equations for a support ############################################################################# # Use this table to assign letters to player strategy variables # We skip 'e' and 'i', because PHC doesn't allow these in variable names. playerletters = [ 'a', 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' ] def Equations(support, player): payoffs = [ [] for strategy in support.Strategies(player) ] players = [ (pl, oplayer) for (pl, oplayer) in enumerate(support.GetGame().Players()) if player != oplayer ] strategies = [ (st, strategy) for (st, strategy) in enumerate(support.Strategies(player)) ] for profile in gambit.StrategyIterator(support, support.GetStrategy(player.GetNumber(), 1)): contingency = "*".join([playerletters[pl] + "%d" % (profile.GetStrategy(oplayer).GetNumber()-1) for (pl, oplayer) in players]) for (st, strategy) in strategies: payoffs[st].append("(%s*%s)" % (str(float(profile.GetStrategyValue(strategy))), contingency)) equations = [ "(%s)-(%s);\n" % ("+".join(payoffs[0]), "+".join(s2)) for s2 in payoffs[1:] ] # Substitute in sum-to-one constraints for (pl, oplayer) in enumerate(support.GetGame().Players()): if player == oplayer: continue playerchar = playerletters[pl] if support.NumStrategies(pl+1) == 1: for (i, equation) in enumerate(equations): equations[i] = equation.replace("*%s%d" % (playerchar, support.GetStrategy(pl+1, 1).GetNumber()-1), "") else: subvar = "1-" + "-".join( playerchar+"%d" % (strategy.GetNumber() - 1) for (st, strategy) in enumerate(support.Strategies(oplayer)) if st != 0 ) for (i, equation) in enumerate(equations): equations[i] = equation.replace("%s%d" % (playerchar, support.GetStrategy(pl+1, 1).GetNumber()-1), "("+subvar+")") return equations ############################################################################# # Utility routines ############################################################################# def IsNash(profile, vars): for i in xrange(1, profile.MixedProfileLength()+1): if profile[i] < -negTolerance: return False for (pl, player) in enumerate(profile.GetGame().Players()): playerchar = playerletters[pl] payoff = profile.GetPayoff(player) total = 0.0 for (st, strategy) in enumerate(player.Strategies()): if "%s%d" % (playerchar, st) not in vars.keys(): if profile.GetStrategyValue(strategy) - payoff > payoffTolerance: return False else: total += vars["%s%d" % (playerchar, st)].real return True def CheckEquilibrium(game, support, entry, logger): profile = game.NewMixedStrategyDouble() index = 1 for (pl, player) in enumerate(game.Players()): playerchar = playerletters[pl] total = 0.0 for (st, strategy) in enumerate(player.Strategies()): try: profile[index] = entry["vars"][playerchar + str(st)].real except KeyError: profile[index] = 0.0 total += profile[index] index += 1 profile[support.GetStrategy(pl+1, 1).GetId()] = 1.0 - total entry["vars"][playerchar + str(support.GetStrategy(pl+1,1).GetNumber()-1)] = complex(1.0 - total) x = ",".join([ "%f" % profile[i] for i in xrange(1, game.MixedProfileLength() + 1)]) if IsNash(profile, entry["vars"]): logger.OnNashSolution(profile) else: logger.OnNonNashSolution(profile) def IsPureSupport(support): return reduce(lambda x, y: x and y, [ support.NumStrategies(pl+1) == 1 for (pl, player) in enumerate(support.Players()) ]) def ProfileFromPureSupport(game, support): profile = game.NewMixedStrategyDouble() for index in xrange(1, game.MixedProfileLength() + 1): profile[index] = 0.0 for (pl, player) in enumerate(support.Players()): profile[support.GetStrategy(pl+1, 1).GetId()] = 1.0 return profile ############################################################################# # Solver classes ############################################################################# class SupportSolver: def __init__(self, logger): self.logger = logger def GetLogger(self): return self.logger class NullSolver(SupportSolver): def __init__(self, logger): SupportSolver.__init__(self, logger) def Solve(support): pass ############################################################################# # Solver for solving support via PHCpack ############################################################################# class PHCSolver(SupportSolver): def __init__(self, prefix, logger): SupportSolver.__init__(self, logger) self.prefix = prefix def GetFilePrefix(self): return self.prefix def Solve(self, support): game = support.GetGame() eqns = reduce(lambda x, y: x + y, [ Equations(support, player) for player in game.Players() ]) phcinput = ("%d\n" % len(eqns)) + "".join(eqns) #print phcinput try: phcoutput = phc.RunPHC("./phc", self.prefix, phcinput) #print "%d solutions found; checking for equilibria now" % len(phcoutput) for entry in phcoutput: CheckEquilibrium(game, support, entry, self.logger) #print "Equilibrium checking complete" except ValueError: self.logger.OnSingularSupport(support) except: self.logger.OnSingularSupport(support) ############################################################################# # Solver for solving support via Bertini ############################################################################# class BertiniSolver(SupportSolver): def __init__(self, logger, bertiniPath="./bertini"): SupportSolver.__init__(self, logger) self.bertiniPath = bertiniPath def GetBertiniPath(self): return self.bertiniPath def SetBertiniPath(self, path): self.bertiniPath = path def Solve(self, support): game = support.GetGame() eqns = reduce(lambda x, y: x + y, [ Equations(support, player) for player in game.Players() ]) variables = [ ] for (pl, player) in enumerate(game.Players()): for st in xrange(support.NumStrategies(pl+1) - 1): variables.append("%c%d" % (playerletters[pl], st+1)) bertiniInput = "CONFIG\n\nEND;\n\nINPUT\n\n" bertiniInput += "variable_group %s;\n" % ", ".join(variables) bertiniInput += "function %s;\n\n" % ", ".join([ "e%d" % i for i in xrange(len(eqns)) ]) for (eq, eqn) in enumerate(eqns): bertiniInput += "e%d = %s\n" % (eq, eqn) bertiniInput += "\nEND;\n" #print bertiniInput infile = file("input", "w") infile.write(bertiniInput) infile.close() if os.system("%s > /dev/null" % self.bertiniPath) == 0: try: solutions = [ ] outfile = file("real_finite_solutions") lines = iter(outfile) lines.next() lines.next() while lines.next().strip() != "-1": solution = { } solution["vars"] = { } for var in variables: value = lines.next().split() solution["vars"][var] = complex(float(value[0]), float(value[1])) #print solution solutions.append(solution) outfile.close() os.remove("real_finite_solutions") for entry in solutions: CheckEquilibrium(game, support, entry, self.logger) except IOError: #print "couldn't open real_finite_solutions" self.logger.OnSingularSupport(support) ############################################################################# # Logger classes for storing and reporting output ############################################################################# class NullLogger: def OnCandidateSupport(self, support): pass def OnSingularSupport(self, support): pass def OnNashSolution(self, profile): pass def OnNonNashSolution(self, profile): pass class StandardLogger(NullLogger): def OnNashSolution(self, profile): print "NE," + ",".join(["%f" % max(profile[i], 0.0) for i in xrange(1, profile.MixedProfileLength() + 1)]) class VerboseLogger(StandardLogger): def PrintSupport(self, support, label): strings = [ reduce(lambda x, y: x + y, [ str(int(support.Contains(strategy))) for strategy in player.Strategies() ]) for player in support.Players() ] print label + "," + ",".join(strings) def OnCandidateSupport(self, support): self.PrintSupport(support, "candidate") def OnSingularSupport(self, support): self.PrintSupport(support, "singular") def OnNonNashSolution(self, profile): print ("noneqm," + ",".join([str(profile[i]) for i in xrange(1, profile.MixedProfileLength() + 1)]) + "," + str(profile.GetLiapValue())) class CountLogger: def __init__(self): self.candidates = 0 self.singulars = 0 self.nash = 0 self.nonnash = 0 def OnCandidateSupport(self, support): self.candidates += 1 def OnSingularSupport(self, support): self.singulars += 1 def OnNashSolution(self, profile): self.nash += 1 def OnNonNashSolution(self, profile): self.nonnash += 1 ############################################################################# # The main program: enumerate supports and pass them to a solver class ############################################################################# # # Compute the admissible supports such that all strategies in 'setin' # are in the support, all the strategies in 'setout' are not in the # support. # # setin: Set of strategies assumed "in" the support # setout: Set of strategies assumed "outside" the support # setfree: Set of strategies not yet allocated # These form a partition of the set of all strategies # def AdmissibleSubsupports(game, setin, setout, setfree, skipdom = False): #print time.time(), len(setin), len(setout) support = gambit.StrategySupport(game) for strategy in setout: if not support.RemoveStrategy(strategy): # If the removal fails, it means we have no strategies # for this player; we can stop raise StopIteration if setfree == []: # We have assigned all strategies. Now check for dominance. # Note that we check these "by hand" because when eliminating # by "external" dominance, the last strategy for a player # won't be eliminated, even if it should, because RemoveStrategy() # will not allow the last strategy for a player to be removed. # Need to consider whether the API should be modified for this. for player in game.Players(): for strategy in support.Strategies(player): if support.IsDominated(strategy, True, True): raise StopIteration yield support else: #print "Starting iterated dominance" if not skipdom: while True: newsupport = support.Undominated(True, True) if newsupport == support: break support = newsupport #print "Done with iterated dominance" for strategy in setin: if not support.Contains(strategy): # We dropped a strategy already assigned as "in": # we can terminate this branch of the search raise StopIteration subsetout = setout[:] subsetfree = setfree[:] for strategy in setfree: if not newsupport.Contains(strategy): subsetout.append(strategy) subsetfree.remove(strategy) else: subsetout = setout[:] subsetfree = setfree[:] # Switching the order of the following two calls (roughly) # switches whether supports are tried largest first, or # smallest first # Currently: smallest first # When we add a strategy to 'setin', we can skip the dominance # check at the next iteration, because it will return the same # result as here for subsupport in AdmissibleSubsupports(game, setin, subsetout + [subsetfree[0]], subsetfree[1:]): yield subsupport for subsupport in AdmissibleSubsupports(game, setin + [subsetfree[0]], subsetout, subsetfree[1:]): yield subsupport raise StopIteration def Enumerate(game, solver): game.BuildComputedValues() for support in AdmissibleSubsupports(game, [], [], [ strategy for player in game.Players() for strategy in player.Strategies() ]): solver.GetLogger().OnCandidateSupport(support) if IsPureSupport(support): # By definition, if this is a pure-strategy support, it # must be an equilibrium (because of the dominance # elimination process) solver.GetLogger().OnNashSolution(ProfileFromPureSupport(game, support)) else: solver.Solve(support) ######################################################################## # Instrumentation for standalone use ######################################################################## def PrintBanner(f): f.write("Compute Nash equilibria by solving polynomial systems\n") f.write("(solved using Jan Verschelde's PHCPACK solver)\n") f.write("Gambit version 0.2007.03.12, Copyright (C) 2007, The Gambit Project\n") f.write("This is free software, distributed under the GNU GPL\n\n") def PrintHelp(progname): PrintBanner(sys.stderr) sys.stderr.write("Usage: %s [OPTIONS]\n" % progname) sys.stderr.write("Accepts game on standard input.\n") sys.stderr.write("With no options, reports all Nash equilibria found.\n\n") sys.stderr.write("Options:\n") sys.stderr.write(" -h print this help message\n") sys.stderr.write(" -m backend to use (null, phc, bertini)\n") sys.stderr.write(" -n tolerance for negative probabilities (default 0)\n") sys.stderr.write(" -p prefix to use for filename in calling PHC\n") sys.stderr.write(" -q quiet mode (suppresses banner)\n") sys.stderr.write(" -t tolerance for non-best-response payoff (default 1.0e-6)\n") sys.stderr.write(" -v verbose mode (shows supports investigated)\n") sys.stderr.write(" (default is only to show equilibria)\n") sys.exit(1) payoffTolerance = 1.0e-6 negTolerance = 0.0 if __name__ == '__main__': import getopt, sys verbose = False quiet = False prefix = "blek" backend = "phc" try: opts, args = getopt.getopt(sys.argv[1:], "p:n:t:hqvd:m:") except getopt.GetoptError: PrintHelp(sys.argv[0]) for (o, a) in opts: if o == "-h": PrintHelp(sys.argv[0]) elif o == "-d": pass elif o == "-v": verbose = True elif o == "-q": quiet = True elif o == "-p": prefix = a elif o == "-m": if a in [ "null", "phc", "bertini" ]: backend = a else: sys.stderr.write("%s: unknown backend `%s' passed to `-m'\n" % (sys.argv[0], a)) sys.exit(1) elif o == "-n": try: negTolerance = float(a) except ValueError: sys.stderr.write("%s: `-n' option expects a floating-point number\n" % sys.argv[0]) sys.exit(1) elif o == "-t": try: payoffTolerance = float(a) except ValueError: sys.stderr.write("%s: `-t' option expects a floating-point number\n" % sys.argv[0]) else: sys.stderr.write("%s: Unknown option `-%s'.\n" % (sys.argv[0], o)) sys.exit(1) if not quiet: PrintBanner(sys.stderr) game = gambit.ReadGame(sys.stdin.read()) game.BuildComputedValues() if verbose: logger = VerboseLogger() else: logger = StandardLogger() if backend == "bertini": Enumerate(game, solver=BertiniSolver(logger, bertiniPath="./bertini")) elif backend == "phc": Enumerate(game, solver=PHCSolver(prefix, logger)) else: Enumerate(game, solver=NullSolver(logger)) gambit-0.2010.09.01/contrib/scripts/enumpoly/Makefile.am0000644000076500007650000000035311350032206017464 00000000000000# # $Source$ # $Date: 2005-12-12 01:22:08 -0600 (Mon, 12 Dec 2005) $ # $Revision: 6040 $ # # DESCRIPTION: # automake input for sample scripts directory # EXTRA_DIST = \ countsupport.py \ enumpoly.py \ phc.py \ setup.py \ README gambit-0.2010.09.01/contrib/scripts/enumpoly/Makefile.in0000644000076500007650000002225311441456741017517 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # $Source$ # $Date: 2005-12-12 01:22:08 -0600 (Mon, 12 Dec 2005) $ # $Revision: 6040 $ # # DESCRIPTION: # automake input for sample scripts directory # srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/scripts/enumpoly DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENUMPOLY_PROGS = @ENUMPOLY_PROGS@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GREP = @GREP@ GUI_PROGS = @GUI_PROGS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ RC_OBJECT = @RC_OBJECT@ RC_OBJECT_PATH = @RC_OBJECT_PATH@ REZFLAGS = @REZFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WITH_ENUMPOLY_FALSE = @WITH_ENUMPOLY_FALSE@ WITH_ENUMPOLY_TRUE = @WITH_ENUMPOLY_TRUE@ WITH_GUI_FALSE = @WITH_GUI_FALSE@ WITH_GUI_TRUE = @WITH_GUI_TRUE@ WX_CFLAGS = @WX_CFLAGS@ WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ WX_CONFIG_PATH = @WX_CONFIG_PATH@ WX_CPPFLAGS = @WX_CPPFLAGS@ WX_CXXFLAGS = @WX_CXXFLAGS@ WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ WX_LIBS = @WX_LIBS@ WX_LIBS_STATIC = @WX_LIBS_STATIC@ WX_RESCOMP = @WX_RESCOMP@ WX_VERSION = @WX_VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ EXTRA_DIST = \ countsupport.py \ enumpoly.py \ phc.py \ setup.py \ README all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu contrib/scripts/enumpoly/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/scripts/enumpoly/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-exec install-exec-am \ install-info install-info-am install-man install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gambit-0.2010.09.01/contrib/scripts/enumpoly/phc.py0000644000076500007650000001156111350032206016557 00000000000000 ########################################################################### # A Python interface to PHCPACK ########################################################################### # This takes the entire output of a PHCPACK run, and returns a list of # solutions. # Each solution is a Python dictionary with the following entries, # each containing one of the (corresponding) data from a solution: # * "startresidual" # * "iterations" # * "result" # * "t" # * "m" # * "err" # * "rco" # * "res" # # There are two other dictionary entries of interest: # * "type": the text string PHCPACK emits describing the output # (e.g., "no solution", "real regular", etc.) # * "vars": a dictionary whose keys are the variable names, # and whose values are the solution values, represented # using the Python `complex` type. def ProcessPHCOutput(output): # This initial phase identifies the part of the output containing # the solutions. It is complicated slightly because (as of Jan 2007) # PHCPACK's blackbox solver uses special-case code for linear and # sparse systems (this per email from Jan Verschelde). When these # methods are in effect, the output format is slightly different. startsol = output.find("THE SOLUTIONS :\n\n") if startsol == -1: startsol = output.find("THE SOLUTIONS :\n") solns = output[startsol:] firstequals = solns.find("solution") firstcut = solns[firstequals:] secondequals = firstcut.find("=====") if secondequals >= 0: secondcut = firstcut[:secondequals] else: secondequals = firstcut.find("TIMING") secondcut = firstcut[:secondequals] solutions = [ ] for line in secondcut.split("\n"): tokens = [ x.strip(" ") for x in line.split(" ") if x != "" and not x.isspace() ] if tokens == []: continue if tokens[0] == "solution": if len(tokens) == 3: # This is a solution that didn't involve iteration solutions.append( { "vars": { } } ) else: solutions.append({ "startresidual": float(tokens[6]), "iterations": int(tokens[9]), "result": tokens[10], "vars": { } }) elif tokens[0] == "t": solutions[-1]["t"] = complex(float(tokens[2]), float(tokens[3])) elif tokens[0] == "m": solutions[-1]["m"] = int(tokens[2]) elif tokens[0] == "the": pass elif tokens[0] == "==": solutions[-1]["err"] = float(tokens[3]) solutions[-1]["rco"] = float(tokens[7]) solutions[-1]["res"] = float(tokens[11]) try: solutions[-1]["type"] = " ".join([tokens[13], tokens[14]]) except IndexError: # Some solutions don't have type information pass else: # This is a solution line solutions[-1]["vars"][tokens[0]] = complex(float(tokens[2]), float(tokens[3])) return solutions import os # This sets up and processes a PHC run. # 'phcpath' is the full path to PHC on the system; # 'equations' is a text string containing the system in PHC's input format # Returns a list of the solutions # (see the comments on ProcessPHCOutput() above for the description of # each of these solution entries) def RunPHC(phcpath, filename, equations): infilename = filename outfilename = filename + ".phc" infile = file(infilename, "w") infile.write(equations) infile.write("\n\n") infile.close() if os.system(" ".join([phcpath, "-b", infilename, outfilename])) == 0: outfile = file(outfilename) output = outfile.read() outfile.close() else: # For convenience, print the equation sets that cause problems print equations os.remove(infilename) os.remove(outfilename) raise ValueError, "PHC run failed" os.remove(outfilename) os.remove(infilename) return ProcessPHCOutput(output) if __name__ == '__main__': # 2x2.nfg, full support output = RunPHC("./phc", "foo", "4\n" "2*b1 - b2;\n" "b1 + b2 - 1;\n" "a2 - a1;\n" "a1 + a2 - 1;\n") print output # 2x2x2.nfg, full support output = RunPHC("./phc", "foo", "6\n" "9*b1*c1+3*b2*c2-(3*b1*c2+9*b2*c1);\n" "8*a1*c1+4*a2*c2-(4*a1*c2+8*a2*c1);\n" "12*a1*b1+2*a2*b2-(6*a1*b2+6*a2*b1);\n" "a1+a2-1;\n" "b1+b2-1;\n" "c1+c2-1;\n" ) print output gambit-0.2010.09.01/contrib/scripts/enumpoly/README0000644000076500007650000001331011350032206016305 00000000000000gambit-enumphc version 0.2007.03.12 =================================== This is the README for gambit-enumphc, which attempts to compute all (isolated) Nash equilibria of a strategic game by enumerating possible supports and solving the corresponding systems of polynomial equations. This program is similar in principle to the gambit-enumpoly program in the Gambit distribution. It differs in practice in two (useful) ways: (1) The support enumeration method is slightly different (although it appears to produce identical output, just in a different order). The correctness of the implementation here has been established formally, in that it will (a) visit any support at most once, and (b) visit any support that may harbor a Nash equilibrium. It is somewhat more efficient than the implementation in gambit-enumpoly, although the support enumeration process is typically a small portion of the overall running time of this method. Also, this implementation solves on each support as it is generated, as opposed to gambit-enumpoly, which first generates the list of candidate supports, and then solves them. (2) The backend is the PHCPACK solver of Jan Verschelde. This program has been tested with version 2.3.24 of PHCPACK. PHCPACK source, and binaries for several systems, can be obtained either from the main PHCPACK site at http://www.math.uic.edu/~jan/download.html or from the Gambit website http://econweb.tamu.edu/gambit/download.html The version of PHCPACK mirrored on the Gambit site has been tested with this program. Newer versions of PHCPACK may be available from the main site; these should also work with this program, but there is always the possibility of incompatible changes in PHCPACK's output. The PHCPACK "black-box" solver for computing solutions to a system of polynomial equations, which is called by this program, is much more reliable than the polynomial system solver used in gambit-enumpoly. The program is written in Python, and has been tested with Python 2.4. It requires that the Gambit Python extension (available from the Gambit website) has been installed. The program is invoked as python enumphc.py [options] < game.nfg Consult the gambit-enumpoly documentation for general information about the method; this program can be thought of as a "drop-in" replacement for that program (at least for strategic games). What follows documents some differences and usage notes for this program. Note that this program is still young, and may require some care and feeding in terms of the tolerances below. Additional options available: -p: Specify a prefix for the files used to communicate with PHCPACK. In calling the PHCPACK executable, this program creates a file with the polynomial system that is passed to PHCPACK, and PHCPACK communicates the solutions back via another file. If you run multiple instances of this program at once, you will want to specify different prefixes for these files to use. -t: Payoff tolerance. There are typically many solutions to the system of equations for a support that are not Nash equilibria. Some of these solutions fail to be Nash because a strategy not in the support has a higher payoff than the strategies in the support. This parameter adjusts the tolerance for strategies with superior payoffs outside the support; it defaults to 1.0e-6, meaning that a profile is reported to be Nash even if there exists strategies with superior payoffs outside the support, so long as the regret is no more than 1.0e-6. Note that if your payoff scales are large, you will almost certainly want to modify this (1.0e-6 seems about appropriate for games whose payoffs are on [0, 10] or so). -n: Negative probability tolerance. By default, any solution with a negative probability, no matter how small, is not regarded as Nash. Giving a number greater than zero for this parameter allows solutions with negative probabilities no greater in magnitude than the parameter to be considered Nash. Both the -t and -n parameters attempt to address situations in which the game being solved is "almost non-generic", in the sense that there is a nearby game that is degenerate. By default the program only reports equilibria found. Using the -v command-line switch adds three additional pieces of information to the output: (1) candidate supports: as each support is visited, its contents are output with the tag "candidate" (2) singular supports: If for any reason PHCPACK returns with an error on a system, that support is flagged as "singular". This might indicate a bug in PHCPACK; more often, it may indicate that a game is not generic, in that this support (or a closely related one) might harbor a positive-dimensional continuum of equilibria. The program currently does not attempt to further characterize equilibria on such supports (but hopes to do so in the future). (3) non-equilibrium profiles: All solutions to the system of equations which are not Nash equilibria are reported, prefixed by the tag "noneqm". In addition, to these lines is appended the Lyapunov value of the profile. This is a nonnegative value which is zero exactly at Nash equilibria. Small values of the Lyapunov value might indicate that the profile is in fact an approximate Nash equilibrium, i.e., there is in fact an equilibrium nearby, but the profile fails the equilibrium test for numerical reasons. This value can thus be used as a diagnostic for setting the -t and -n parameters (above) appropriately. This program is described in "Towards a Black-Box Solver for Finte Games: Finding All Nash Equilibria with Gambit and PHCpack," which is available at http://econweb.tamu.edu/turocy/papers/enumpoly.html gambit-0.2010.09.01/contrib/scripts/enumpoly/setup.py0000644000076500007650000000036111350032206017141 00000000000000# This is a distutils/py2exe script to build the Windows binary version # of gambit-enumphc from distutils.core import setup import py2exe setup(console=["enumphc.py"], data_files=[(".", [ "phc.exe", "README" ])]) gambit-0.2010.09.01/contrib/scripts/Makefile.am0000644000076500007650000000167311435216077015640 00000000000000## ## This file is part of Gambit ## Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) ## ## FILE: contrib/scripts/Makefile.am ## automake input for sample scripts directory ## ## 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. ## SUBDIRS = enumpoly EXTRA_DIST = gambit-0.2010.09.01/contrib/scripts/Makefile.in0000644000076500007650000003435411441456740015653 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/scripts DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ install-recursive installcheck-recursive installdirs-recursive \ pdf-recursive ps-recursive uninstall-info-recursive \ uninstall-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENUMPOLY_PROGS = @ENUMPOLY_PROGS@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GREP = @GREP@ GUI_PROGS = @GUI_PROGS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ RC_OBJECT = @RC_OBJECT@ RC_OBJECT_PATH = @RC_OBJECT_PATH@ REZFLAGS = @REZFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WITH_ENUMPOLY_FALSE = @WITH_ENUMPOLY_FALSE@ WITH_ENUMPOLY_TRUE = @WITH_ENUMPOLY_TRUE@ WITH_GUI_FALSE = @WITH_GUI_FALSE@ WITH_GUI_TRUE = @WITH_GUI_TRUE@ WX_CFLAGS = @WX_CFLAGS@ WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ WX_CONFIG_PATH = @WX_CONFIG_PATH@ WX_CPPFLAGS = @WX_CPPFLAGS@ WX_CXXFLAGS = @WX_CXXFLAGS@ WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ WX_LIBS = @WX_LIBS@ WX_LIBS_STATIC = @WX_LIBS_STATIC@ WX_RESCOMP = @WX_RESCOMP@ WX_VERSION = @WX_VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = enumpoly EXTRA_DIST = all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu contrib/scripts/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/scripts/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(mkdir_p) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ clean clean-generic clean-libtool clean-recursive ctags \ ctags-recursive distclean distclean-generic distclean-libtool \ distclean-recursive distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive \ mostlyclean mostlyclean-generic mostlyclean-libtool \ mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gambit-0.2010.09.01/COPYING0000644000076500007650000004311011350032206011462 00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 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 Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision 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 generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. gambit-0.2010.09.01/depcomp0000755000076500007650000004426711425044435012034 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2009-04-28.21; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 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. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u="sed s,\\\\\\\\,/,g" depmode=msvisualcpp fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gambit-0.2010.09.01/gambit.desktop0000644000076500007650000000032111350032206013262 00000000000000[Desktop Entry] Version=1.0 Encoding=UTF-8 Name=Gambit Game Analysis Comment=Construction and analysis of finite extensive and strategic games Exec=gambit Icon=gambit Type=Application Categories=Math;Science; gambit-0.2010.09.01/gambit.spec0000644000076500007650000000235211350032206012551 00000000000000Summary: Gambit Game Theory Tools Name: gambit Version: 0.2006.01.20 Release: 1 License: GPL Group: Applications URL: http://econweb.tamu.edu/gambit Source0: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot %description Gambit is a collection of tools for interactively building and analyzing finite games. %prep %setup -q %configure %build make %install %makeinstall mkdir -p $RPM_BUILD_ROOT%{_datadir}/gambit cp -R efg $RPM_BUILD_ROOT%{_datadir}/gambit cp -R nfg $RPM_BUILD_ROOT%{_datadir}/gambit %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc AUTHORS ChangeLog COPYING INSTALL NEWS README %{_bindir}/gambit* %{_libdir}/libgambit* %{_libdir}/liblab* %{_includedir}/libgambit* %{_datadir}/gambit %changelog * Tue Dec 13 2005 Ted Turocy - adding to main distribution; tweak descriptions * Mon Dec 12 2005 Paul E. Johnson - version bump & reorganization * Tue Apr 06 2004 Paul E. Johnson - version bump. * Wed Mar 10 2004 Christopher C. Weis - cleaned up spec file to use macros and proper file inclusions * Thu Oct 23 2003 Paul E. Johnson - Initial build. gambit-0.2010.09.01/INSTALL0000644000076500007650000001210311425044435011470 00000000000000General information ------------------- Gambit uses the standard autotools mechanism for configuring and building. This should be familiar to most users of Un*ces and MacOS X. In general, you just need to unpack the sources, change directory to the top level of the sources (typically of the form gambit-0.yyyy.mm.dd), and do the usual ./configure make sudo make install Command-line options are available to modify the configuration process; do `./configure --help` for information. By default Gambit will be installed in /usr/local. You can change this by replacing configure step with one of the form ./configure --prefix=/your/path/here NOTE: The graphical interface relies on external calls to other programs built in this process, especially for the computation of equilibria. It is strongly recommended that you install the Gambit executables to a directory in your path! Note that if you install to a different location than the default, on some systems (especially linux) you may have to run ldconfig manually. Supported compilers ------------------- Currently, gcc is the only compiler supported. The version of gcc needs to be new enough to handle templates correctly. The oldest versions of gcc known to compile Gambit are 3.4.6 (Linux, Ubuntu) and 3.4.2 (MinGW for Windows, Debian stable). If you wish to use another compiler, the most likely stumbling block is that Gambit uses templated member functions for classes, so the compiler must support these. (Version of gcc prior to 3.4 do not, for example.) For 64-bit users ---------------- The program gambit-enumpoly does not compile on 64-bit systems. A new version of that program is being developed. It is currently being distributed separately on the Gambit website. In the meanwhile, to compile the other programs in Gambit, 64-bit users should add the switch --disable-enumpoly to the configuration step, e.g. ./configure --disable-enumpoly [other options here] For Windows users ----------------- For Windows users wanting to compile Gambit on their own, you'll need to use either the Cygwin or MinGW environments. We do compilation and testing of Gambit on Windows using MinGW, which can be gotten from http://www.mingw.org We prefer MinGW over Cygwin because MinGW will create native Windows applications, whereas Cygwin requires an extra compatibility layer. Note that support for the Borland C++ 5.5 compiler has been removed from Gambit. This is because that compiler is now sufficiently old that significant numbers of special cases had to be handled to reconcile the C++ it accepts with that accepted by modern versions of gcc (which attempt to adhere to the C++ standard). We are open to supporting other compilers in Gambit if there are volunteers willing to contribute and maintain build systems for them. For OS X users -------------- OS X users should being by following the Un*x/Linux instructions above. This will create the command-line tools, and the graphical interface binary called 'gambit'. This graphical interface binary requires the X server to run correctly. For a more native OS X experience, after completing the Un*x/Linux instructions, additionally issue the command make osx-bundle This will create a directory Gambit.app with the graphical interface in an application bundle. This bundle can then be copied (e.g., to /Applications) and used like any other OS X application. Depending on which version of OS X you use, the version of wxWidgets that comes bundled may not be new enough to meet Gambit's requirements. The version that shipped with OS X Tiger, for instance, is not. If you need to build wxWidgets yourself (see below), be sure to tell the ./configure step where to find the version you built by using the --with-wx-prefix parameter. For example, if you install wxWidgets into /usr/local (the default when you build it), configure Gambit with ./configure --with-wx-prefix=/usr/local The graphical interface and wxWidgets ------------------------------------- Gambit requires wxWidgets version 2.6.0 or higher for the graphical interface. See their website at http://www.wxwidgets.org to download this if you need it. Packages of this should be available for most Un*x users through their package managers (apt or rpm). Note that you'll need the appropriate -dev package for wxWidgets to get the header files needed to build Gambit. Un*x users, please note that Gambit at this time only supports the GTK port of wxWidgets, and not the Motif/Lesstif or the Universal ports. Neither of the latter ports support drag-and-drop features, which are heavily used in the graphical interface. If wxWidgets it isn't installed in a standard place (e.g., /usr or /usr/local), you'll need to tell configure where to find it with the --with-wx-prefix=PREFIX option, for example: ./configure --with-wx-prefix=/home/mylogin/wx Finally, if you don't want to build the graphical interface, you can either (a) simply not install wxWidgets, or (b) pass the argument --disable-gui to the configure step, for example, ./configure --disable-gui This will just build the command-line tools, and will not require a wxWidgets installation. gambit-0.2010.09.01/install-sh0000755000076500007650000003253711425044435012460 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2009-04-28.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gambit-0.2010.09.01/ltmain.sh0000644000076500007650000060603111352250350012262 00000000000000# ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. basename="s,^.*/,,g" # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" # The name of this program: progname=`echo "$progpath" | $SED $basename` modename="$progname" # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 PROGRAM=ltmain.sh PACKAGE=libtool VERSION=1.5.26 TIMESTAMP=" (1.1220.2.492 2008/01/30 06:40:56)" # Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE). if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell, and then maybe $echo will work. exec $SHELL "$progpath" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <&2 $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit $EXIT_FAILURE fi # Global variables. mode=$default_mode nonopt= prev= prevopt= run= show="$echo" show_help= execute_dlfiles= duplicate_deps=no preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 ##################################### # Shell function definitions: # This seems to be the best place for them # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $mkdir "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || { $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 exit $EXIT_FAILURE } fi $echo "X$my_tmpdir" | $Xsed } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. func_win32_libid () { win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | \ $SED -n -e '1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $echo $win32_libid_type } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac CC_quoted="$CC_quoted $arg" done case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac CC_quoted="$CC_quoted $arg" done case "$@ " in " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then $echo "$modename: unable to infer tagged configuration" $echo "$modename: specify a tag with \`--tag'" 1>&2 exit $EXIT_FAILURE # else # $echo "$modename: using $tagname tagged configuration" fi ;; esac fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 exit $EXIT_FAILURE fi } # func_extract_archives gentop oldlib ... func_extract_archives () { my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" my_status="" $show "${rm}r $my_gentop" $run ${rm}r "$my_gentop" $show "$mkdir $my_gentop" $run $mkdir "$my_gentop" my_status=$? if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then exit $my_status fi for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) extracted_serial=`expr $extracted_serial + 1` my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" $show "${rm}r $my_xdir" $run ${rm}r "$my_xdir" $show "$mkdir $my_xdir" $run $mkdir "$my_xdir" exit_status=$? if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then exit $exit_status fi case $host in *-darwin*) $show "Extracting $my_xabs" # Do not bother doing anything if just a dry run if test -z "$run"; then darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` if test -n "$darwin_arches"; then darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= $show "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we have a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` lipo -create -output "$darwin_file" $darwin_files done # $darwin_filelist ${rm}r unfat-$$ cd "$darwin_orig_dir" else cd "$darwin_orig_dir" func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches fi # $run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # End of Shell function definitions ##################################### # Darwin sucks eval std_shrext=\"$shrext_cmds\" disable_libs=no # Parse our command line options once, thoroughly. while test "$#" -gt 0 do arg="$1" shift case $arg in -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in execute_dlfiles) execute_dlfiles="$execute_dlfiles $arg" ;; tag) tagname="$arg" preserve_args="${preserve_args}=$arg" # Check whether tagname contains only valid characters case $tagname in *[!-_A-Za-z0-9,/]*) $echo "$progname: invalid tag name: $tagname" 1>&2 exit $EXIT_FAILURE ;; esac case $tagname in CC) # Don't test for the "default" C tag, as we know, it's there, but # not specially marked. ;; *) if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then taglist="$taglist $tagname" # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" else $echo "$progname: ignoring unknown tag $tagname" 1>&2 fi ;; esac ;; *) eval "$prev=\$arg" ;; esac prev= prevopt= continue fi # Have we seen a non-optional argument yet? case $arg in --help) show_help=yes ;; --version) echo "\ $PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP Copyright (C) 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." exit $? ;; --config) ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath # Now print the configurations for the tags. for tagname in $taglist; do ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" done exit $? ;; --debug) $echo "$progname: enabling shell trace mode" set -x preserve_args="$preserve_args $arg" ;; --dry-run | -n) run=: ;; --features) $echo "host: $host" if test "$build_libtool_libs" = yes; then $echo "enable shared libraries" else $echo "disable shared libraries" fi if test "$build_old_libs" = yes; then $echo "enable static libraries" else $echo "disable static libraries" fi exit $? ;; --finish) mode="finish" ;; --mode) prevopt="--mode" prev=mode ;; --mode=*) mode="$optarg" ;; --preserve-dup-deps) duplicate_deps="yes" ;; --quiet | --silent) show=: preserve_args="$preserve_args $arg" ;; --tag) prevopt="--tag" prev=tag preserve_args="$preserve_args --tag" ;; --tag=*) set tag "$optarg" ${1+"$@"} shift prev=tag preserve_args="$preserve_args --tag" ;; -dlopen) prevopt="-dlopen" prev=execute_dlfiles ;; -*) $echo "$modename: unrecognized option \`$arg'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; *) nonopt="$arg" break ;; esac done if test -n "$prevopt"; then $echo "$modename: option \`$prevopt' requires an argument" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi case $disable_libs in no) ;; shared) build_libtool_libs=no build_old_libs=yes ;; static) build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` ;; esac # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 case $nonopt in *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) mode=link for arg do case $arg in -c) mode=compile break ;; esac done ;; *db | *dbx | *strace | *truss) mode=execute ;; *install*|cp|mv) mode=install ;; *rm) mode=uninstall ;; *) # If we have no mode, but dlfiles were specified, then do execute mode. test -n "$execute_dlfiles" && mode=execute # Just use the default operation mode. if test -z "$mode"; then if test -n "$nonopt"; then $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 else $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 fi fi ;; esac fi # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then $echo "$modename: unrecognized option \`-dlopen'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$modename --help --mode=$mode' for more information." # These modes are in order of execution frequency so that they run quickly. case $mode in # libtool compile mode compile) modename="$modename: compile" # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) if test -n "$libobj" ; then $echo "$modename: you cannot specify \`-o' more than once" 1>&2 exit $EXIT_FAILURE fi arg_mode=target continue ;; -static | -prefer-pic | -prefer-non-pic) later="$later $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac lastarg="$lastarg $arg" done IFS="$save_ifs" lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` # Add the arguments to base_compile. base_compile="$base_compile $lastarg" continue ;; * ) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` case $lastarg in # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, and some SunOS ksh mistreat backslash-escaping # in scan sets (worked around with variable expansion), # and furthermore cannot handle '|' '&' '(' ')' in scan sets # at all, so we specify them separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; esac base_compile="$base_compile $lastarg" done # for arg case $arg_mode in arg) $echo "$modename: you must specify an argument for -Xcompile" exit $EXIT_FAILURE ;; target) $echo "$modename: you must specify a target with \`-o'" 1>&2 exit $EXIT_FAILURE ;; *) # Get the name of the library object. [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo xform='[cCFSifmso]' case $libobj in *.ada) xform=ada ;; *.adb) xform=adb ;; *.ads) xform=ads ;; *.asm) xform=asm ;; *.c++) xform=c++ ;; *.cc) xform=cc ;; *.ii) xform=ii ;; *.class) xform=class ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; *.[fF][09]?) xform=[fF][09]. ;; *.for) xform=for ;; *.java) xform=java ;; *.obj) xform=obj ;; *.sx) xform=sx ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` case $libobj in *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; *) $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 exit $EXIT_FAILURE ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -static) build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` case $qlibobj in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qlibobj="\"$qlibobj\"" ;; esac test "X$libobj" != "X$qlibobj" \ && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir= else xdir=$xdir/ fi lobj=${xdir}$objdir/$objname if test -z "$base_compile"; then $echo "$modename: you must specify a compilation command" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi $run $rm $removelist trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" removelist="$removelist $output_obj $lockfile" trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $run ln "$progpath" "$lockfile" 2>/dev/null; do $show "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $echo "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit $EXIT_FAILURE fi $echo "$srcfile" > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` case $qsrcfile in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qsrcfile="\"$qsrcfile\"" ;; esac $run $rm "$libobj" "${libobj}T" # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then $echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then $show "$mv $output_obj $lobj" if $run $mv $output_obj $lobj; then : else error=$? $run $rm $removelist exit $error fi fi # Append the name of the PIC object to the libtool object file. test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then $echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then $show "$mv $output_obj $obj" if $run $mv $output_obj $obj; then : else error=$? $run $rm $removelist exit $error fi fi # Append the name of the non-PIC object the libtool object file. # Only append if the libtool object file exists. test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test ;; *) qarg=$arg ;; esac libtool_args="$libtool_args $qarg" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) compile_command="$compile_command @OUTPUT@" finalize_command="$finalize_command @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. compile_command="$compile_command @SYMFILE@" finalize_command="$finalize_command @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" if test ! -f "$arg"; then $echo "$modename: symbol file \`$arg' does not exist" exit $EXIT_FAILURE fi prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat $save_arg` do # moreargs="$moreargs $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then pic_object= non_pic_object= # Read the .lo file # If there is no directory component, then add one. case $arg in */* | *\\*) . $arg ;; *) . ./$arg ;; esac if test -z "$pic_object" || \ test -z "$non_pic_object" || test "$pic_object" = none && \ test "$non_pic_object" = none; then $echo "$modename: cannot find name of object for \`$arg'" 1>&2 exit $EXIT_FAILURE fi # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. libobjs="$libobjs $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object non_pic_objects="$non_pic_objects $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi else # Only an error if not doing a dry-run. if test -z "$run"; then $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 exit $EXIT_FAILURE else # Dry-run case. # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` libobjs="$libobjs $pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi fi done else $echo "$modename: link input file \`$save_arg' does not exist" exit $EXIT_FAILURE fi arg=$save_arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit $EXIT_FAILURE ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= compile_command="$compile_command $wl$qarg" finalize_command="$finalize_command $wl$qarg" continue ;; xcclinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; shrext) shrext_cmds="$arg" prev= continue ;; darwin_framework|darwin_framework_skip) test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" prev= continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 continue ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: more than one -exported-symbols argument is not allowed" exit $EXIT_FAILURE fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework|-arch|-isysroot) case " $CC " in *" ${arg} ${1} "* | *" ${arg} ${1} "*) prev=darwin_framework_skip ;; *) compiler_flags="$compiler_flags $arg" prev=darwin_framework ;; esac compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" ;; esac continue ;; -L*) dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" notinst_path="$notinst_path $dir" fi dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; *) dllsearchpath="$dllsearchpath:$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework deplibs="$deplibs -framework System" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. -model) compile_command="$compile_command $arg" compiler_flags="$compiler_flags $arg" finalize_command="$finalize_command $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) compiler_flags="$compiler_flags $arg" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -module) module=yes continue ;; # -64, -mips[0-9] enable 64-bit mode on the SGI compiler # -r[0-9][0-9]* specifies the processor on the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler # +DA*, +DD* enable 64-bit mode on the HP compiler # -q* pass through compiler args for the IBM compiler # -m* pass through architecture-specific compiler args for GCC # -m*, -t[45]*, -txscale* pass through architecture-specific # compiler args for GCC # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC # -F/path gives path to uninstalled frameworks, gcc on darwin # @file GCC response files -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" compiler_flags="$compiler_flags $arg" continue ;; -shrext) prev=shrext continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit $EXIT_FAILURE ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Wl,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $wl$flag" linker_flags="$linker_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # Some other compiler flag. -* | +*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; *.$objext) # A standard object. objs="$objs $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then pic_object= non_pic_object= # Read the .lo file # If there is no directory component, then add one. case $arg in */* | *\\*) . $arg ;; *) . ./$arg ;; esac if test -z "$pic_object" || \ test -z "$non_pic_object" || test "$pic_object" = none && \ test "$non_pic_object" = none; then $echo "$modename: cannot find name of object for \`$arg'" 1>&2 exit $EXIT_FAILURE fi # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. libobjs="$libobjs $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object non_pic_objects="$non_pic_objects $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi else # Only an error if not doing a dry-run. if test -z "$run"; then $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 exit $EXIT_FAILURE else # Dry-run case. # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` libobjs="$libobjs $pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi done # argument parsing loop if test -n "$prev"; then $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi oldlibs= # calculate the name of the file, without its directory outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi # Create the object directory. if test ! -d "$output_objdir"; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir exit_status=$? if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then exit $exit_status fi fi # Determine the type of output case $output in "") $echo "$modename: you must specify an output file" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac case $host in *cygwin* | *mingw* | *pw32*) # don't eliminate duplications in $postdeps and $predeps duplicate_compiler_generated_deps=yes ;; *) duplicate_compiler_generated_deps=$duplicate_deps ;; esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if test "X$duplicate_deps" = "Xyes" ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; esac pre_post_deps="$pre_post_deps $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries case $linkmode in lib) passes="conv link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 exit $EXIT_FAILURE ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else compiler_flags="$compiler_flags $deplib" fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then library_names= old_library= case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; *) $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` if eval $echo \"$deplib\" 2>/dev/null \ | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then $echo $echo "*** Warning: Trying to link with static lib archive $deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because the file extensions .$libext of this argument makes me believe" $echo "*** that it is just a static archive that I should not used here." else $echo $echo "*** Warning: Linking the shared library $output against the" $echo "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 exit $EXIT_FAILURE fi # Check to see that this really is a libtool archive. if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." dlname= dlopen= dlpreopen= libdir= library_names= old_library= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit $EXIT_FAILURE fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then $echo "$modename: \`$lib' is not a convenience library" 1>&2 exit $EXIT_FAILURE fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit $EXIT_FAILURE fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 exit $EXIT_FAILURE fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. dlprefiles="$dlprefiles $lib $dependency_libs" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 abs_ladir="$ladir" fi ;; esac laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then $echo "$modename: warning: library \`$lib' was moved." 1>&2 dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi fi # $installed = yes name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 exit $EXIT_FAILURE fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; *) temp_rpath="$temp_rpath $absdir" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes ; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi # This is a shared library # Warn about portability, can't link against -module's on # some systems (darwin) if test "$shouldnotlink" = yes && test "$pass" = link ; then $echo if test "$linkmode" = prog; then $echo "*** Warning: Linking the executable $output against the loadable module" else $echo "*** Warning: Linking the shared library $output against the loadable module" fi $echo "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names realname="$2" shift; shift libname=`eval \\$echo \"$libname_spec\"` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw*) major=`expr $current - $age` versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" soname=`$echo $soroot | ${SED} -e 's/^.*\///'` newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else $show "extracting exported symbol list from \`$soname'" save_ifs="$IFS"; IFS='~' cmds=$extract_expsyms_cmds for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else $show "generating import library for \`$soname'" save_ifs="$IFS"; IFS='~' cmds=$old_archive_from_expsyms_cmds for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a module then we can not link against # it, someone is ignoring the new warnings I added if /usr/bin/file -L $add 2> /dev/null | $EGREP ": [^:]* bundle" >/dev/null ; then $echo "** Warning, lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $echo $echo "** And there doesn't seem to be a static archive available" $echo "** The link will probably fail, sorry" else add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then $echo "$modename: configuration error: unsupported hardcode properties" exit $EXIT_FAILURE fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && \ test "$hardcode_minus_L" != yes && \ test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. $echo $echo "*** Warning: This system can not link to static lib archive $lib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then $echo "*** But as you try to build a module library, libtool will still create " $echo "*** a static module, that should work as long as the dlopening application" $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then $echo $echo "*** However, this would only work if libtool was able to extract symbol" $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" $echo "*** not find such a program. So, this module is probably useless." $echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$deplib" && dir="." # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" fi ;; esac if grep "^installed=no" $deplib > /dev/null; then path="$absdir/$objdir" else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi if test "$absdir" != "$libdir"; then $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 fi path="$absdir" fi depdepl= case $host in *-*-darwin*) # we do not want to link against static libs, # but need to link against shared eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` eval deplibdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$deplibdir/$depdepl" ; then depdepl="$deplibdir/$depdepl" elif test -f "$path/$depdepl" ; then depdepl="$path/$depdepl" else # Can't find it, oh well... depdepl= fi # do not add paths which are already there case " $newlib_search_path " in *" $path "*) ;; *) newlib_search_path="$newlib_search_path $path";; esac fi path="" ;; *) path="-L$path" ;; esac ;; -l*) case $host in *-*-darwin*) # Again, we only want to link against shared libraries eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` for tmp in $newlib_search_path ; do if test -f "$tmp/lib$tmp_libs.dylib" ; then eval depdepl="$tmp/lib$tmp_libs.dylib" break fi done path="" ;; *) continue ;; esac ;; *) continue ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac case " $deplibs " in *" $depdepl "*) ;; *) deplibs="$depdepl $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then tmp_libs="$tmp_libs $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) case " $deplibs" in *\ -l* | *\ -L*) $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 ;; esac if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 fi if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 fi # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) if test "$module" = no; then $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 exit $EXIT_FAILURE else $echo $echo "*** Warning: Linking the shared library $output against the non-libtool" $echo "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi if test "$dlself" != no; then $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 fi set dummy $rpath if test "$#" -gt 2; then $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 fi else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 IFS="$save_ifs" if test -n "$8"; then $echo "$modename: too many parameters to \`-version-info'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$2" number_minor="$3" number_revision="$4" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows|none) current=`expr $number_major + $number_minor` age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) current=`expr $number_major + $number_minor` age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$2" revision="$3" age="$4" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE ;; esac if test "$age" -gt "$current"; then $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header major=.`expr $current - $age` versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current"; ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then major=`expr $current - $age` else major=`expr $current - $age + 1` fi case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do iface=`expr $revision - $loop` loop=`expr $loop - 1` verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) major=.`expr $current - $age` versuffix="$major.$age.$revision" ;; osf) major=.`expr $current - $age` versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do iface=`expr $current - $loop` loop=`expr $loop - 1` verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. major=`expr $current - $age` versuffix="-$major" ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit $EXIT_FAILURE ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$echo "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi removelist="$removelist $p" ;; *) ;; esac done if test -n "$removelist"; then $show "${rm}r $removelist" $run ${rm}r $removelist fi fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` # deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` # dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs -framework System" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $rm conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null \ | grep " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ | ${SED} 10q \ | $EGREP "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $echo $echo "*** Warning: linker path does not have real file for library $a_deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $echo "*** with $libname but no candidates were found. (...for file magic test)" else $echo "*** with $libname and none of the candidates passed a file format test" $echo "*** using a file magic. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do name=`expr $a_deplib : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) newdeplibs="$newdeplibs $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval \\$echo \"$libname_spec\"` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval $echo \"$potent_lib\" 2>/dev/null \ | ${SED} 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $echo $echo "*** Warning: linker path does not have real file for library $a_deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $echo "*** with $libname but no candidates were found. (...for regex pattern test)" else $echo "*** with $libname and none of the candidates passed a file format test" $echo "*** using a regex pattern. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ -e 's/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` done fi if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ | grep . >/dev/null; then $echo if test "X$deplibs_check_method" = "Xnone"; then $echo "*** Warning: inter-library dependencies are not supported in this platform." else $echo "*** Warning: inter-library dependencies are not known to be supported." fi $echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then $echo $echo "*** Warning: libtool could not satisfy all declared inter-library" $echo "*** dependencies of module $libname. Therefore, libtool will create" $echo "*** a static module, that should work as long as the dlopening" $echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then $echo $echo "*** However, this would only work if libtool was able to extract symbol" $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" $echo "*** not find such a program. So, this module is probably useless." $echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else $echo "*** The inter-library dependencies that have been dropped here will be" $echo "*** automatically added whenever a program is linked with this library" $echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then $echo $echo "*** Since this library must not contain undefined symbols," $echo "*** because either the platform does not support them or" $echo "*** it was explicitly requested with -no-undefined," $echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then case $archive_cmds in *\$LD*) eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" ;; *) eval dep_rpath=\"$hardcode_libdir_flag_spec\" ;; esac else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names realname="$2" shift; shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do linknames="$linknames $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" if len=`expr "X$cmd" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then $show "$cmd" $run eval "$cmd" || exit $? skipped_export=false else # The command line is too long to execute in one step. $show "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex"; then $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' $show "$mv \"${export_symbols}T\" \"$export_symbols\"" $run eval '$mv "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $convenience libobjs="$libobjs $func_extract_archives_result" fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise. $echo "creating reloadable object files..." # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output output_la=`$echo "X$output" | $Xsed -e "$basename"` # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= delfiles= last_robj= k=1 output=$output_objdir/$output_la-${k}.$objext # Loop over the list of objects to be linked. for obj in $save_libobjs do eval test_cmds=\"$reload_cmds $objlist $last_robj\" if test "X$objlist" = X || { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len"; }; then objlist="$objlist $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else # All subsequent reloadable object files will link in # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext k=`expr $k + 1` output=$output_objdir/$output_la-${k}.$objext objlist=$obj len=1 fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if ${skipped_export-false}; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols libobjs=$output # Append the command to create the export file. eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" fi # Set up a command to remove the reloadable object files # after they are used. i=0 while test "$i" -lt "$k" do i=`expr $i + 1` delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" done $echo "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi # Append the command to remove the reloadable object files # to the just-reset $cmds. eval cmds=\"\$cmds~\$rm $delfiles\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then $show "${rm}r $gentop" $run ${rm}r "$gentop" fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) case " $deplibs" in *\ -l* | *\ -L*) $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 ;; esac if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 fi case $output in *.lo) if test -n "$objs$old_deplibs"; then $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 exit $EXIT_FAILURE fi libobj="$output" obj=`$echo "X$output" | $Xsed -e "$lo2o"` ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $run $rm $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` else gentop="$output_objdir/${obj}x" generated="$generated $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" cmds=$reload_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $run eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" cmds=$reload_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; esac if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 fi if test "$preload" = yes; then if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && test "$dlopen_self_static" = unknown; then $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." fi fi case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac case $host in *darwin*) # Don't allow lazy linking, it breaks C++ global constructors if test "$tagname" = CXX ; then compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" fi ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done compile_deplibs="$new_libs" compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; *) dllsearchpath="$dllsearchpath:$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then dlsyms="${outputname}S.c" else $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 fi fi if test -n "$dlsyms"; then case $dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${outputname}.nm" $show "$rm $nlist ${nlist}S ${nlist}T" $run $rm "$nlist" "${nlist}S" "${nlist}T" # Parse the name list into a source file. $show "creating $output_objdir/$dlsyms" test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ /* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ /* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ #ifdef __cplusplus extern \"C\" { #endif /* Prevent the only kind of declaration conflicts we can make. */ #define lt_preloaded_symbols some_other_symbol /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then $show "generating symbol list for \`$output'" test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for arg in $progfiles; do $show "extracting global C symbols from \`$arg'" $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi if test -n "$export_symbols_regex"; then $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $run $rm $export_symbols $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* ) $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac else $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* ) $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac fi fi for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` $run eval '$echo ": $name " >> "$nlist"' $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -z "$run"; then # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $mv "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if grep -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else grep -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' else $echo '/* NONE */' >> "$output_objdir/$dlsyms" fi $echo >> "$output_objdir/$dlsyms" "\ #undef lt_preloaded_symbols #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ " case $host in *cygwin* | *mingw* ) $echo >> "$output_objdir/$dlsyms" "\ /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs */ struct { " ;; * ) $echo >> "$output_objdir/$dlsyms" "\ const struct { " ;; esac $echo >> "$output_objdir/$dlsyms" "\ const char *name; lt_ptr address; } lt_preloaded_symbols[] = {\ " eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" $echo >> "$output_objdir/$dlsyms" "\ {0, (lt_ptr) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " fi pic_flag_for_symtable= case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; esac;; *-*-hpux*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag";; esac esac # Now compile the dynamic symbol file. $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. case $host in *cygwin* | *mingw* ) if test -f "$output_objdir/${outputname}.def" ; then compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP` else compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` fi ;; * ) compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` ;; esac ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 exit $EXIT_FAILURE ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP` fi if test "$need_relink" = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" exit_status=$? # Delete the generated files. if test -n "$dlsyms"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi exit $exit_status fi if test -n "$shlibpath_var"; then # We should set the shlibpath_var rpath= for dir in $temp_rpath; do case $dir in [\\/]* | [A-Za-z]:[\\/]*) # Absolute path. rpath="$rpath$dir:" ;; *) # Relative path: add a thisdir entry. rpath="$rpath\$thisdir/$dir:" ;; esac done temp_rpath="$rpath" fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $run $rm $output # Link the executable and exit $show "$link_command" $run eval "$link_command" || exit $? exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 $echo "$modename: \`$output' will be relinked during installation" 1>&2 else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname $show "$link_command" $run eval "$link_command" || exit $? # Now create the wrapper script. $show "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP` fi # Quote $echo for shipping. if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then case $progpath in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; esac qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if our run command is non-null. if test -z "$run"; then # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) output_name=`basename $output` output_path=`dirname $output` cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $rm $cwrappersource $cwrapper trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 cat > $cwrappersource <> $cwrappersource<<"EOF" #include #include #include #include #include #include #include #include #include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) /* -DDEBUG is fairly common in CFLAGS. */ #undef DEBUG #if defined DEBUGWRAPPER # define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) #else # define DEBUG(format, ...) #endif const char *program_name = NULL; void * xmalloc (size_t num); char * xstrdup (const char *string); const char * base_name (const char *name); char * find_executable(const char *wrapper); int check_executable(const char *path); char * strendzap(char *str, const char *pat); void lt_fatal (const char *message, ...); int main (int argc, char *argv[]) { char **newargz; int i; program_name = (char *) xstrdup (base_name (argv[0])); DEBUG("(main) argv[0] : %s\n",argv[0]); DEBUG("(main) program_name : %s\n",program_name); newargz = XMALLOC(char *, argc+2); EOF cat >> $cwrappersource <> $cwrappersource <<"EOF" newargz[1] = find_executable(argv[0]); if (newargz[1] == NULL) lt_fatal("Couldn't find %s", argv[0]); DEBUG("(main) found exe at : %s\n",newargz[1]); /* we know the script has the same name, without the .exe */ /* so make sure newargz[1] doesn't end in .exe */ strendzap(newargz[1],".exe"); for (i = 1; i < argc; i++) newargz[i+1] = xstrdup(argv[i]); newargz[argc+1] = NULL; for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" return 127; } void * xmalloc (size_t num) { void * p = (void *) malloc (num); if (!p) lt_fatal ("Memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL ; } const char * base_name (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha ((unsigned char)name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return base; } int check_executable(const char * path) { struct stat st; DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); if ((!path) || (!*path)) return 0; if ((stat (path, &st) >= 0) && ( /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ #if defined (S_IXOTH) ((st.st_mode & S_IXOTH) == S_IXOTH) || #endif #if defined (S_IXGRP) ((st.st_mode & S_IXGRP) == S_IXGRP) || #endif ((st.st_mode & S_IXUSR) == S_IXUSR)) ) return 1; else return 0; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise */ char * find_executable (const char* wrapper) { int has_slash = 0; const char* p; const char* p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char* concat_name; DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable(concat_name)) return concat_name; XFREE(concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable(concat_name)) return concat_name; XFREE(concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char* path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char* q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR(*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen(tmp); concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable(concat_name)) return concat_name; XFREE(concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen(tmp); concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable(concat_name)) return concat_name; XFREE(concat_name); return NULL; } char * strendzap(char *str, const char *pat) { size_t len, patlen; assert(str != NULL); assert(pat != NULL); len = strlen(str); patlen = strlen(pat); if (patlen <= len) { str += len - patlen; if (strcmp(str, pat) == 0) *str = '\0'; } return str; } static void lt_error_core (int exit_status, const char * mode, const char * message, va_list ap) { fprintf (stderr, "%s: %s: ", program_name, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, "FATAL", message, ap); va_end (ap); } EOF # we should really use a build-platform specific compiler # here, but OTOH, the wrappers (shell script and this C one) # are only useful if you want to execute the "real" binary. # Since the "real" binary is built for $host, then this # wrapper might as well be built for $host, too. $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource ;; esac $rm $output trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 $echo > $output "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE). if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variable: notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$echo are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then echo=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then # Yippee, \$echo works! : else # Restart under the correct shell, and then maybe \$echo will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $echo >> $output "\ # Find the directory that this script lives in. thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $echo >> $output "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || \\ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $mkdir \"\$progdir\" else $rm \"\$progdir/\$file\" fi" $echo >> $output "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $echo \"\$relink_command_output\" >&2 $rm \"\$progdir/\$file\" exit $EXIT_FAILURE fi fi $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $rm \"\$progdir/\$program\"; $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } $rm \"\$progdir/\$file\" fi" else $echo >> $output "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $echo >> $output "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $echo >> $output "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $echo >> $output "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $echo >> $output "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $echo >> $output "\ exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $echo >> $output "\ \$echo \"\$0: cannot exec \$program \$*\" exit $EXIT_FAILURE fi else # The program doesn't exist. \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 $echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit $EXIT_FAILURE fi fi\ " chmod +x $output fi exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $addlibs oldobjs="$oldobjs $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do $echo "X$obj" | $Xsed -e 's%^.*/%%' done | sort | sort -uc >/dev/null 2>&1); then : else $echo "copying selected object files to avoid basename conflicts..." if test -z "$gentop"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "$mkdir $gentop" $run $mkdir "$gentop" exit_status=$? if test "$exit_status" -ne 0 && test ! -d "$gentop"; then exit $exit_status fi fi save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase counter=`expr $counter + 1` case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" $run ln "$obj" "$gentop/$newobj" || $run cp "$obj" "$gentop/$newobj" oldobjs="$oldobjs $gentop/$newobj" ;; *) oldobjs="$oldobjs $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" if len=`expr "X$cmds" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts $echo "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done for obj in $save_oldobjs do oldobjs="$objlist $obj" objlist="$objlist $obj" eval test_cmds=\"$old_archive_cmds\" if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do eval cmd=\"$cmd\" IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$generated"; then $show "${rm}r$generated" $run ${rm}r$generated fi # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" $show "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. if test -z "$run"; then for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi newdlfiles="$newdlfiles $libdir/$name" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE fi newdlprefiles="$newdlprefiles $libdir/$name" done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlfiles="$newdlfiles $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlprefiles="$newdlprefiles $abs" done dlprefiles="$newdlprefiles" fi $rm $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $echo > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $echo >> $output "\ relink_command=\"$relink_command\"" fi done fi # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? ;; esac exit $EXIT_SUCCESS ;; # libtool install mode install) modename="$modename: install" # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $echo "X$nonopt" | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac install_prog="$arg " arg="$1" shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac install_prog="$install_prog$arg" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) case " $install_prog " in *[\\\ /]cp\ *) ;; *) prev=$arg ;; esac ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac install_prog="$install_prog $arg" done if test -z "$install_prog"; then $echo "$modename: you must specify an install program" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi if test -n "$prev"; then $echo "$modename: the \`$prev' option requires an argument" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi if test -z "$files"; then if test -z "$dest"; then $echo "$modename: no file or destination specified" 1>&2 else $echo "$modename: you must specify a destination" 1>&2 fi $echo "$help" 1>&2 exit $EXIT_FAILURE fi # Strip any trailing slash from the destination. dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` test "X$destdir" = "X$dest" && destdir=. destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` # Not a directory, so check to see that there is only one file specified. set dummy $files if test "$#" -gt 2; then $echo "$modename: \`$dest' is not a directory" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi library_names= old_library= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ test "X$dir" = "X$file/" && dir= dir="$dir$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. if test "$inst_prefix_dir" = "$destdir"; then $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 exit $EXIT_FAILURE fi if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP` else relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP` fi $echo "$modename: warning: relinking \`$file'" 1>&2 $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 exit $EXIT_FAILURE fi fi # See the names of the shared library. set dummy $library_names if test -n "$2"; then realname="$2" shift shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. $show "$install_prog $dir/$srcname $destdir/$realname" $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$striplib $destdir/$realname" $run eval "$striplib $destdir/$realname" || exit $? fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do if test "$linkname" != "$realname"; then $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" fi done fi # Do each command in the postinstall commands. lib="$destdir/$realname" cmds=$postinstall_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' fi exit $lt_exit } done IFS="$save_ifs" fi # Install the pseudo-library for information purposes. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` instname="$dir/$name"i $show "$install_prog $instname $destdir/$name" $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` ;; *.$objext) staticdest="$destfile" destfile= ;; *) $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; esac # Install the libtool object if requested. if test -n "$destfile"; then $show "$install_prog $file $destfile" $run eval "$install_prog $file $destfile" || exit $? fi # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` $show "$install_prog $staticobj $staticdest" $run eval "$install_prog \$staticobj \$staticdest" || exit $? fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then file=`$echo $file|${SED} 's,.exe$,,'` stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin*|*mingw*) wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` ;; *) wrapper=$file ;; esac if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then notinst_deplibs= relink_command= # Note that it is not necessary on cygwin/mingw to append a dot to # foo even if both foo and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. # # If there is no directory component, then add one. case $wrapper in */* | *\\*) . ${wrapper} ;; *) . ./${wrapper} ;; esac # Check the variables that should have been set. if test -z "$notinst_deplibs"; then $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 exit $EXIT_FAILURE fi finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then # If there is no directory component, then add one. case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac fi libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 finalize=no fi done relink_command= # Note that it is not necessary on cygwin/mingw to append a dot to # foo even if both foo and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. # # If there is no directory component, then add one. case $wrapper in */* | *\\*) . ${wrapper} ;; *) . ./${wrapper} ;; esac outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then tmpdir=`func_mktempdir` file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP` $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 ${rm}r "$tmpdir" continue fi file="$outputname" else $echo "$modename: warning: cannot relink \`$file'" 1>&2 fi else # Install the binary that we compiled earlier. file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` ;; esac ;; esac $show "$install_prog$stripme $file $destfile" $run eval "$install_prog\$stripme \$file \$destfile" || exit $? test -n "$outputname" && ${rm}r "$tmpdir" ;; esac done for file in $staticlibs; do name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` # Set up the ranlib parameters. oldlib="$destdir/$name" $show "$install_prog $file $oldlib" $run eval "$install_prog \$file \$oldlib" || exit $? if test -n "$stripme" && test -n "$old_striplib"; then $show "$old_striplib $oldlib" $run eval "$old_striplib $oldlib" || exit $? fi # Do each command in the postinstall commands. cmds=$old_postinstall_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$future_libdirs"; then $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 fi if test -n "$current_libdirs"; then # Maybe just do a dry run. test -n "$run" && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi ;; # libtool finish mode finish) modename="$modename: finish" libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. cmds=$finish_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" || admincmds="$admincmds $cmd" done IFS="$save_ifs" fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $run eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. test "$show" = : && exit $EXIT_SUCCESS $echo "X----------------------------------------------------------------------" | $Xsed $echo "Libraries have been installed in:" for libdir in $libdirs; do $echo " $libdir" done $echo $echo "If you ever happen to want to link against installed libraries" $echo "in a given directory, LIBDIR, you must either use libtool, and" $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" $echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" $echo " during execution" fi if test -n "$runpath_var"; then $echo " - add LIBDIR to the \`$runpath_var' environment variable" $echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $echo " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $echo " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi $echo $echo "See any operating system documentation about shared libraries for" $echo "more information, such as the ld(1) and ld.so(8) manual pages." $echo "X----------------------------------------------------------------------" | $Xsed exit $EXIT_SUCCESS ;; # libtool execute mode execute) modename="$modename: execute" # The first argument is the command name. cmd="$nonopt" if test -z "$cmd"; then $echo "$modename: you must specify a COMMAND" 1>&2 $echo "$help" exit $EXIT_FAILURE fi # Handle -dlopen flags immediately. for file in $execute_dlfiles; do if test ! -f "$file"; then $echo "$modename: \`$file' is not a file" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi dir= case $file in *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi # Read the libtool library. dlname= library_names= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" continue fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else if test ! -f "$dir/$dlname"; then $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 exit $EXIT_FAILURE fi fi ;; *.lo) # Just add the directory containing the .lo file. dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. ;; *) $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` args="$args \"$file\"" done if test -z "$run"; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" $echo "export $shlibpath_var" fi $echo "$cmd$args" exit $EXIT_SUCCESS fi ;; # libtool clean and uninstall mode clean | uninstall) modename="$modename: $mode" rm="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) rm="$rm $arg"; rmforce=yes ;; -*) rm="$rm $arg" ;; *) files="$files $arg" ;; esac done if test -z "$rm"; then $echo "$modename: you must specify an RM program" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE fi rmdirs= origobjdir="$objdir" for file in $files; do dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$file"; then dir=. objdir="$origobjdir" else objdir="$dir/$origobjdir" fi name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` test "$mode" = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test "$mode" = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if (test -L "$file") >/dev/null 2>&1 \ || (test -h "$file") >/dev/null 2>&1 \ || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then . $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" case "$mode" in clean) case " $library_names " in # " " in the beginning catches empty $dlname *" $dlname "*) ;; *) rmfiles="$rmfiles $objdir/$dlname" ;; esac test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. cmds=$postuninstall_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" if test "$?" -ne 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. cmds=$old_postuninstall_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" $run eval "$cmd" if test "$?" -ne 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # Read the .lo file . $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" \ && test "$pic_object" != none; then rmfiles="$rmfiles $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" \ && test "$non_pic_object" != none; then rmfiles="$rmfiles $dir/$non_pic_object" fi fi ;; *) if test "$mode" = clean ; then noexename=$name case $file in *.exe) file=`$echo $file|${SED} 's,.exe$,,'` noexename=`$echo $name|${SED} 's,.exe$,,'` # $file with .exe has already been added to rmfiles, # add $file without .exe rmfiles="$rmfiles $file" ;; esac # Do a test to see if this is a libtool program. if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then relink_command= . $dir/$noexename # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi if test "X$noexename" != "X$name" ; then rmfiles="$rmfiles $objdir/lt-${noexename}.c" fi fi fi ;; esac $show "$rm $rmfiles" $run $rm $rmfiles || exit_status=1 done objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then $show "rmdir $dir" $run rmdir $dir >/dev/null 2>&1 fi done exit $exit_status ;; "") $echo "$modename: you must specify a MODE" 1>&2 $echo "$generic_help" 1>&2 exit $EXIT_FAILURE ;; esac if test -z "$exec_cmd"; then $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$generic_help" 1>&2 exit $EXIT_FAILURE fi fi # test -z "$show_help" if test -n "$exec_cmd"; then eval exec $exec_cmd exit $EXIT_FAILURE fi # We need to display help for each of the modes. case $mode in "") $echo \ "Usage: $modename [OPTION]... [MODE-ARG]... Provide generalized library-building support services. --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --finish same as \`--mode=finish' --help display this help message and exit --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] --quiet same as \`--silent' --silent don't print informational messages --tag=TAG use configuration variables from tag TAG --version print version information MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for a more detailed description of MODE. Report bugs to ." exit $EXIT_SUCCESS ;; clean) $echo \ "Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $echo \ "Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -static always build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $echo \ "Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $echo \ "Usage: $modename [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $echo \ "Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $echo \ "Usage: $modename [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $echo \ "Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$help" 1>&2 exit $EXIT_FAILURE ;; esac $echo $echo "Try \`$modename --help' for more information about other modes." exit $? # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared disable_libs=shared # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static disable_libs=static # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: gambit-0.2010.09.01/Makefile.am0000644000076500007650000005166411441453534012514 00000000000000## ## This file is part of Gambit ## Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) ## ## FILE: Makefile.am ## Top-level automake input file for Gambit ## ## 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. ## SUBDIRS = contrib ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = \ gambit.spec \ gambit.desktop \ contrib/mac/Info.plist \ src/labenski/README.txt \ src/labenski/art/grab.xpm \ src/labenski/art/hand.xpm \ src/labenski/art/ledgreen.xpm \ src/labenski/art/ledgrey.xpm \ src/labenski/doc/README-plotctrl.txt \ src/labenski/doc/README-sheet.txt \ src/labenski/doc/README-wxthings.txt \ src/labenski/include/wx/wxthings/bitmaps/copy.xpm \ src/labenski/include/wx/wxthings/bitmaps/cut.xpm \ src/labenski/include/wx/wxthings/bitmaps/findnext.xpm \ src/labenski/include/wx/wxthings/bitmaps/find.xpm \ src/labenski/include/wx/wxthings/bitmaps/grab.xpm \ src/labenski/include/wx/wxthings/bitmaps/hand.xpm \ src/labenski/include/wx/wxthings/bitmaps/help.xpm \ src/labenski/include/wx/wxthings/bitmaps/new.xpm \ src/labenski/include/wx/wxthings/bitmaps/open.xpm \ src/labenski/include/wx/wxthings/bitmaps/paste.xpm \ src/labenski/include/wx/wxthings/bitmaps/preview.xpm \ src/labenski/include/wx/wxthings/bitmaps/print.xpm \ src/labenski/include/wx/wxthings/bitmaps/question.xpm \ src/labenski/include/wx/wxthings/bitmaps/redo.xpm \ src/labenski/include/wx/wxthings/bitmaps/replace.xpm \ src/labenski/include/wx/wxthings/bitmaps/saveall.xpm \ src/labenski/include/wx/wxthings/bitmaps/saveas.xpm \ src/labenski/include/wx/wxthings/bitmaps/spell.xpm \ src/labenski/include/wx/wxthings/bitmaps/undo.xpm \ src/gui/bitmaps/about.xpm \ src/gui/bitmaps/adddecimal.xpm \ src/gui/bitmaps/calc.xpm \ src/gui/bitmaps/close.xpm \ src/gui/bitmaps/color.xpm \ src/gui/bitmaps/datasrc.xpm \ src/gui/bitmaps/deldecimal.xpm \ src/gui/bitmaps/dice.xpm \ src/gui/bitmaps/efg.ico \ src/gui/bitmaps/exit.xpm \ src/gui/bitmaps/font.xpm \ src/gui/bitmaps/gambitbig.xpm \ src/gui/bitmaps/gambit.bmp \ src/gui/bitmaps/gambit.ico \ src/gui/bitmaps/gambit.xpm \ src/gui/bitmaps/label.xpm \ src/gui/bitmaps/layout.xpm \ src/gui/bitmaps/move.xpm \ src/gui/bitmaps/newcol.xpm \ src/gui/bitmaps/newplayer.xpm \ src/gui/bitmaps/newrow.xpm \ src/gui/bitmaps/newtable.xpm \ src/gui/bitmaps/newtree.xpm \ src/gui/bitmaps/new.xpm \ src/gui/bitmaps/next.xpm \ src/gui/bitmaps/nfg.ico \ src/gui/bitmaps/open.xpm \ src/gui/bitmaps/person.xpm \ src/gui/bitmaps/preview.xpm \ src/gui/bitmaps/prev.xpm \ src/gui/bitmaps/print.xpm \ src/gui/bitmaps/profiles.xpm \ src/gui/bitmaps/redo.xpm \ src/gui/bitmaps/saveas.xpm \ src/gui/bitmaps/savedata.xpm \ src/gui/bitmaps/save.xpm \ src/gui/bitmaps/stop.xpm \ src/gui/bitmaps/table.xpm \ src/gui/bitmaps/tobegin.xpm \ src/gui/bitmaps/toend.xpm \ src/gui/bitmaps/tree.xpm \ src/gui/bitmaps/undo.xpm \ src/gui/bitmaps/zoomfit.xpm \ src/gui/bitmaps/zoomin.xpm \ src/gui/bitmaps/zoomout.xpm \ src/gui/bitmaps/zoom1.xpm \ src/gui/bitmaps/gambitrc.rc \ contrib/games/2s2x2x2.efg \ contrib/games/2smp.efg \ contrib/games/2x2x2.efg \ contrib/games/4cards.efg \ contrib/games/artist1.efg \ contrib/games/artist2.efg \ contrib/games/badgame1.efg \ contrib/games/badgame2.efg \ contrib/games/bayes1a.efg \ contrib/games/bayes2a.efg \ contrib/games/bcp2.efg \ contrib/games/bcp3.efg \ contrib/games/bcp4.efg \ contrib/games/bhg1.efg \ contrib/games/bhg2.efg \ contrib/games/bhg3.efg \ contrib/games/bhg4.efg \ contrib/games/bhg5.efg \ contrib/games/caro2.efg \ contrib/games/cent2.efg \ contrib/games/cent3.efg \ contrib/games/cent4.efg \ contrib/games/cent6.efg \ contrib/games/centcs10.efg \ contrib/games/centcs6.efg \ contrib/games/condjury.efg \ contrib/games/coord2.efg \ contrib/games/coord2ts.efg \ contrib/games/coord3.efg \ contrib/games/coord4.efg \ contrib/games/cross.efg \ contrib/games/cs.efg \ contrib/games/e01.efg \ contrib/games/e02.efg \ contrib/games/e03.efg \ contrib/games/e04.efg \ contrib/games/e05.efg \ contrib/games/e06.efg \ contrib/games/e07.efg \ contrib/games/e08.efg \ contrib/games/e09.efg \ contrib/games/e10a.efg \ contrib/games/e10.efg \ contrib/games/e13.efg \ contrib/games/e16.efg \ contrib/games/e17.efg \ contrib/games/e18.efg \ contrib/games/g1.efg \ contrib/games/g2.efg \ contrib/games/g3.efg \ contrib/games/holdout7.efg \ contrib/games/holdout.efg \ contrib/games/hs1.efg \ contrib/games/jury_mr.efg \ contrib/games/jury_un.efg \ contrib/games/km1.efg \ contrib/games/km2.efg \ contrib/games/km3.efg \ contrib/games/km6.efg \ contrib/games/montyhal.efg \ contrib/games/my_2-1.efg \ contrib/games/my_2-4.efg \ contrib/games/my_2-8.efg \ contrib/games/my_3-3a.efg \ contrib/games/my_3-3b.efg \ contrib/games/my_3-3c.efg \ contrib/games/my_3-3d.efg \ contrib/games/my_3-3e.efg \ contrib/games/my_3-4.efg \ contrib/games/myerson.efg \ contrib/games/nim7.efg \ contrib/games/nim.efg \ contrib/games/palf2.efg \ contrib/games/palf3.efg \ contrib/games/palf.efg \ contrib/games/poker2.efg \ contrib/games/poker.efg \ contrib/games/pvw2.efg \ contrib/games/pvw.efg \ contrib/games/sh3.efg \ contrib/games/sww1.efg \ contrib/games/sww2.efg \ contrib/games/sww3.efg \ contrib/games/tim.efg \ contrib/games/ttt.efg \ contrib/games/vd.efg \ contrib/games/w_ex1.efg \ contrib/games/w_ex2.efg \ contrib/games/wilson1.efg \ contrib/games/work1.efg \ contrib/games/work2.efg \ contrib/games/work3.efg \ contrib/games/2x2a.nfg \ contrib/games/2x2const.nfg \ contrib/games/2x2.nfg \ contrib/games/2x2x2.nfg \ contrib/games/2x2x2x2.nfg \ contrib/games/2x2x2x2x2.nfg \ contrib/games/3x3x3.nfg \ contrib/games/5x4x3.nfg \ contrib/games/8x2x2.nfg \ contrib/games/8x8.nfg \ contrib/games/cent2.nfg \ contrib/games/coord2.nfg \ contrib/games/coord333.nfg \ contrib/games/coord3.nfg \ contrib/games/coord4.nfg \ contrib/games/csg1.nfg \ contrib/games/csg2.nfg \ contrib/games/csg3.nfg \ contrib/games/csg4.nfg \ contrib/games/deg1.nfg \ contrib/games/deg2.nfg \ contrib/games/e01.nfg \ contrib/games/e02.nfg \ contrib/games/e04.nfg \ contrib/games/e07.nfg \ contrib/games/g1.nfg \ contrib/games/g2.nfg \ contrib/games/g3.nfg \ contrib/games/loopback.nfg \ contrib/games/mixdom2.nfg \ contrib/games/mixdom.nfg \ contrib/games/oneill.nfg \ contrib/games/pd.nfg \ contrib/games/perfect1.nfg \ contrib/games/perfect2.nfg \ contrib/games/perfect3.nfg \ contrib/games/poker.nfg \ contrib/games/sh3.nfg \ contrib/games/stengel.nfg \ contrib/games/sww1.nfg \ contrib/games/todd1.nfg \ contrib/games/todd2.nfg \ contrib/games/todd3.nfg \ contrib/games/vd.nfg \ contrib/games/wink3.nfg \ contrib/games/winkels.nfg \ contrib/games/yamamoto.nfg \ contrib/games/zero.nfg # lib_LTLIBRARIES = libgambit.la libgambit_la_SOURCES = \ src/libgambit/integer.cc \ src/libgambit/integer.h \ src/libgambit/rational.cc \ src/libgambit/rational.h \ src/libgambit/array.h \ src/libgambit/list.h \ src/libgambit/map.h \ src/libgambit/vector.cc \ src/libgambit/vector.h \ src/libgambit/vector.imp \ src/libgambit/pvector.cc \ src/libgambit/pvector.h \ src/libgambit/pvector.imp \ src/libgambit/dvector.cc \ src/libgambit/dvector.h \ src/libgambit/dvector.imp \ src/libgambit/recarray.h \ src/libgambit/matrix.cc \ src/libgambit/matrix.h \ src/libgambit/matrix.imp \ src/libgambit/sqmatrix.cc \ src/libgambit/sqmatrix.h \ src/libgambit/sqmatrix.imp \ src/libgambit/number.h \ src/libgambit/game.cc \ src/libgambit/game.h \ src/libgambit/behav.cc \ src/libgambit/behav.h \ src/libgambit/behav.imp \ src/libgambit/behavitr.cc \ src/libgambit/behavitr.h \ src/libgambit/behavspt.cc \ src/libgambit/behavspt.h \ src/libgambit/mixed.cc \ src/libgambit/mixed.h \ src/libgambit/mixed.imp \ src/libgambit/stratitr.cc \ src/libgambit/stratitr.h \ src/libgambit/stratspt.cc \ src/libgambit/stratspt.h \ src/libgambit/subgame.cc \ src/libgambit/subgame.h \ src/libgambit/file.cc \ src/libgambit/libgambit.h libgambitincludedir = $(includedir)/libgambit libgambitinclude_HEADERS = \ src/libgambit/integer.h \ src/libgambit/rational.h \ src/libgambit/array.h \ src/libgambit/list.h \ src/libgambit/map.h \ src/libgambit/vector.h \ src/libgambit/vector.imp \ src/libgambit/pvector.h \ src/libgambit/pvector.imp \ src/libgambit/dvector.h \ src/libgambit/dvector.imp \ src/libgambit/recarray.h \ src/libgambit/matrix.h \ src/libgambit/matrix.imp \ src/libgambit/sqmatrix.h \ src/libgambit/sqmatrix.imp \ src/libgambit/number.h \ src/libgambit/game.h \ src/libgambit/behav.h \ src/libgambit/behav.imp \ src/libgambit/behavitr.h \ src/libgambit/behavspt.h \ src/libgambit/mixed.h \ src/libgambit/mixed.imp \ src/libgambit/stratitr.h \ src/libgambit/stratspt.h \ src/libgambit/libgambit.h # libgambit_la_LDFLAGS = -no-undefined -version-info 0:0:0 bin_PROGRAMS = \ gambit-nfg2html \ gambit-nfg2tex \ gambit-enummixed if WITH_ENUMPOLY bin_PROGRAMS += gambit-enumpoly endif bin_PROGRAMS += \ gambit-enumpure \ gambit-gnm \ gambit-ipa \ gambit-lcp \ gambit-liap \ gambit-logit \ gambit-nfg-logitdyn \ gambit-lp \ gambit-simpdiv if WITH_GUI bin_PROGRAMS += gambit endif EXTRA_PROGRAMS = gambit-enumpoly gambit AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/labenski/include ${WX_CXXFLAGS} ## Command-line tools gambit_nfg2html_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/convert/nfg2html.cc gambit_nfg2tex_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/convert/nfg2tex.cc gambit_enummixed_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/enummixed/lrsmp.h \ src/tools/enummixed/lrsmp.c \ src/tools/enummixed/lrslib.h \ src/tools/enummixed/lrslib.c \ src/tools/enummixed/lrsnash.cc \ src/tools/enummixed/basis.cc \ src/tools/enummixed/basis.h \ src/tools/enummixed/bfs.cc \ src/tools/enummixed/bfs.h \ src/tools/enummixed/btableau.cc \ src/tools/enummixed/btableau.h \ src/tools/enummixed/btableau.imp \ src/tools/enummixed/lptab.cc \ src/tools/enummixed/lptab.h \ src/tools/enummixed/lptab.imp \ src/tools/enummixed/ludecomp.cc \ src/tools/enummixed/ludecomp.h \ src/tools/enummixed/ludecomp.imp \ src/tools/enummixed/tableau.h \ src/tools/enummixed/tableau.imp \ src/tools/enummixed/vertenum.h \ src/tools/enummixed/vertenum.imp \ src/tools/enummixed/clique.cc \ src/tools/enummixed/clique.h \ src/tools/enummixed/enummixed.cc # For enumpoly, sources starting in 'pel' are from Pelican; # sources from gpartltr to quiksolv were formerly in convenience lib libpoly. gambit_enumpoly_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/enumpoly/pelclhpk.cc \ src/tools/enumpoly/pelclhpk.h \ src/tools/enumpoly/pelclqhl.cc \ src/tools/enumpoly/pelclqhl.h \ src/tools/enumpoly/pelclyal.cc \ src/tools/enumpoly/pelclyal.h \ src/tools/enumpoly/pelconv.cc \ src/tools/enumpoly/pelconv.h \ src/tools/enumpoly/peleval.cc \ src/tools/enumpoly/peleval.h \ src/tools/enumpoly/pelgennd.cc \ src/tools/enumpoly/pelgennd.h \ src/tools/enumpoly/pelgmatr.cc \ src/tools/enumpoly/pelgmatr.h \ src/tools/enumpoly/pelgntyp.h \ src/tools/enumpoly/pelhomot.cc \ src/tools/enumpoly/pelhomot.h \ src/tools/enumpoly/pelpred.cc \ src/tools/enumpoly/pelpred.h \ src/tools/enumpoly/pelprgen.cc \ src/tools/enumpoly/pelprgen.h \ src/tools/enumpoly/pelproc.cc \ src/tools/enumpoly/pelproc.h \ src/tools/enumpoly/pelpscon.h \ src/tools/enumpoly/pelpsys.cc \ src/tools/enumpoly/pelpsys.h \ src/tools/enumpoly/pelqhull.cc \ src/tools/enumpoly/pelqhull.h \ src/tools/enumpoly/pelsymbl.cc \ src/tools/enumpoly/pelsymbl.h \ src/tools/enumpoly/pelutils.cc \ src/tools/enumpoly/pelutils.h \ src/tools/enumpoly/gpartltr.cc \ src/tools/enumpoly/gpartltr.h \ src/tools/enumpoly/gpartltr.imp \ src/tools/enumpoly/gpoly.cc \ src/tools/enumpoly/gpoly.h \ src/tools/enumpoly/gpoly.imp \ src/tools/enumpoly/gpolyctr.h \ src/tools/enumpoly/gpolylst.cc \ src/tools/enumpoly/gpolylst.h \ src/tools/enumpoly/gpolylst.imp \ src/tools/enumpoly/gsolver.cc \ src/tools/enumpoly/gsolver.h \ src/tools/enumpoly/gsolver.imp \ src/tools/enumpoly/ideal.cc \ src/tools/enumpoly/ideal.h \ src/tools/enumpoly/ideal.imp \ src/tools/enumpoly/ineqsolv.cc \ src/tools/enumpoly/ineqsolv.h \ src/tools/enumpoly/ineqsolv.imp \ src/tools/enumpoly/interval.cc \ src/tools/enumpoly/interval.h \ src/tools/enumpoly/interval.imp \ src/tools/enumpoly/monomial.cc \ src/tools/enumpoly/monomial.h \ src/tools/enumpoly/monomial.imp \ src/tools/enumpoly/pelclass.cc \ src/tools/enumpoly/pelclass.h \ src/tools/enumpoly/poly.cc \ src/tools/enumpoly/poly.h \ src/tools/enumpoly/poly.imp \ src/tools/enumpoly/prepoly.cc \ src/tools/enumpoly/prepoly.h \ src/tools/enumpoly/quiksolv.cc \ src/tools/enumpoly/quiksolv.h \ src/tools/enumpoly/quiksolv.imp \ src/tools/enumpoly/rectangl.cc \ src/tools/enumpoly/rectangl.h \ src/tools/enumpoly/rectangl.imp \ src/tools/enumpoly/behavextend.cc \ src/tools/enumpoly/behavextend.h \ src/tools/enumpoly/complex.cc \ src/tools/enumpoly/complex.h \ src/tools/enumpoly/gtree.h \ src/tools/enumpoly/gtree.imp \ src/tools/enumpoly/linrcomb.cc \ src/tools/enumpoly/linrcomb.h \ src/tools/enumpoly/linrcomb.imp \ src/tools/enumpoly/efgensup.cc \ src/tools/enumpoly/efgensup.h \ src/tools/enumpoly/gnarray.h \ src/tools/enumpoly/gnarray.imp \ src/tools/enumpoly/sfg.cc \ src/tools/enumpoly/sfg.h \ src/tools/enumpoly/sfstrat.cc \ src/tools/enumpoly/sfstrat.h \ src/tools/enumpoly/nfgensup.cc \ src/tools/enumpoly/nfgensup.h \ src/tools/enumpoly/odometer.cc \ src/tools/enumpoly/odometer.h \ src/tools/enumpoly/nfgcpoly.cc \ src/tools/enumpoly/nfgcpoly.h \ src/tools/enumpoly/nfghs.cc \ src/tools/enumpoly/nfghs.h \ src/tools/enumpoly/efgpoly.cc \ src/tools/enumpoly/nfgpoly.cc \ src/tools/enumpoly/enumpoly.cc gambit_enumpure_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/enumpure/enumpure.cc gambit_gnm_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/gt/cmatrix.cc \ src/tools/gt/cmatrix.h \ src/tools/gt/gnm.cc \ src/tools/gt/gnm.h \ src/tools/gt/gnmgame.cc \ src/tools/gt/gnmgame.h \ src/tools/gt/nfgame.cc \ src/tools/gt/nfgame.h \ src/tools/gt/nfggnm.cc gambit_ipa_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/gt/cmatrix.cc \ src/tools/gt/cmatrix.h \ src/tools/gt/gnmgame.cc \ src/tools/gt/gnmgame.h \ src/tools/gt/ipa.cc \ src/tools/gt/ipa.h \ src/tools/gt/nfgame.cc \ src/tools/gt/nfgame.h \ src/tools/gt/nfgipa.cc gambit_lcp_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/lcp/basis.cc \ src/tools/lcp/basis.h \ src/tools/lcp/bfs.cc \ src/tools/lcp/bfs.h \ src/tools/lcp/btableau.cc \ src/tools/lcp/btableau.h \ src/tools/lcp/btableau.imp \ src/tools/lcp/lemketab.cc \ src/tools/lcp/lemketab.h \ src/tools/lcp/lemketab.imp \ src/tools/lcp/lhtab.cc \ src/tools/lcp/lhtab.h \ src/tools/lcp/lhtab.imp \ src/tools/lcp/ludecomp.cc \ src/tools/lcp/ludecomp.h \ src/tools/lcp/ludecomp.imp \ src/tools/lcp/tableau.cc \ src/tools/lcp/tableau.h \ src/tools/lcp/tableau.imp \ src/tools/lcp/efglcp.cc \ src/tools/lcp/nfglcp.cc \ src/tools/lcp/lcp.cc gambit_liap_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/liap/funcmin.cc \ src/tools/liap/funcmin.h \ src/tools/liap/efgliap.cc \ src/tools/liap/nfgliap.cc \ src/tools/liap/liap.cc gambit_logit_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/logit/logbehav.h \ src/tools/logit/logbehav.imp \ src/tools/logit/path.cc \ src/tools/logit/path.h \ src/tools/logit/efglogit.h \ src/tools/logit/efglogit.cc \ src/tools/logit/nfglogit.h \ src/tools/logit/nfglogit.cc \ src/tools/logit/logit.cc gambit_nfg_logitdyn_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/logit/nfgdyn.cc gambit_lp_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/lp/basis.cc \ src/tools/lp/basis.h \ src/tools/lp/bfs.cc \ src/tools/lp/bfs.h \ src/tools/lp/btableau.cc \ src/tools/lp/btableau.h \ src/tools/lp/btableau.imp \ src/tools/lp/lpsolve.cc \ src/tools/lp/lpsolve.h \ src/tools/lp/lpsolve.imp \ src/tools/lp/lptab.cc \ src/tools/lp/lptab.h \ src/tools/lp/lptab.imp \ src/tools/lp/ludecomp.cc \ src/tools/lp/ludecomp.h \ src/tools/lp/ludecomp.imp \ src/tools/lp/tableau.cc \ src/tools/lp/tableau.h \ src/tools/lp/tableau.imp \ src/tools/lp/efglp.cc \ src/tools/lp/nfglp.cc \ src/tools/lp/lp.cc gambit_simpdiv_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/simpdiv/nfgsimpdiv.cc gambit_SOURCES = \ ${libgambit_la_SOURCES} \ src/labenski/src/sheetatr.cpp \ src/labenski/src/sheet.cpp \ src/labenski/src/sheetedg.cpp \ src/labenski/src/sheetedt.cpp \ src/labenski/src/sheetren.cpp \ src/labenski/src/sheetsel.cpp \ src/labenski/src/sheetspt.cpp \ src/labenski/src/sheettbl.cpp \ src/labenski/src/block.cpp \ src/labenski/src/genergdi.cpp \ src/labenski/src/geometry.cpp \ src/labenski/src/menubtn.cpp \ src/labenski/src/optvalue.cpp \ src/labenski/src/range.cpp \ src/labenski/src/spinctld.cpp \ src/labenski/src/toggle.cpp \ src/labenski/src/fparser.cpp \ src/labenski/src/fparser.hh \ src/labenski/src/fourier.c \ src/labenski/src/lm_lsqr.cpp \ src/labenski/src/plotctrl.cpp \ src/labenski/src/plotcurv.cpp \ src/labenski/src/plotdata.cpp \ src/labenski/src/plotdraw.cpp \ src/labenski/src/plotfunc.cpp \ src/labenski/src/plotmark.cpp \ src/labenski/src/plotprnt.cpp \ src/labenski/include/wx/plotctrl/fourier.h \ src/labenski/include/wx/plotctrl/fparser.h \ src/labenski/include/wx/plotctrl/lm_lsqr.h \ src/labenski/include/wx/plotctrl/plotctrl.h \ src/labenski/include/wx/plotctrl/plotcurv.h \ src/labenski/include/wx/plotctrl/plotdata.h \ src/labenski/include/wx/plotctrl/plotdefs.h \ src/labenski/include/wx/plotctrl/plotdraw.h \ src/labenski/include/wx/plotctrl/plotfunc.h \ src/labenski/include/wx/plotctrl/plotmark.h \ src/labenski/include/wx/plotctrl/plotprnt.h \ src/labenski/include/wx/sheet/pairarr.h \ src/labenski/include/wx/sheet/sheetatr.h \ src/labenski/include/wx/sheet/sheetdef.h \ src/labenski/include/wx/sheet/sheetedg.h \ src/labenski/include/wx/sheet/sheetedt.h \ src/labenski/include/wx/sheet/sheet.h \ src/labenski/include/wx/sheet/sheetren.h \ src/labenski/include/wx/sheet/sheetsel.h \ src/labenski/include/wx/sheet/sheetspt.h \ src/labenski/include/wx/sheet/sheettbl.h \ src/labenski/include/wx/sheet/wx24defs.h \ src/labenski/include/wx/wxthings/block.h \ src/labenski/include/wx/wxthings/bmpcombo.h \ src/labenski/include/wx/wxthings/dropdown.h \ src/labenski/include/wx/wxthings/filebrws.h \ src/labenski/include/wx/wxthings/genergdi.h \ src/labenski/include/wx/wxthings/geometry.h \ src/labenski/include/wx/wxthings/medsort.h \ src/labenski/include/wx/wxthings/menubtn.h \ src/labenski/include/wx/wxthings/optvalue.h \ src/labenski/include/wx/wxthings/range.h \ src/labenski/include/wx/wxthings/spinctld.h \ src/labenski/include/wx/wxthings/thingdef.h \ src/labenski/include/wx/wxthings/toggle.h \ src/gui/analysis.cc \ src/gui/analysis.h \ src/gui/edittext.cc \ src/gui/edittext.h \ src/gui/dlabout.cc \ src/gui/dlabout.h \ src/gui/dleditmove.cc \ src/gui/dleditmove.h \ src/gui/dleditnode.cc \ src/gui/dleditnode.h \ src/gui/dlefglayout.cc \ src/gui/dlefglayout.h \ src/gui/dlefglegend.cc \ src/gui/dlefglegend.h \ src/gui/dlefglogit.cc \ src/gui/dlefglogit.h \ src/gui/dlefgreveal.cc \ src/gui/dlefgreveal.h \ src/gui/dlgameprop.cc \ src/gui/dlgameprop.h \ src/gui/dlinsertmove.cc \ src/gui/dlinsertmove.h \ src/gui/dlnash.cc \ src/gui/dlnash.h \ src/gui/dlnashmon.cc \ src/gui/dlnashmon.h \ src/gui/dlnfglogit.cc \ src/gui/efgdisplay.cc \ src/gui/efgdisplay.h \ src/gui/efglayout.cc \ src/gui/efglayout.h \ src/gui/efgpanel.cc \ src/gui/efgpanel.h \ src/gui/efgprofile.cc \ src/gui/efgprofile.h \ src/gui/gambit.cc \ src/gui/gambit.h \ src/gui/gamedoc.cc \ src/gui/gamedoc.h \ src/gui/gameframe.cc \ src/gui/gameframe.h \ src/gui/menuconst.h \ src/gui/nfgpanel.cc \ src/gui/nfgpanel.h \ src/gui/nfgprofile.cc \ src/gui/nfgprofile.h \ src/gui/nfgtable.cc \ src/gui/nfgtable.h \ src/gui/renratio.cc \ src/gui/renratio.h \ src/gui/style.cc \ src/gui/style.h \ src/gui/valnumber.cc \ src/gui/valnumber.h \ src/gui/tinyxml.cc \ src/gui/tinyxml.h \ src/gui/tinyxmlerror.cc \ src/gui/tinyxmlparser.cc \ src/gui/dcsvg.cc \ src/gui/dcsvg.h gambit_LDADD = \ $(RC_OBJECT_PATH) \ $(WX_LIBS) osx-bundle: make all -rm -rf Gambit.app -mkdir Gambit.app -mkdir Gambit.app/Contents -mkdir Gambit.app/Contents/MacOS -mkdir Gambit.app/Contents/Resources cp contrib/mac/Info.plist Gambit.app/Contents echo -n 'APPL????' > Gambit.app/Contents/PkgInfo cp gambit Gambit.app/Contents/MacOS/gambit gambit-0.2010.09.01/Makefile.in0000644000076500007650000031165711441456741012531 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = gambit-nfg2html$(EXEEXT) gambit-nfg2tex$(EXEEXT) \ gambit-enummixed$(EXEEXT) $(am__EXEEXT_1) \ gambit-enumpure$(EXEEXT) gambit-gnm$(EXEEXT) \ gambit-ipa$(EXEEXT) gambit-lcp$(EXEEXT) gambit-liap$(EXEEXT) \ gambit-logit$(EXEEXT) gambit-nfg-logitdyn$(EXEEXT) \ gambit-lp$(EXEEXT) gambit-simpdiv$(EXEEXT) $(am__EXEEXT_2) @WITH_ENUMPOLY_TRUE@am__append_1 = gambit-enumpoly @WITH_GUI_TRUE@am__append_2 = gambit EXTRA_PROGRAMS = gambit-enumpoly$(EXEEXT) gambit$(EXEEXT) DIST_COMMON = README $(am__configure_deps) $(libgambitinclude_HEADERS) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ compile config.guess config.sub depcomp install-sh ltmain.sh \ missing mkinstalldirs subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno configure.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = @WITH_ENUMPOLY_TRUE@am__EXEEXT_1 = gambit-enumpoly$(EXEEXT) @WITH_GUI_TRUE@am__EXEEXT_2 = gambit$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libgambitincludedir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am__dirstamp = $(am__leading_dot)dirstamp am__objects_1 = src/libgambit/integer.$(OBJEXT) \ src/libgambit/rational.$(OBJEXT) \ src/libgambit/vector.$(OBJEXT) src/libgambit/pvector.$(OBJEXT) \ src/libgambit/dvector.$(OBJEXT) src/libgambit/matrix.$(OBJEXT) \ src/libgambit/sqmatrix.$(OBJEXT) src/libgambit/game.$(OBJEXT) \ src/libgambit/behav.$(OBJEXT) src/libgambit/behavitr.$(OBJEXT) \ src/libgambit/behavspt.$(OBJEXT) src/libgambit/mixed.$(OBJEXT) \ src/libgambit/stratitr.$(OBJEXT) \ src/libgambit/stratspt.$(OBJEXT) \ src/libgambit/subgame.$(OBJEXT) src/libgambit/file.$(OBJEXT) am_gambit_OBJECTS = $(am__objects_1) \ src/labenski/src/sheetatr.$(OBJEXT) \ src/labenski/src/sheet.$(OBJEXT) \ src/labenski/src/sheetedg.$(OBJEXT) \ src/labenski/src/sheetedt.$(OBJEXT) \ src/labenski/src/sheetren.$(OBJEXT) \ src/labenski/src/sheetsel.$(OBJEXT) \ src/labenski/src/sheetspt.$(OBJEXT) \ src/labenski/src/sheettbl.$(OBJEXT) \ src/labenski/src/block.$(OBJEXT) \ src/labenski/src/genergdi.$(OBJEXT) \ src/labenski/src/geometry.$(OBJEXT) \ src/labenski/src/menubtn.$(OBJEXT) \ src/labenski/src/optvalue.$(OBJEXT) \ src/labenski/src/range.$(OBJEXT) \ src/labenski/src/spinctld.$(OBJEXT) \ src/labenski/src/toggle.$(OBJEXT) \ src/labenski/src/fparser.$(OBJEXT) \ src/labenski/src/fourier.$(OBJEXT) \ src/labenski/src/lm_lsqr.$(OBJEXT) \ src/labenski/src/plotctrl.$(OBJEXT) \ src/labenski/src/plotcurv.$(OBJEXT) \ src/labenski/src/plotdata.$(OBJEXT) \ src/labenski/src/plotdraw.$(OBJEXT) \ src/labenski/src/plotfunc.$(OBJEXT) \ src/labenski/src/plotmark.$(OBJEXT) \ src/labenski/src/plotprnt.$(OBJEXT) src/gui/analysis.$(OBJEXT) \ src/gui/edittext.$(OBJEXT) src/gui/dlabout.$(OBJEXT) \ src/gui/dleditmove.$(OBJEXT) src/gui/dleditnode.$(OBJEXT) \ src/gui/dlefglayout.$(OBJEXT) src/gui/dlefglegend.$(OBJEXT) \ src/gui/dlefglogit.$(OBJEXT) src/gui/dlefgreveal.$(OBJEXT) \ src/gui/dlgameprop.$(OBJEXT) src/gui/dlinsertmove.$(OBJEXT) \ src/gui/dlnash.$(OBJEXT) src/gui/dlnashmon.$(OBJEXT) \ src/gui/dlnfglogit.$(OBJEXT) src/gui/efgdisplay.$(OBJEXT) \ src/gui/efglayout.$(OBJEXT) src/gui/efgpanel.$(OBJEXT) \ src/gui/efgprofile.$(OBJEXT) src/gui/gambit.$(OBJEXT) \ src/gui/gamedoc.$(OBJEXT) src/gui/gameframe.$(OBJEXT) \ src/gui/nfgpanel.$(OBJEXT) src/gui/nfgprofile.$(OBJEXT) \ src/gui/nfgtable.$(OBJEXT) src/gui/renratio.$(OBJEXT) \ src/gui/style.$(OBJEXT) src/gui/valnumber.$(OBJEXT) \ src/gui/tinyxml.$(OBJEXT) src/gui/tinyxmlerror.$(OBJEXT) \ src/gui/tinyxmlparser.$(OBJEXT) src/gui/dcsvg.$(OBJEXT) gambit_OBJECTS = $(am_gambit_OBJECTS) am__DEPENDENCIES_1 = gambit_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_gambit_enummixed_OBJECTS = $(am__objects_1) \ src/tools/enummixed/lrsmp.$(OBJEXT) \ src/tools/enummixed/lrslib.$(OBJEXT) \ src/tools/enummixed/lrsnash.$(OBJEXT) \ src/tools/enummixed/basis.$(OBJEXT) \ src/tools/enummixed/bfs.$(OBJEXT) \ src/tools/enummixed/btableau.$(OBJEXT) \ src/tools/enummixed/lptab.$(OBJEXT) \ src/tools/enummixed/ludecomp.$(OBJEXT) \ src/tools/enummixed/clique.$(OBJEXT) \ src/tools/enummixed/enummixed.$(OBJEXT) gambit_enummixed_OBJECTS = $(am_gambit_enummixed_OBJECTS) gambit_enummixed_LDADD = $(LDADD) am_gambit_enumpoly_OBJECTS = $(am__objects_1) \ src/tools/enumpoly/pelclhpk.$(OBJEXT) \ src/tools/enumpoly/pelclqhl.$(OBJEXT) \ src/tools/enumpoly/pelclyal.$(OBJEXT) \ src/tools/enumpoly/pelconv.$(OBJEXT) \ src/tools/enumpoly/peleval.$(OBJEXT) \ src/tools/enumpoly/pelgennd.$(OBJEXT) \ src/tools/enumpoly/pelgmatr.$(OBJEXT) \ src/tools/enumpoly/pelhomot.$(OBJEXT) \ src/tools/enumpoly/pelpred.$(OBJEXT) \ src/tools/enumpoly/pelprgen.$(OBJEXT) \ src/tools/enumpoly/pelproc.$(OBJEXT) \ src/tools/enumpoly/pelpsys.$(OBJEXT) \ src/tools/enumpoly/pelqhull.$(OBJEXT) \ src/tools/enumpoly/pelsymbl.$(OBJEXT) \ src/tools/enumpoly/pelutils.$(OBJEXT) \ src/tools/enumpoly/gpartltr.$(OBJEXT) \ src/tools/enumpoly/gpoly.$(OBJEXT) \ src/tools/enumpoly/gpolylst.$(OBJEXT) \ src/tools/enumpoly/gsolver.$(OBJEXT) \ src/tools/enumpoly/ideal.$(OBJEXT) \ src/tools/enumpoly/ineqsolv.$(OBJEXT) \ src/tools/enumpoly/interval.$(OBJEXT) \ src/tools/enumpoly/monomial.$(OBJEXT) \ src/tools/enumpoly/pelclass.$(OBJEXT) \ src/tools/enumpoly/poly.$(OBJEXT) \ src/tools/enumpoly/prepoly.$(OBJEXT) \ src/tools/enumpoly/quiksolv.$(OBJEXT) \ src/tools/enumpoly/rectangl.$(OBJEXT) \ src/tools/enumpoly/behavextend.$(OBJEXT) \ src/tools/enumpoly/complex.$(OBJEXT) \ src/tools/enumpoly/linrcomb.$(OBJEXT) \ src/tools/enumpoly/efgensup.$(OBJEXT) \ src/tools/enumpoly/sfg.$(OBJEXT) \ src/tools/enumpoly/sfstrat.$(OBJEXT) \ src/tools/enumpoly/nfgensup.$(OBJEXT) \ src/tools/enumpoly/odometer.$(OBJEXT) \ src/tools/enumpoly/nfgcpoly.$(OBJEXT) \ src/tools/enumpoly/nfghs.$(OBJEXT) \ src/tools/enumpoly/efgpoly.$(OBJEXT) \ src/tools/enumpoly/nfgpoly.$(OBJEXT) \ src/tools/enumpoly/enumpoly.$(OBJEXT) gambit_enumpoly_OBJECTS = $(am_gambit_enumpoly_OBJECTS) gambit_enumpoly_LDADD = $(LDADD) am_gambit_enumpure_OBJECTS = $(am__objects_1) \ src/tools/enumpure/enumpure.$(OBJEXT) gambit_enumpure_OBJECTS = $(am_gambit_enumpure_OBJECTS) gambit_enumpure_LDADD = $(LDADD) am_gambit_gnm_OBJECTS = $(am__objects_1) \ src/tools/gt/cmatrix.$(OBJEXT) src/tools/gt/gnm.$(OBJEXT) \ src/tools/gt/gnmgame.$(OBJEXT) src/tools/gt/nfgame.$(OBJEXT) \ src/tools/gt/nfggnm.$(OBJEXT) gambit_gnm_OBJECTS = $(am_gambit_gnm_OBJECTS) gambit_gnm_LDADD = $(LDADD) am_gambit_ipa_OBJECTS = $(am__objects_1) \ src/tools/gt/cmatrix.$(OBJEXT) src/tools/gt/gnmgame.$(OBJEXT) \ src/tools/gt/ipa.$(OBJEXT) src/tools/gt/nfgame.$(OBJEXT) \ src/tools/gt/nfgipa.$(OBJEXT) gambit_ipa_OBJECTS = $(am_gambit_ipa_OBJECTS) gambit_ipa_LDADD = $(LDADD) am_gambit_lcp_OBJECTS = $(am__objects_1) src/tools/lcp/basis.$(OBJEXT) \ src/tools/lcp/bfs.$(OBJEXT) src/tools/lcp/btableau.$(OBJEXT) \ src/tools/lcp/lemketab.$(OBJEXT) src/tools/lcp/lhtab.$(OBJEXT) \ src/tools/lcp/ludecomp.$(OBJEXT) \ src/tools/lcp/tableau.$(OBJEXT) src/tools/lcp/efglcp.$(OBJEXT) \ src/tools/lcp/nfglcp.$(OBJEXT) src/tools/lcp/lcp.$(OBJEXT) gambit_lcp_OBJECTS = $(am_gambit_lcp_OBJECTS) gambit_lcp_LDADD = $(LDADD) am_gambit_liap_OBJECTS = $(am__objects_1) \ src/tools/liap/funcmin.$(OBJEXT) \ src/tools/liap/efgliap.$(OBJEXT) \ src/tools/liap/nfgliap.$(OBJEXT) src/tools/liap/liap.$(OBJEXT) gambit_liap_OBJECTS = $(am_gambit_liap_OBJECTS) gambit_liap_LDADD = $(LDADD) am_gambit_logit_OBJECTS = $(am__objects_1) \ src/tools/logit/path.$(OBJEXT) \ src/tools/logit/efglogit.$(OBJEXT) \ src/tools/logit/nfglogit.$(OBJEXT) \ src/tools/logit/logit.$(OBJEXT) gambit_logit_OBJECTS = $(am_gambit_logit_OBJECTS) gambit_logit_LDADD = $(LDADD) am_gambit_lp_OBJECTS = $(am__objects_1) src/tools/lp/basis.$(OBJEXT) \ src/tools/lp/bfs.$(OBJEXT) src/tools/lp/btableau.$(OBJEXT) \ src/tools/lp/lpsolve.$(OBJEXT) src/tools/lp/lptab.$(OBJEXT) \ src/tools/lp/ludecomp.$(OBJEXT) src/tools/lp/tableau.$(OBJEXT) \ src/tools/lp/efglp.$(OBJEXT) src/tools/lp/nfglp.$(OBJEXT) \ src/tools/lp/lp.$(OBJEXT) gambit_lp_OBJECTS = $(am_gambit_lp_OBJECTS) gambit_lp_LDADD = $(LDADD) am_gambit_nfg_logitdyn_OBJECTS = $(am__objects_1) \ src/tools/logit/nfgdyn.$(OBJEXT) gambit_nfg_logitdyn_OBJECTS = $(am_gambit_nfg_logitdyn_OBJECTS) gambit_nfg_logitdyn_LDADD = $(LDADD) am_gambit_nfg2html_OBJECTS = $(am__objects_1) \ src/tools/convert/nfg2html.$(OBJEXT) gambit_nfg2html_OBJECTS = $(am_gambit_nfg2html_OBJECTS) gambit_nfg2html_LDADD = $(LDADD) am_gambit_nfg2tex_OBJECTS = $(am__objects_1) \ src/tools/convert/nfg2tex.$(OBJEXT) gambit_nfg2tex_OBJECTS = $(am_gambit_nfg2tex_OBJECTS) gambit_nfg2tex_LDADD = $(LDADD) am_gambit_simpdiv_OBJECTS = $(am__objects_1) \ src/tools/simpdiv/nfgsimpdiv.$(OBJEXT) gambit_simpdiv_OBJECTS = $(am_gambit_simpdiv_OBJECTS) gambit_simpdiv_LDADD = $(LDADD) DEFAULT_INCLUDES = -I. -I$(srcdir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(gambit_SOURCES) $(gambit_enummixed_SOURCES) \ $(gambit_enumpoly_SOURCES) $(gambit_enumpure_SOURCES) \ $(gambit_gnm_SOURCES) $(gambit_ipa_SOURCES) \ $(gambit_lcp_SOURCES) $(gambit_liap_SOURCES) \ $(gambit_logit_SOURCES) $(gambit_lp_SOURCES) \ $(gambit_nfg_logitdyn_SOURCES) $(gambit_nfg2html_SOURCES) \ $(gambit_nfg2tex_SOURCES) $(gambit_simpdiv_SOURCES) DIST_SOURCES = $(gambit_SOURCES) $(gambit_enummixed_SOURCES) \ $(gambit_enumpoly_SOURCES) $(gambit_enumpure_SOURCES) \ $(gambit_gnm_SOURCES) $(gambit_ipa_SOURCES) \ $(gambit_lcp_SOURCES) $(gambit_liap_SOURCES) \ $(gambit_logit_SOURCES) $(gambit_lp_SOURCES) \ $(gambit_nfg_logitdyn_SOURCES) $(gambit_nfg2html_SOURCES) \ $(gambit_nfg2tex_SOURCES) $(gambit_simpdiv_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ install-recursive installcheck-recursive installdirs-recursive \ pdf-recursive ps-recursive uninstall-info-recursive \ uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; libgambitincludeHEADERS_INSTALL = $(INSTALL_HEADER) HEADERS = $(libgambitinclude_HEADERS) ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENUMPOLY_PROGS = @ENUMPOLY_PROGS@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ GREP = @GREP@ GUI_PROGS = @GUI_PROGS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ RC_OBJECT = @RC_OBJECT@ RC_OBJECT_PATH = @RC_OBJECT_PATH@ REZFLAGS = @REZFLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ WITH_ENUMPOLY_FALSE = @WITH_ENUMPOLY_FALSE@ WITH_ENUMPOLY_TRUE = @WITH_ENUMPOLY_TRUE@ WITH_GUI_FALSE = @WITH_GUI_FALSE@ WITH_GUI_TRUE = @WITH_GUI_TRUE@ WX_CFLAGS = @WX_CFLAGS@ WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ WX_CONFIG_PATH = @WX_CONFIG_PATH@ WX_CPPFLAGS = @WX_CPPFLAGS@ WX_CXXFLAGS = @WX_CXXFLAGS@ WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ WX_LIBS = @WX_LIBS@ WX_LIBS_STATIC = @WX_LIBS_STATIC@ WX_RESCOMP = @WX_RESCOMP@ WX_VERSION = @WX_VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = contrib ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = \ gambit.spec \ gambit.desktop \ contrib/mac/Info.plist \ src/labenski/README.txt \ src/labenski/art/grab.xpm \ src/labenski/art/hand.xpm \ src/labenski/art/ledgreen.xpm \ src/labenski/art/ledgrey.xpm \ src/labenski/doc/README-plotctrl.txt \ src/labenski/doc/README-sheet.txt \ src/labenski/doc/README-wxthings.txt \ src/labenski/include/wx/wxthings/bitmaps/copy.xpm \ src/labenski/include/wx/wxthings/bitmaps/cut.xpm \ src/labenski/include/wx/wxthings/bitmaps/findnext.xpm \ src/labenski/include/wx/wxthings/bitmaps/find.xpm \ src/labenski/include/wx/wxthings/bitmaps/grab.xpm \ src/labenski/include/wx/wxthings/bitmaps/hand.xpm \ src/labenski/include/wx/wxthings/bitmaps/help.xpm \ src/labenski/include/wx/wxthings/bitmaps/new.xpm \ src/labenski/include/wx/wxthings/bitmaps/open.xpm \ src/labenski/include/wx/wxthings/bitmaps/paste.xpm \ src/labenski/include/wx/wxthings/bitmaps/preview.xpm \ src/labenski/include/wx/wxthings/bitmaps/print.xpm \ src/labenski/include/wx/wxthings/bitmaps/question.xpm \ src/labenski/include/wx/wxthings/bitmaps/redo.xpm \ src/labenski/include/wx/wxthings/bitmaps/replace.xpm \ src/labenski/include/wx/wxthings/bitmaps/saveall.xpm \ src/labenski/include/wx/wxthings/bitmaps/saveas.xpm \ src/labenski/include/wx/wxthings/bitmaps/spell.xpm \ src/labenski/include/wx/wxthings/bitmaps/undo.xpm \ src/gui/bitmaps/about.xpm \ src/gui/bitmaps/adddecimal.xpm \ src/gui/bitmaps/calc.xpm \ src/gui/bitmaps/close.xpm \ src/gui/bitmaps/color.xpm \ src/gui/bitmaps/datasrc.xpm \ src/gui/bitmaps/deldecimal.xpm \ src/gui/bitmaps/dice.xpm \ src/gui/bitmaps/efg.ico \ src/gui/bitmaps/exit.xpm \ src/gui/bitmaps/font.xpm \ src/gui/bitmaps/gambitbig.xpm \ src/gui/bitmaps/gambit.bmp \ src/gui/bitmaps/gambit.ico \ src/gui/bitmaps/gambit.xpm \ src/gui/bitmaps/label.xpm \ src/gui/bitmaps/layout.xpm \ src/gui/bitmaps/move.xpm \ src/gui/bitmaps/newcol.xpm \ src/gui/bitmaps/newplayer.xpm \ src/gui/bitmaps/newrow.xpm \ src/gui/bitmaps/newtable.xpm \ src/gui/bitmaps/newtree.xpm \ src/gui/bitmaps/new.xpm \ src/gui/bitmaps/next.xpm \ src/gui/bitmaps/nfg.ico \ src/gui/bitmaps/open.xpm \ src/gui/bitmaps/person.xpm \ src/gui/bitmaps/preview.xpm \ src/gui/bitmaps/prev.xpm \ src/gui/bitmaps/print.xpm \ src/gui/bitmaps/profiles.xpm \ src/gui/bitmaps/redo.xpm \ src/gui/bitmaps/saveas.xpm \ src/gui/bitmaps/savedata.xpm \ src/gui/bitmaps/save.xpm \ src/gui/bitmaps/stop.xpm \ src/gui/bitmaps/table.xpm \ src/gui/bitmaps/tobegin.xpm \ src/gui/bitmaps/toend.xpm \ src/gui/bitmaps/tree.xpm \ src/gui/bitmaps/undo.xpm \ src/gui/bitmaps/zoomfit.xpm \ src/gui/bitmaps/zoomin.xpm \ src/gui/bitmaps/zoomout.xpm \ src/gui/bitmaps/zoom1.xpm \ src/gui/bitmaps/gambitrc.rc \ contrib/games/2s2x2x2.efg \ contrib/games/2smp.efg \ contrib/games/2x2x2.efg \ contrib/games/4cards.efg \ contrib/games/artist1.efg \ contrib/games/artist2.efg \ contrib/games/badgame1.efg \ contrib/games/badgame2.efg \ contrib/games/bayes1a.efg \ contrib/games/bayes2a.efg \ contrib/games/bcp2.efg \ contrib/games/bcp3.efg \ contrib/games/bcp4.efg \ contrib/games/bhg1.efg \ contrib/games/bhg2.efg \ contrib/games/bhg3.efg \ contrib/games/bhg4.efg \ contrib/games/bhg5.efg \ contrib/games/caro2.efg \ contrib/games/cent2.efg \ contrib/games/cent3.efg \ contrib/games/cent4.efg \ contrib/games/cent6.efg \ contrib/games/centcs10.efg \ contrib/games/centcs6.efg \ contrib/games/condjury.efg \ contrib/games/coord2.efg \ contrib/games/coord2ts.efg \ contrib/games/coord3.efg \ contrib/games/coord4.efg \ contrib/games/cross.efg \ contrib/games/cs.efg \ contrib/games/e01.efg \ contrib/games/e02.efg \ contrib/games/e03.efg \ contrib/games/e04.efg \ contrib/games/e05.efg \ contrib/games/e06.efg \ contrib/games/e07.efg \ contrib/games/e08.efg \ contrib/games/e09.efg \ contrib/games/e10a.efg \ contrib/games/e10.efg \ contrib/games/e13.efg \ contrib/games/e16.efg \ contrib/games/e17.efg \ contrib/games/e18.efg \ contrib/games/g1.efg \ contrib/games/g2.efg \ contrib/games/g3.efg \ contrib/games/holdout7.efg \ contrib/games/holdout.efg \ contrib/games/hs1.efg \ contrib/games/jury_mr.efg \ contrib/games/jury_un.efg \ contrib/games/km1.efg \ contrib/games/km2.efg \ contrib/games/km3.efg \ contrib/games/km6.efg \ contrib/games/montyhal.efg \ contrib/games/my_2-1.efg \ contrib/games/my_2-4.efg \ contrib/games/my_2-8.efg \ contrib/games/my_3-3a.efg \ contrib/games/my_3-3b.efg \ contrib/games/my_3-3c.efg \ contrib/games/my_3-3d.efg \ contrib/games/my_3-3e.efg \ contrib/games/my_3-4.efg \ contrib/games/myerson.efg \ contrib/games/nim7.efg \ contrib/games/nim.efg \ contrib/games/palf2.efg \ contrib/games/palf3.efg \ contrib/games/palf.efg \ contrib/games/poker2.efg \ contrib/games/poker.efg \ contrib/games/pvw2.efg \ contrib/games/pvw.efg \ contrib/games/sh3.efg \ contrib/games/sww1.efg \ contrib/games/sww2.efg \ contrib/games/sww3.efg \ contrib/games/tim.efg \ contrib/games/ttt.efg \ contrib/games/vd.efg \ contrib/games/w_ex1.efg \ contrib/games/w_ex2.efg \ contrib/games/wilson1.efg \ contrib/games/work1.efg \ contrib/games/work2.efg \ contrib/games/work3.efg \ contrib/games/2x2a.nfg \ contrib/games/2x2const.nfg \ contrib/games/2x2.nfg \ contrib/games/2x2x2.nfg \ contrib/games/2x2x2x2.nfg \ contrib/games/2x2x2x2x2.nfg \ contrib/games/3x3x3.nfg \ contrib/games/5x4x3.nfg \ contrib/games/8x2x2.nfg \ contrib/games/8x8.nfg \ contrib/games/cent2.nfg \ contrib/games/coord2.nfg \ contrib/games/coord333.nfg \ contrib/games/coord3.nfg \ contrib/games/coord4.nfg \ contrib/games/csg1.nfg \ contrib/games/csg2.nfg \ contrib/games/csg3.nfg \ contrib/games/csg4.nfg \ contrib/games/deg1.nfg \ contrib/games/deg2.nfg \ contrib/games/e01.nfg \ contrib/games/e02.nfg \ contrib/games/e04.nfg \ contrib/games/e07.nfg \ contrib/games/g1.nfg \ contrib/games/g2.nfg \ contrib/games/g3.nfg \ contrib/games/loopback.nfg \ contrib/games/mixdom2.nfg \ contrib/games/mixdom.nfg \ contrib/games/oneill.nfg \ contrib/games/pd.nfg \ contrib/games/perfect1.nfg \ contrib/games/perfect2.nfg \ contrib/games/perfect3.nfg \ contrib/games/poker.nfg \ contrib/games/sh3.nfg \ contrib/games/stengel.nfg \ contrib/games/sww1.nfg \ contrib/games/todd1.nfg \ contrib/games/todd2.nfg \ contrib/games/todd3.nfg \ contrib/games/vd.nfg \ contrib/games/wink3.nfg \ contrib/games/winkels.nfg \ contrib/games/yamamoto.nfg \ contrib/games/zero.nfg # lib_LTLIBRARIES = libgambit.la libgambit_la_SOURCES = \ src/libgambit/integer.cc \ src/libgambit/integer.h \ src/libgambit/rational.cc \ src/libgambit/rational.h \ src/libgambit/array.h \ src/libgambit/list.h \ src/libgambit/map.h \ src/libgambit/vector.cc \ src/libgambit/vector.h \ src/libgambit/vector.imp \ src/libgambit/pvector.cc \ src/libgambit/pvector.h \ src/libgambit/pvector.imp \ src/libgambit/dvector.cc \ src/libgambit/dvector.h \ src/libgambit/dvector.imp \ src/libgambit/recarray.h \ src/libgambit/matrix.cc \ src/libgambit/matrix.h \ src/libgambit/matrix.imp \ src/libgambit/sqmatrix.cc \ src/libgambit/sqmatrix.h \ src/libgambit/sqmatrix.imp \ src/libgambit/number.h \ src/libgambit/game.cc \ src/libgambit/game.h \ src/libgambit/behav.cc \ src/libgambit/behav.h \ src/libgambit/behav.imp \ src/libgambit/behavitr.cc \ src/libgambit/behavitr.h \ src/libgambit/behavspt.cc \ src/libgambit/behavspt.h \ src/libgambit/mixed.cc \ src/libgambit/mixed.h \ src/libgambit/mixed.imp \ src/libgambit/stratitr.cc \ src/libgambit/stratitr.h \ src/libgambit/stratspt.cc \ src/libgambit/stratspt.h \ src/libgambit/subgame.cc \ src/libgambit/subgame.h \ src/libgambit/file.cc \ src/libgambit/libgambit.h libgambitincludedir = $(includedir)/libgambit libgambitinclude_HEADERS = \ src/libgambit/integer.h \ src/libgambit/rational.h \ src/libgambit/array.h \ src/libgambit/list.h \ src/libgambit/map.h \ src/libgambit/vector.h \ src/libgambit/vector.imp \ src/libgambit/pvector.h \ src/libgambit/pvector.imp \ src/libgambit/dvector.h \ src/libgambit/dvector.imp \ src/libgambit/recarray.h \ src/libgambit/matrix.h \ src/libgambit/matrix.imp \ src/libgambit/sqmatrix.h \ src/libgambit/sqmatrix.imp \ src/libgambit/number.h \ src/libgambit/game.h \ src/libgambit/behav.h \ src/libgambit/behav.imp \ src/libgambit/behavitr.h \ src/libgambit/behavspt.h \ src/libgambit/mixed.h \ src/libgambit/mixed.imp \ src/libgambit/stratitr.h \ src/libgambit/stratspt.h \ src/libgambit/libgambit.h AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/labenski/include ${WX_CXXFLAGS} gambit_nfg2html_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/convert/nfg2html.cc gambit_nfg2tex_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/convert/nfg2tex.cc gambit_enummixed_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/enummixed/lrsmp.h \ src/tools/enummixed/lrsmp.c \ src/tools/enummixed/lrslib.h \ src/tools/enummixed/lrslib.c \ src/tools/enummixed/lrsnash.cc \ src/tools/enummixed/basis.cc \ src/tools/enummixed/basis.h \ src/tools/enummixed/bfs.cc \ src/tools/enummixed/bfs.h \ src/tools/enummixed/btableau.cc \ src/tools/enummixed/btableau.h \ src/tools/enummixed/btableau.imp \ src/tools/enummixed/lptab.cc \ src/tools/enummixed/lptab.h \ src/tools/enummixed/lptab.imp \ src/tools/enummixed/ludecomp.cc \ src/tools/enummixed/ludecomp.h \ src/tools/enummixed/ludecomp.imp \ src/tools/enummixed/tableau.h \ src/tools/enummixed/tableau.imp \ src/tools/enummixed/vertenum.h \ src/tools/enummixed/vertenum.imp \ src/tools/enummixed/clique.cc \ src/tools/enummixed/clique.h \ src/tools/enummixed/enummixed.cc # For enumpoly, sources starting in 'pel' are from Pelican; # sources from gpartltr to quiksolv were formerly in convenience lib libpoly. gambit_enumpoly_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/enumpoly/pelclhpk.cc \ src/tools/enumpoly/pelclhpk.h \ src/tools/enumpoly/pelclqhl.cc \ src/tools/enumpoly/pelclqhl.h \ src/tools/enumpoly/pelclyal.cc \ src/tools/enumpoly/pelclyal.h \ src/tools/enumpoly/pelconv.cc \ src/tools/enumpoly/pelconv.h \ src/tools/enumpoly/peleval.cc \ src/tools/enumpoly/peleval.h \ src/tools/enumpoly/pelgennd.cc \ src/tools/enumpoly/pelgennd.h \ src/tools/enumpoly/pelgmatr.cc \ src/tools/enumpoly/pelgmatr.h \ src/tools/enumpoly/pelgntyp.h \ src/tools/enumpoly/pelhomot.cc \ src/tools/enumpoly/pelhomot.h \ src/tools/enumpoly/pelpred.cc \ src/tools/enumpoly/pelpred.h \ src/tools/enumpoly/pelprgen.cc \ src/tools/enumpoly/pelprgen.h \ src/tools/enumpoly/pelproc.cc \ src/tools/enumpoly/pelproc.h \ src/tools/enumpoly/pelpscon.h \ src/tools/enumpoly/pelpsys.cc \ src/tools/enumpoly/pelpsys.h \ src/tools/enumpoly/pelqhull.cc \ src/tools/enumpoly/pelqhull.h \ src/tools/enumpoly/pelsymbl.cc \ src/tools/enumpoly/pelsymbl.h \ src/tools/enumpoly/pelutils.cc \ src/tools/enumpoly/pelutils.h \ src/tools/enumpoly/gpartltr.cc \ src/tools/enumpoly/gpartltr.h \ src/tools/enumpoly/gpartltr.imp \ src/tools/enumpoly/gpoly.cc \ src/tools/enumpoly/gpoly.h \ src/tools/enumpoly/gpoly.imp \ src/tools/enumpoly/gpolyctr.h \ src/tools/enumpoly/gpolylst.cc \ src/tools/enumpoly/gpolylst.h \ src/tools/enumpoly/gpolylst.imp \ src/tools/enumpoly/gsolver.cc \ src/tools/enumpoly/gsolver.h \ src/tools/enumpoly/gsolver.imp \ src/tools/enumpoly/ideal.cc \ src/tools/enumpoly/ideal.h \ src/tools/enumpoly/ideal.imp \ src/tools/enumpoly/ineqsolv.cc \ src/tools/enumpoly/ineqsolv.h \ src/tools/enumpoly/ineqsolv.imp \ src/tools/enumpoly/interval.cc \ src/tools/enumpoly/interval.h \ src/tools/enumpoly/interval.imp \ src/tools/enumpoly/monomial.cc \ src/tools/enumpoly/monomial.h \ src/tools/enumpoly/monomial.imp \ src/tools/enumpoly/pelclass.cc \ src/tools/enumpoly/pelclass.h \ src/tools/enumpoly/poly.cc \ src/tools/enumpoly/poly.h \ src/tools/enumpoly/poly.imp \ src/tools/enumpoly/prepoly.cc \ src/tools/enumpoly/prepoly.h \ src/tools/enumpoly/quiksolv.cc \ src/tools/enumpoly/quiksolv.h \ src/tools/enumpoly/quiksolv.imp \ src/tools/enumpoly/rectangl.cc \ src/tools/enumpoly/rectangl.h \ src/tools/enumpoly/rectangl.imp \ src/tools/enumpoly/behavextend.cc \ src/tools/enumpoly/behavextend.h \ src/tools/enumpoly/complex.cc \ src/tools/enumpoly/complex.h \ src/tools/enumpoly/gtree.h \ src/tools/enumpoly/gtree.imp \ src/tools/enumpoly/linrcomb.cc \ src/tools/enumpoly/linrcomb.h \ src/tools/enumpoly/linrcomb.imp \ src/tools/enumpoly/efgensup.cc \ src/tools/enumpoly/efgensup.h \ src/tools/enumpoly/gnarray.h \ src/tools/enumpoly/gnarray.imp \ src/tools/enumpoly/sfg.cc \ src/tools/enumpoly/sfg.h \ src/tools/enumpoly/sfstrat.cc \ src/tools/enumpoly/sfstrat.h \ src/tools/enumpoly/nfgensup.cc \ src/tools/enumpoly/nfgensup.h \ src/tools/enumpoly/odometer.cc \ src/tools/enumpoly/odometer.h \ src/tools/enumpoly/nfgcpoly.cc \ src/tools/enumpoly/nfgcpoly.h \ src/tools/enumpoly/nfghs.cc \ src/tools/enumpoly/nfghs.h \ src/tools/enumpoly/efgpoly.cc \ src/tools/enumpoly/nfgpoly.cc \ src/tools/enumpoly/enumpoly.cc gambit_enumpure_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/enumpure/enumpure.cc gambit_gnm_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/gt/cmatrix.cc \ src/tools/gt/cmatrix.h \ src/tools/gt/gnm.cc \ src/tools/gt/gnm.h \ src/tools/gt/gnmgame.cc \ src/tools/gt/gnmgame.h \ src/tools/gt/nfgame.cc \ src/tools/gt/nfgame.h \ src/tools/gt/nfggnm.cc gambit_ipa_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/gt/cmatrix.cc \ src/tools/gt/cmatrix.h \ src/tools/gt/gnmgame.cc \ src/tools/gt/gnmgame.h \ src/tools/gt/ipa.cc \ src/tools/gt/ipa.h \ src/tools/gt/nfgame.cc \ src/tools/gt/nfgame.h \ src/tools/gt/nfgipa.cc gambit_lcp_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/lcp/basis.cc \ src/tools/lcp/basis.h \ src/tools/lcp/bfs.cc \ src/tools/lcp/bfs.h \ src/tools/lcp/btableau.cc \ src/tools/lcp/btableau.h \ src/tools/lcp/btableau.imp \ src/tools/lcp/lemketab.cc \ src/tools/lcp/lemketab.h \ src/tools/lcp/lemketab.imp \ src/tools/lcp/lhtab.cc \ src/tools/lcp/lhtab.h \ src/tools/lcp/lhtab.imp \ src/tools/lcp/ludecomp.cc \ src/tools/lcp/ludecomp.h \ src/tools/lcp/ludecomp.imp \ src/tools/lcp/tableau.cc \ src/tools/lcp/tableau.h \ src/tools/lcp/tableau.imp \ src/tools/lcp/efglcp.cc \ src/tools/lcp/nfglcp.cc \ src/tools/lcp/lcp.cc gambit_liap_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/liap/funcmin.cc \ src/tools/liap/funcmin.h \ src/tools/liap/efgliap.cc \ src/tools/liap/nfgliap.cc \ src/tools/liap/liap.cc gambit_logit_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/logit/logbehav.h \ src/tools/logit/logbehav.imp \ src/tools/logit/path.cc \ src/tools/logit/path.h \ src/tools/logit/efglogit.h \ src/tools/logit/efglogit.cc \ src/tools/logit/nfglogit.h \ src/tools/logit/nfglogit.cc \ src/tools/logit/logit.cc gambit_nfg_logitdyn_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/logit/nfgdyn.cc gambit_lp_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/lp/basis.cc \ src/tools/lp/basis.h \ src/tools/lp/bfs.cc \ src/tools/lp/bfs.h \ src/tools/lp/btableau.cc \ src/tools/lp/btableau.h \ src/tools/lp/btableau.imp \ src/tools/lp/lpsolve.cc \ src/tools/lp/lpsolve.h \ src/tools/lp/lpsolve.imp \ src/tools/lp/lptab.cc \ src/tools/lp/lptab.h \ src/tools/lp/lptab.imp \ src/tools/lp/ludecomp.cc \ src/tools/lp/ludecomp.h \ src/tools/lp/ludecomp.imp \ src/tools/lp/tableau.cc \ src/tools/lp/tableau.h \ src/tools/lp/tableau.imp \ src/tools/lp/efglp.cc \ src/tools/lp/nfglp.cc \ src/tools/lp/lp.cc gambit_simpdiv_SOURCES = \ ${libgambit_la_SOURCES} \ src/tools/simpdiv/nfgsimpdiv.cc gambit_SOURCES = \ ${libgambit_la_SOURCES} \ src/labenski/src/sheetatr.cpp \ src/labenski/src/sheet.cpp \ src/labenski/src/sheetedg.cpp \ src/labenski/src/sheetedt.cpp \ src/labenski/src/sheetren.cpp \ src/labenski/src/sheetsel.cpp \ src/labenski/src/sheetspt.cpp \ src/labenski/src/sheettbl.cpp \ src/labenski/src/block.cpp \ src/labenski/src/genergdi.cpp \ src/labenski/src/geometry.cpp \ src/labenski/src/menubtn.cpp \ src/labenski/src/optvalue.cpp \ src/labenski/src/range.cpp \ src/labenski/src/spinctld.cpp \ src/labenski/src/toggle.cpp \ src/labenski/src/fparser.cpp \ src/labenski/src/fparser.hh \ src/labenski/src/fourier.c \ src/labenski/src/lm_lsqr.cpp \ src/labenski/src/plotctrl.cpp \ src/labenski/src/plotcurv.cpp \ src/labenski/src/plotdata.cpp \ src/labenski/src/plotdraw.cpp \ src/labenski/src/plotfunc.cpp \ src/labenski/src/plotmark.cpp \ src/labenski/src/plotprnt.cpp \ src/labenski/include/wx/plotctrl/fourier.h \ src/labenski/include/wx/plotctrl/fparser.h \ src/labenski/include/wx/plotctrl/lm_lsqr.h \ src/labenski/include/wx/plotctrl/plotctrl.h \ src/labenski/include/wx/plotctrl/plotcurv.h \ src/labenski/include/wx/plotctrl/plotdata.h \ src/labenski/include/wx/plotctrl/plotdefs.h \ src/labenski/include/wx/plotctrl/plotdraw.h \ src/labenski/include/wx/plotctrl/plotfunc.h \ src/labenski/include/wx/plotctrl/plotmark.h \ src/labenski/include/wx/plotctrl/plotprnt.h \ src/labenski/include/wx/sheet/pairarr.h \ src/labenski/include/wx/sheet/sheetatr.h \ src/labenski/include/wx/sheet/sheetdef.h \ src/labenski/include/wx/sheet/sheetedg.h \ src/labenski/include/wx/sheet/sheetedt.h \ src/labenski/include/wx/sheet/sheet.h \ src/labenski/include/wx/sheet/sheetren.h \ src/labenski/include/wx/sheet/sheetsel.h \ src/labenski/include/wx/sheet/sheetspt.h \ src/labenski/include/wx/sheet/sheettbl.h \ src/labenski/include/wx/sheet/wx24defs.h \ src/labenski/include/wx/wxthings/block.h \ src/labenski/include/wx/wxthings/bmpcombo.h \ src/labenski/include/wx/wxthings/dropdown.h \ src/labenski/include/wx/wxthings/filebrws.h \ src/labenski/include/wx/wxthings/genergdi.h \ src/labenski/include/wx/wxthings/geometry.h \ src/labenski/include/wx/wxthings/medsort.h \ src/labenski/include/wx/wxthings/menubtn.h \ src/labenski/include/wx/wxthings/optvalue.h \ src/labenski/include/wx/wxthings/range.h \ src/labenski/include/wx/wxthings/spinctld.h \ src/labenski/include/wx/wxthings/thingdef.h \ src/labenski/include/wx/wxthings/toggle.h \ src/gui/analysis.cc \ src/gui/analysis.h \ src/gui/edittext.cc \ src/gui/edittext.h \ src/gui/dlabout.cc \ src/gui/dlabout.h \ src/gui/dleditmove.cc \ src/gui/dleditmove.h \ src/gui/dleditnode.cc \ src/gui/dleditnode.h \ src/gui/dlefglayout.cc \ src/gui/dlefglayout.h \ src/gui/dlefglegend.cc \ src/gui/dlefglegend.h \ src/gui/dlefglogit.cc \ src/gui/dlefglogit.h \ src/gui/dlefgreveal.cc \ src/gui/dlefgreveal.h \ src/gui/dlgameprop.cc \ src/gui/dlgameprop.h \ src/gui/dlinsertmove.cc \ src/gui/dlinsertmove.h \ src/gui/dlnash.cc \ src/gui/dlnash.h \ src/gui/dlnashmon.cc \ src/gui/dlnashmon.h \ src/gui/dlnfglogit.cc \ src/gui/efgdisplay.cc \ src/gui/efgdisplay.h \ src/gui/efglayout.cc \ src/gui/efglayout.h \ src/gui/efgpanel.cc \ src/gui/efgpanel.h \ src/gui/efgprofile.cc \ src/gui/efgprofile.h \ src/gui/gambit.cc \ src/gui/gambit.h \ src/gui/gamedoc.cc \ src/gui/gamedoc.h \ src/gui/gameframe.cc \ src/gui/gameframe.h \ src/gui/menuconst.h \ src/gui/nfgpanel.cc \ src/gui/nfgpanel.h \ src/gui/nfgprofile.cc \ src/gui/nfgprofile.h \ src/gui/nfgtable.cc \ src/gui/nfgtable.h \ src/gui/renratio.cc \ src/gui/renratio.h \ src/gui/style.cc \ src/gui/style.h \ src/gui/valnumber.cc \ src/gui/valnumber.h \ src/gui/tinyxml.cc \ src/gui/tinyxml.h \ src/gui/tinyxmlerror.cc \ src/gui/tinyxmlparser.cc \ src/gui/dcsvg.cc \ src/gui/dcsvg.h gambit_LDADD = \ $(RC_OBJECT_PATH) \ $(WX_LIBS) all: all-recursive .SUFFIXES: .SUFFIXES: .c .cc .cpp .lo .o .obj am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \ cd $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done src/libgambit/$(am__dirstamp): @$(mkdir_p) src/libgambit @: > src/libgambit/$(am__dirstamp) src/libgambit/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/libgambit/$(DEPDIR) @: > src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/integer.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/rational.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/vector.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/pvector.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/dvector.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/matrix.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/sqmatrix.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/game.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/behav.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/behavitr.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/behavspt.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/mixed.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/stratitr.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/stratspt.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/subgame.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/libgambit/file.$(OBJEXT): src/libgambit/$(am__dirstamp) \ src/libgambit/$(DEPDIR)/$(am__dirstamp) src/labenski/src/$(am__dirstamp): @$(mkdir_p) src/labenski/src @: > src/labenski/src/$(am__dirstamp) src/labenski/src/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/labenski/src/$(DEPDIR) @: > src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/sheetatr.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/sheet.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/sheetedg.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/sheetedt.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/sheetren.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/sheetsel.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/sheetspt.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/sheettbl.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/block.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/genergdi.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/geometry.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/menubtn.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/optvalue.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/range.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/spinctld.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/toggle.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/fparser.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/fourier.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/lm_lsqr.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/plotctrl.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/plotcurv.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/plotdata.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/plotdraw.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/plotfunc.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/plotmark.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/labenski/src/plotprnt.$(OBJEXT): src/labenski/src/$(am__dirstamp) \ src/labenski/src/$(DEPDIR)/$(am__dirstamp) src/gui/$(am__dirstamp): @$(mkdir_p) src/gui @: > src/gui/$(am__dirstamp) src/gui/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/gui/$(DEPDIR) @: > src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/analysis.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/edittext.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlabout.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dleditmove.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dleditnode.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlefglayout.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlefglegend.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlefglogit.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlefgreveal.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlgameprop.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlinsertmove.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlnash.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlnashmon.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dlnfglogit.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/efgdisplay.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/efglayout.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/efgpanel.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/efgprofile.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/gambit.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/gamedoc.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/gameframe.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/nfgpanel.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/nfgprofile.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/nfgtable.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/renratio.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/style.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/valnumber.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/tinyxml.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/tinyxmlerror.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/tinyxmlparser.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) src/gui/dcsvg.$(OBJEXT): src/gui/$(am__dirstamp) \ src/gui/$(DEPDIR)/$(am__dirstamp) gambit$(EXEEXT): $(gambit_OBJECTS) $(gambit_DEPENDENCIES) @rm -f gambit$(EXEEXT) $(CXXLINK) $(gambit_LDFLAGS) $(gambit_OBJECTS) $(gambit_LDADD) $(LIBS) src/tools/enummixed/$(am__dirstamp): @$(mkdir_p) src/tools/enummixed @: > src/tools/enummixed/$(am__dirstamp) src/tools/enummixed/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/enummixed/$(DEPDIR) @: > src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/lrsmp.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/lrslib.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/lrsnash.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/basis.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/bfs.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/btableau.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/lptab.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/ludecomp.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/clique.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) src/tools/enummixed/enummixed.$(OBJEXT): \ src/tools/enummixed/$(am__dirstamp) \ src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) gambit-enummixed$(EXEEXT): $(gambit_enummixed_OBJECTS) $(gambit_enummixed_DEPENDENCIES) @rm -f gambit-enummixed$(EXEEXT) $(CXXLINK) $(gambit_enummixed_LDFLAGS) $(gambit_enummixed_OBJECTS) $(gambit_enummixed_LDADD) $(LIBS) src/tools/enumpoly/$(am__dirstamp): @$(mkdir_p) src/tools/enumpoly @: > src/tools/enumpoly/$(am__dirstamp) src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/enumpoly/$(DEPDIR) @: > src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelclhpk.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelclqhl.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelclyal.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelconv.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/peleval.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelgennd.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelgmatr.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelhomot.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelpred.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelprgen.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelproc.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelpsys.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelqhull.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelsymbl.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelutils.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/gpartltr.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/gpoly.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/gpolylst.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/gsolver.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/ideal.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/ineqsolv.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/interval.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/monomial.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/pelclass.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/poly.$(OBJEXT): src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/prepoly.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/quiksolv.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/rectangl.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/behavextend.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/complex.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/linrcomb.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/efgensup.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/sfg.$(OBJEXT): src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/sfstrat.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/nfgensup.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/odometer.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/nfgcpoly.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/nfghs.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/efgpoly.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/nfgpoly.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) src/tools/enumpoly/enumpoly.$(OBJEXT): \ src/tools/enumpoly/$(am__dirstamp) \ src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) gambit-enumpoly$(EXEEXT): $(gambit_enumpoly_OBJECTS) $(gambit_enumpoly_DEPENDENCIES) @rm -f gambit-enumpoly$(EXEEXT) $(CXXLINK) $(gambit_enumpoly_LDFLAGS) $(gambit_enumpoly_OBJECTS) $(gambit_enumpoly_LDADD) $(LIBS) src/tools/enumpure/$(am__dirstamp): @$(mkdir_p) src/tools/enumpure @: > src/tools/enumpure/$(am__dirstamp) src/tools/enumpure/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/enumpure/$(DEPDIR) @: > src/tools/enumpure/$(DEPDIR)/$(am__dirstamp) src/tools/enumpure/enumpure.$(OBJEXT): \ src/tools/enumpure/$(am__dirstamp) \ src/tools/enumpure/$(DEPDIR)/$(am__dirstamp) gambit-enumpure$(EXEEXT): $(gambit_enumpure_OBJECTS) $(gambit_enumpure_DEPENDENCIES) @rm -f gambit-enumpure$(EXEEXT) $(CXXLINK) $(gambit_enumpure_LDFLAGS) $(gambit_enumpure_OBJECTS) $(gambit_enumpure_LDADD) $(LIBS) src/tools/gt/$(am__dirstamp): @$(mkdir_p) src/tools/gt @: > src/tools/gt/$(am__dirstamp) src/tools/gt/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/gt/$(DEPDIR) @: > src/tools/gt/$(DEPDIR)/$(am__dirstamp) src/tools/gt/cmatrix.$(OBJEXT): src/tools/gt/$(am__dirstamp) \ src/tools/gt/$(DEPDIR)/$(am__dirstamp) src/tools/gt/gnm.$(OBJEXT): src/tools/gt/$(am__dirstamp) \ src/tools/gt/$(DEPDIR)/$(am__dirstamp) src/tools/gt/gnmgame.$(OBJEXT): src/tools/gt/$(am__dirstamp) \ src/tools/gt/$(DEPDIR)/$(am__dirstamp) src/tools/gt/nfgame.$(OBJEXT): src/tools/gt/$(am__dirstamp) \ src/tools/gt/$(DEPDIR)/$(am__dirstamp) src/tools/gt/nfggnm.$(OBJEXT): src/tools/gt/$(am__dirstamp) \ src/tools/gt/$(DEPDIR)/$(am__dirstamp) gambit-gnm$(EXEEXT): $(gambit_gnm_OBJECTS) $(gambit_gnm_DEPENDENCIES) @rm -f gambit-gnm$(EXEEXT) $(CXXLINK) $(gambit_gnm_LDFLAGS) $(gambit_gnm_OBJECTS) $(gambit_gnm_LDADD) $(LIBS) src/tools/gt/ipa.$(OBJEXT): src/tools/gt/$(am__dirstamp) \ src/tools/gt/$(DEPDIR)/$(am__dirstamp) src/tools/gt/nfgipa.$(OBJEXT): src/tools/gt/$(am__dirstamp) \ src/tools/gt/$(DEPDIR)/$(am__dirstamp) gambit-ipa$(EXEEXT): $(gambit_ipa_OBJECTS) $(gambit_ipa_DEPENDENCIES) @rm -f gambit-ipa$(EXEEXT) $(CXXLINK) $(gambit_ipa_LDFLAGS) $(gambit_ipa_OBJECTS) $(gambit_ipa_LDADD) $(LIBS) src/tools/lcp/$(am__dirstamp): @$(mkdir_p) src/tools/lcp @: > src/tools/lcp/$(am__dirstamp) src/tools/lcp/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/lcp/$(DEPDIR) @: > src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/basis.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/bfs.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/btableau.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/lemketab.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/lhtab.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/ludecomp.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/tableau.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/efglcp.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/nfglcp.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) src/tools/lcp/lcp.$(OBJEXT): src/tools/lcp/$(am__dirstamp) \ src/tools/lcp/$(DEPDIR)/$(am__dirstamp) gambit-lcp$(EXEEXT): $(gambit_lcp_OBJECTS) $(gambit_lcp_DEPENDENCIES) @rm -f gambit-lcp$(EXEEXT) $(CXXLINK) $(gambit_lcp_LDFLAGS) $(gambit_lcp_OBJECTS) $(gambit_lcp_LDADD) $(LIBS) src/tools/liap/$(am__dirstamp): @$(mkdir_p) src/tools/liap @: > src/tools/liap/$(am__dirstamp) src/tools/liap/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/liap/$(DEPDIR) @: > src/tools/liap/$(DEPDIR)/$(am__dirstamp) src/tools/liap/funcmin.$(OBJEXT): src/tools/liap/$(am__dirstamp) \ src/tools/liap/$(DEPDIR)/$(am__dirstamp) src/tools/liap/efgliap.$(OBJEXT): src/tools/liap/$(am__dirstamp) \ src/tools/liap/$(DEPDIR)/$(am__dirstamp) src/tools/liap/nfgliap.$(OBJEXT): src/tools/liap/$(am__dirstamp) \ src/tools/liap/$(DEPDIR)/$(am__dirstamp) src/tools/liap/liap.$(OBJEXT): src/tools/liap/$(am__dirstamp) \ src/tools/liap/$(DEPDIR)/$(am__dirstamp) gambit-liap$(EXEEXT): $(gambit_liap_OBJECTS) $(gambit_liap_DEPENDENCIES) @rm -f gambit-liap$(EXEEXT) $(CXXLINK) $(gambit_liap_LDFLAGS) $(gambit_liap_OBJECTS) $(gambit_liap_LDADD) $(LIBS) src/tools/logit/$(am__dirstamp): @$(mkdir_p) src/tools/logit @: > src/tools/logit/$(am__dirstamp) src/tools/logit/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/logit/$(DEPDIR) @: > src/tools/logit/$(DEPDIR)/$(am__dirstamp) src/tools/logit/path.$(OBJEXT): src/tools/logit/$(am__dirstamp) \ src/tools/logit/$(DEPDIR)/$(am__dirstamp) src/tools/logit/efglogit.$(OBJEXT): src/tools/logit/$(am__dirstamp) \ src/tools/logit/$(DEPDIR)/$(am__dirstamp) src/tools/logit/nfglogit.$(OBJEXT): src/tools/logit/$(am__dirstamp) \ src/tools/logit/$(DEPDIR)/$(am__dirstamp) src/tools/logit/logit.$(OBJEXT): src/tools/logit/$(am__dirstamp) \ src/tools/logit/$(DEPDIR)/$(am__dirstamp) gambit-logit$(EXEEXT): $(gambit_logit_OBJECTS) $(gambit_logit_DEPENDENCIES) @rm -f gambit-logit$(EXEEXT) $(CXXLINK) $(gambit_logit_LDFLAGS) $(gambit_logit_OBJECTS) $(gambit_logit_LDADD) $(LIBS) src/tools/lp/$(am__dirstamp): @$(mkdir_p) src/tools/lp @: > src/tools/lp/$(am__dirstamp) src/tools/lp/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/lp/$(DEPDIR) @: > src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/basis.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/bfs.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/btableau.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/lpsolve.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/lptab.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/ludecomp.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/tableau.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/efglp.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/nfglp.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) src/tools/lp/lp.$(OBJEXT): src/tools/lp/$(am__dirstamp) \ src/tools/lp/$(DEPDIR)/$(am__dirstamp) gambit-lp$(EXEEXT): $(gambit_lp_OBJECTS) $(gambit_lp_DEPENDENCIES) @rm -f gambit-lp$(EXEEXT) $(CXXLINK) $(gambit_lp_LDFLAGS) $(gambit_lp_OBJECTS) $(gambit_lp_LDADD) $(LIBS) src/tools/logit/nfgdyn.$(OBJEXT): src/tools/logit/$(am__dirstamp) \ src/tools/logit/$(DEPDIR)/$(am__dirstamp) gambit-nfg-logitdyn$(EXEEXT): $(gambit_nfg_logitdyn_OBJECTS) $(gambit_nfg_logitdyn_DEPENDENCIES) @rm -f gambit-nfg-logitdyn$(EXEEXT) $(CXXLINK) $(gambit_nfg_logitdyn_LDFLAGS) $(gambit_nfg_logitdyn_OBJECTS) $(gambit_nfg_logitdyn_LDADD) $(LIBS) src/tools/convert/$(am__dirstamp): @$(mkdir_p) src/tools/convert @: > src/tools/convert/$(am__dirstamp) src/tools/convert/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/convert/$(DEPDIR) @: > src/tools/convert/$(DEPDIR)/$(am__dirstamp) src/tools/convert/nfg2html.$(OBJEXT): \ src/tools/convert/$(am__dirstamp) \ src/tools/convert/$(DEPDIR)/$(am__dirstamp) gambit-nfg2html$(EXEEXT): $(gambit_nfg2html_OBJECTS) $(gambit_nfg2html_DEPENDENCIES) @rm -f gambit-nfg2html$(EXEEXT) $(CXXLINK) $(gambit_nfg2html_LDFLAGS) $(gambit_nfg2html_OBJECTS) $(gambit_nfg2html_LDADD) $(LIBS) src/tools/convert/nfg2tex.$(OBJEXT): \ src/tools/convert/$(am__dirstamp) \ src/tools/convert/$(DEPDIR)/$(am__dirstamp) gambit-nfg2tex$(EXEEXT): $(gambit_nfg2tex_OBJECTS) $(gambit_nfg2tex_DEPENDENCIES) @rm -f gambit-nfg2tex$(EXEEXT) $(CXXLINK) $(gambit_nfg2tex_LDFLAGS) $(gambit_nfg2tex_OBJECTS) $(gambit_nfg2tex_LDADD) $(LIBS) src/tools/simpdiv/$(am__dirstamp): @$(mkdir_p) src/tools/simpdiv @: > src/tools/simpdiv/$(am__dirstamp) src/tools/simpdiv/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) src/tools/simpdiv/$(DEPDIR) @: > src/tools/simpdiv/$(DEPDIR)/$(am__dirstamp) src/tools/simpdiv/nfgsimpdiv.$(OBJEXT): \ src/tools/simpdiv/$(am__dirstamp) \ src/tools/simpdiv/$(DEPDIR)/$(am__dirstamp) gambit-simpdiv$(EXEEXT): $(gambit_simpdiv_OBJECTS) $(gambit_simpdiv_DEPENDENCIES) @rm -f gambit-simpdiv$(EXEEXT) $(CXXLINK) $(gambit_simpdiv_LDFLAGS) $(gambit_simpdiv_OBJECTS) $(gambit_simpdiv_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f src/gui/analysis.$(OBJEXT) -rm -f src/gui/dcsvg.$(OBJEXT) -rm -f src/gui/dlabout.$(OBJEXT) -rm -f src/gui/dleditmove.$(OBJEXT) -rm -f src/gui/dleditnode.$(OBJEXT) -rm -f src/gui/dlefglayout.$(OBJEXT) -rm -f src/gui/dlefglegend.$(OBJEXT) -rm -f src/gui/dlefglogit.$(OBJEXT) -rm -f src/gui/dlefgreveal.$(OBJEXT) -rm -f src/gui/dlgameprop.$(OBJEXT) -rm -f src/gui/dlinsertmove.$(OBJEXT) -rm -f src/gui/dlnash.$(OBJEXT) -rm -f src/gui/dlnashmon.$(OBJEXT) -rm -f src/gui/dlnfglogit.$(OBJEXT) -rm -f src/gui/edittext.$(OBJEXT) -rm -f src/gui/efgdisplay.$(OBJEXT) -rm -f src/gui/efglayout.$(OBJEXT) -rm -f src/gui/efgpanel.$(OBJEXT) -rm -f src/gui/efgprofile.$(OBJEXT) -rm -f src/gui/gambit.$(OBJEXT) -rm -f src/gui/gamedoc.$(OBJEXT) -rm -f src/gui/gameframe.$(OBJEXT) -rm -f src/gui/nfgpanel.$(OBJEXT) -rm -f src/gui/nfgprofile.$(OBJEXT) -rm -f src/gui/nfgtable.$(OBJEXT) -rm -f src/gui/renratio.$(OBJEXT) -rm -f src/gui/style.$(OBJEXT) -rm -f src/gui/tinyxml.$(OBJEXT) -rm -f src/gui/tinyxmlerror.$(OBJEXT) -rm -f src/gui/tinyxmlparser.$(OBJEXT) -rm -f src/gui/valnumber.$(OBJEXT) -rm -f src/labenski/src/block.$(OBJEXT) -rm -f src/labenski/src/fourier.$(OBJEXT) -rm -f src/labenski/src/fparser.$(OBJEXT) -rm -f src/labenski/src/genergdi.$(OBJEXT) -rm -f src/labenski/src/geometry.$(OBJEXT) -rm -f src/labenski/src/lm_lsqr.$(OBJEXT) -rm -f src/labenski/src/menubtn.$(OBJEXT) -rm -f src/labenski/src/optvalue.$(OBJEXT) -rm -f src/labenski/src/plotctrl.$(OBJEXT) -rm -f src/labenski/src/plotcurv.$(OBJEXT) -rm -f src/labenski/src/plotdata.$(OBJEXT) -rm -f src/labenski/src/plotdraw.$(OBJEXT) -rm -f src/labenski/src/plotfunc.$(OBJEXT) -rm -f src/labenski/src/plotmark.$(OBJEXT) -rm -f src/labenski/src/plotprnt.$(OBJEXT) -rm -f src/labenski/src/range.$(OBJEXT) -rm -f src/labenski/src/sheet.$(OBJEXT) -rm -f src/labenski/src/sheetatr.$(OBJEXT) -rm -f src/labenski/src/sheetedg.$(OBJEXT) -rm -f src/labenski/src/sheetedt.$(OBJEXT) -rm -f src/labenski/src/sheetren.$(OBJEXT) -rm -f src/labenski/src/sheetsel.$(OBJEXT) -rm -f src/labenski/src/sheetspt.$(OBJEXT) -rm -f src/labenski/src/sheettbl.$(OBJEXT) -rm -f src/labenski/src/spinctld.$(OBJEXT) -rm -f src/labenski/src/toggle.$(OBJEXT) -rm -f src/libgambit/behav.$(OBJEXT) -rm -f src/libgambit/behavitr.$(OBJEXT) -rm -f src/libgambit/behavspt.$(OBJEXT) -rm -f src/libgambit/dvector.$(OBJEXT) -rm -f src/libgambit/file.$(OBJEXT) -rm -f src/libgambit/game.$(OBJEXT) -rm -f src/libgambit/integer.$(OBJEXT) -rm -f src/libgambit/matrix.$(OBJEXT) -rm -f src/libgambit/mixed.$(OBJEXT) -rm -f src/libgambit/pvector.$(OBJEXT) -rm -f src/libgambit/rational.$(OBJEXT) -rm -f src/libgambit/sqmatrix.$(OBJEXT) -rm -f src/libgambit/stratitr.$(OBJEXT) -rm -f src/libgambit/stratspt.$(OBJEXT) -rm -f src/libgambit/subgame.$(OBJEXT) -rm -f src/libgambit/vector.$(OBJEXT) -rm -f src/tools/convert/nfg2html.$(OBJEXT) -rm -f src/tools/convert/nfg2tex.$(OBJEXT) -rm -f src/tools/enummixed/basis.$(OBJEXT) -rm -f src/tools/enummixed/bfs.$(OBJEXT) -rm -f src/tools/enummixed/btableau.$(OBJEXT) -rm -f src/tools/enummixed/clique.$(OBJEXT) -rm -f src/tools/enummixed/enummixed.$(OBJEXT) -rm -f src/tools/enummixed/lptab.$(OBJEXT) -rm -f src/tools/enummixed/lrslib.$(OBJEXT) -rm -f src/tools/enummixed/lrsmp.$(OBJEXT) -rm -f src/tools/enummixed/lrsnash.$(OBJEXT) -rm -f src/tools/enummixed/ludecomp.$(OBJEXT) -rm -f src/tools/enumpoly/behavextend.$(OBJEXT) -rm -f src/tools/enumpoly/complex.$(OBJEXT) -rm -f src/tools/enumpoly/efgensup.$(OBJEXT) -rm -f src/tools/enumpoly/efgpoly.$(OBJEXT) -rm -f src/tools/enumpoly/enumpoly.$(OBJEXT) -rm -f src/tools/enumpoly/gpartltr.$(OBJEXT) -rm -f src/tools/enumpoly/gpoly.$(OBJEXT) -rm -f src/tools/enumpoly/gpolylst.$(OBJEXT) -rm -f src/tools/enumpoly/gsolver.$(OBJEXT) -rm -f src/tools/enumpoly/ideal.$(OBJEXT) -rm -f src/tools/enumpoly/ineqsolv.$(OBJEXT) -rm -f src/tools/enumpoly/interval.$(OBJEXT) -rm -f src/tools/enumpoly/linrcomb.$(OBJEXT) -rm -f src/tools/enumpoly/monomial.$(OBJEXT) -rm -f src/tools/enumpoly/nfgcpoly.$(OBJEXT) -rm -f src/tools/enumpoly/nfgensup.$(OBJEXT) -rm -f src/tools/enumpoly/nfghs.$(OBJEXT) -rm -f src/tools/enumpoly/nfgpoly.$(OBJEXT) -rm -f src/tools/enumpoly/odometer.$(OBJEXT) -rm -f src/tools/enumpoly/pelclass.$(OBJEXT) -rm -f src/tools/enumpoly/pelclhpk.$(OBJEXT) -rm -f src/tools/enumpoly/pelclqhl.$(OBJEXT) -rm -f src/tools/enumpoly/pelclyal.$(OBJEXT) -rm -f src/tools/enumpoly/pelconv.$(OBJEXT) -rm -f src/tools/enumpoly/peleval.$(OBJEXT) -rm -f src/tools/enumpoly/pelgennd.$(OBJEXT) -rm -f src/tools/enumpoly/pelgmatr.$(OBJEXT) -rm -f src/tools/enumpoly/pelhomot.$(OBJEXT) -rm -f src/tools/enumpoly/pelpred.$(OBJEXT) -rm -f src/tools/enumpoly/pelprgen.$(OBJEXT) -rm -f src/tools/enumpoly/pelproc.$(OBJEXT) -rm -f src/tools/enumpoly/pelpsys.$(OBJEXT) -rm -f src/tools/enumpoly/pelqhull.$(OBJEXT) -rm -f src/tools/enumpoly/pelsymbl.$(OBJEXT) -rm -f src/tools/enumpoly/pelutils.$(OBJEXT) -rm -f src/tools/enumpoly/poly.$(OBJEXT) -rm -f src/tools/enumpoly/prepoly.$(OBJEXT) -rm -f src/tools/enumpoly/quiksolv.$(OBJEXT) -rm -f src/tools/enumpoly/rectangl.$(OBJEXT) -rm -f src/tools/enumpoly/sfg.$(OBJEXT) -rm -f src/tools/enumpoly/sfstrat.$(OBJEXT) -rm -f src/tools/enumpure/enumpure.$(OBJEXT) -rm -f src/tools/gt/cmatrix.$(OBJEXT) -rm -f src/tools/gt/gnm.$(OBJEXT) -rm -f src/tools/gt/gnmgame.$(OBJEXT) -rm -f src/tools/gt/ipa.$(OBJEXT) -rm -f src/tools/gt/nfgame.$(OBJEXT) -rm -f src/tools/gt/nfggnm.$(OBJEXT) -rm -f src/tools/gt/nfgipa.$(OBJEXT) -rm -f src/tools/lcp/basis.$(OBJEXT) -rm -f src/tools/lcp/bfs.$(OBJEXT) -rm -f src/tools/lcp/btableau.$(OBJEXT) -rm -f src/tools/lcp/efglcp.$(OBJEXT) -rm -f src/tools/lcp/lcp.$(OBJEXT) -rm -f src/tools/lcp/lemketab.$(OBJEXT) -rm -f src/tools/lcp/lhtab.$(OBJEXT) -rm -f src/tools/lcp/ludecomp.$(OBJEXT) -rm -f src/tools/lcp/nfglcp.$(OBJEXT) -rm -f src/tools/lcp/tableau.$(OBJEXT) -rm -f src/tools/liap/efgliap.$(OBJEXT) -rm -f src/tools/liap/funcmin.$(OBJEXT) -rm -f src/tools/liap/liap.$(OBJEXT) -rm -f src/tools/liap/nfgliap.$(OBJEXT) -rm -f src/tools/logit/efglogit.$(OBJEXT) -rm -f src/tools/logit/logit.$(OBJEXT) -rm -f src/tools/logit/nfgdyn.$(OBJEXT) -rm -f src/tools/logit/nfglogit.$(OBJEXT) -rm -f src/tools/logit/path.$(OBJEXT) -rm -f src/tools/lp/basis.$(OBJEXT) -rm -f src/tools/lp/bfs.$(OBJEXT) -rm -f src/tools/lp/btableau.$(OBJEXT) -rm -f src/tools/lp/efglp.$(OBJEXT) -rm -f src/tools/lp/lp.$(OBJEXT) -rm -f src/tools/lp/lpsolve.$(OBJEXT) -rm -f src/tools/lp/lptab.$(OBJEXT) -rm -f src/tools/lp/ludecomp.$(OBJEXT) -rm -f src/tools/lp/nfglp.$(OBJEXT) -rm -f src/tools/lp/tableau.$(OBJEXT) -rm -f src/tools/simpdiv/nfgsimpdiv.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/analysis.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dcsvg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlabout.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dleditmove.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dleditnode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlefglayout.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlefglegend.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlefglogit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlefgreveal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlgameprop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlinsertmove.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlnash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlnashmon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/dlnfglogit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/edittext.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/efgdisplay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/efglayout.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/efgpanel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/efgprofile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/gambit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/gamedoc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/gameframe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/nfgpanel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/nfgprofile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/nfgtable.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/renratio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/style.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/tinyxml.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/tinyxmlerror.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/tinyxmlparser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/gui/$(DEPDIR)/valnumber.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/block.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/fourier.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/fparser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/genergdi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/geometry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/lm_lsqr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/menubtn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/optvalue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/plotctrl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/plotcurv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/plotdata.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/plotdraw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/plotfunc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/plotmark.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/plotprnt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/range.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/sheet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/sheetatr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/sheetedg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/sheetedt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/sheetren.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/sheetsel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/sheetspt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/sheettbl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/spinctld.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/labenski/src/$(DEPDIR)/toggle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/behav.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/behavitr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/behavspt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/dvector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/game.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/integer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/matrix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/mixed.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/pvector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/rational.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/sqmatrix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/stratitr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/stratspt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/subgame.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/libgambit/$(DEPDIR)/vector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/convert/$(DEPDIR)/nfg2html.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/convert/$(DEPDIR)/nfg2tex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/basis.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/bfs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/btableau.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/clique.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/enummixed.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/lptab.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/lrslib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/lrsmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/lrsnash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enummixed/$(DEPDIR)/ludecomp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/behavextend.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/complex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/efgensup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/efgpoly.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/enumpoly.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/gpartltr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/gpoly.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/gpolylst.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/gsolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/ideal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/ineqsolv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/interval.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/linrcomb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/monomial.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/nfgcpoly.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/nfgensup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/nfghs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/nfgpoly.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/odometer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelclass.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelclhpk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelclqhl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelclyal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelconv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/peleval.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelgennd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelgmatr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelhomot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelpred.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelprgen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelproc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelpsys.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelqhull.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelsymbl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/pelutils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/poly.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/prepoly.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/quiksolv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/rectangl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/sfg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpoly/$(DEPDIR)/sfstrat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/enumpure/$(DEPDIR)/enumpure.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/gt/$(DEPDIR)/cmatrix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/gt/$(DEPDIR)/gnm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/gt/$(DEPDIR)/gnmgame.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/gt/$(DEPDIR)/ipa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/gt/$(DEPDIR)/nfgame.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/gt/$(DEPDIR)/nfggnm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/gt/$(DEPDIR)/nfgipa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/basis.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/bfs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/btableau.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/efglcp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/lcp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/lemketab.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/lhtab.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/ludecomp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/nfglcp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lcp/$(DEPDIR)/tableau.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/liap/$(DEPDIR)/efgliap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/liap/$(DEPDIR)/funcmin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/liap/$(DEPDIR)/liap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/liap/$(DEPDIR)/nfgliap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/logit/$(DEPDIR)/efglogit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/logit/$(DEPDIR)/logit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/logit/$(DEPDIR)/nfgdyn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/logit/$(DEPDIR)/nfglogit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/logit/$(DEPDIR)/path.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/basis.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/bfs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/btableau.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/efglp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/lp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/lpsolve.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/lptab.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/ludecomp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/nfglp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/lp/$(DEPDIR)/tableau.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/tools/simpdiv/$(DEPDIR)/nfgsimpdiv.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`; \ @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`; \ @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCC_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`; \ @am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Plo"; else rm -f "$$depbase.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< .cc.o: @am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`; \ @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`; \ @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCXX_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`; \ @am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Plo"; else rm -f "$$depbase.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< .cpp.o: @am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`; \ @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`; \ @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCXX_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`; \ @am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$$depbase.Tpo" "$$depbase.Plo"; else rm -f "$$depbase.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: install-libgambitincludeHEADERS: $(libgambitinclude_HEADERS) @$(NORMAL_INSTALL) test -z "$(libgambitincludedir)" || $(mkdir_p) "$(DESTDIR)$(libgambitincludedir)" @list='$(libgambitinclude_HEADERS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(libgambitincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libgambitincludedir)/$$f'"; \ $(libgambitincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libgambitincludedir)/$$f"; \ done uninstall-libgambitincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libgambitinclude_HEADERS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(libgambitincludedir)/$$f'"; \ rm -f "$(DESTDIR)$(libgambitincludedir)/$$f"; \ done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) $(mkdir_p) $(distdir)/contrib/games $(distdir)/contrib/mac $(distdir)/src/gui/bitmaps $(distdir)/src/labenski $(distdir)/src/labenski/art $(distdir)/src/labenski/doc $(distdir)/src/labenski/include/wx/wxthings/bitmaps $(distdir)/src/libgambit @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(mkdir_p) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libgambitincludedir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -rm -f src/gui/$(DEPDIR)/$(am__dirstamp) -rm -f src/gui/$(am__dirstamp) -rm -f src/labenski/src/$(DEPDIR)/$(am__dirstamp) -rm -f src/labenski/src/$(am__dirstamp) -rm -f src/libgambit/$(DEPDIR)/$(am__dirstamp) -rm -f src/libgambit/$(am__dirstamp) -rm -f src/tools/convert/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/convert/$(am__dirstamp) -rm -f src/tools/enummixed/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/enummixed/$(am__dirstamp) -rm -f src/tools/enumpoly/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/enumpoly/$(am__dirstamp) -rm -f src/tools/enumpure/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/enumpure/$(am__dirstamp) -rm -f src/tools/gt/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/gt/$(am__dirstamp) -rm -f src/tools/lcp/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/lcp/$(am__dirstamp) -rm -f src/tools/liap/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/liap/$(am__dirstamp) -rm -f src/tools/logit/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/logit/$(am__dirstamp) -rm -f src/tools/lp/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/lp/$(am__dirstamp) -rm -f src/tools/simpdiv/$(DEPDIR)/$(am__dirstamp) -rm -f src/tools/simpdiv/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf src/gui/$(DEPDIR) src/labenski/src/$(DEPDIR) src/libgambit/$(DEPDIR) src/tools/convert/$(DEPDIR) src/tools/enummixed/$(DEPDIR) src/tools/enumpoly/$(DEPDIR) src/tools/enumpure/$(DEPDIR) src/tools/gt/$(DEPDIR) src/tools/lcp/$(DEPDIR) src/tools/liap/$(DEPDIR) src/tools/logit/$(DEPDIR) src/tools/lp/$(DEPDIR) src/tools/simpdiv/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-libgambitincludeHEADERS install-exec-am: install-binPROGRAMS install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf src/gui/$(DEPDIR) src/labenski/src/$(DEPDIR) src/libgambit/$(DEPDIR) src/tools/convert/$(DEPDIR) src/tools/enummixed/$(DEPDIR) src/tools/enumpoly/$(DEPDIR) src/tools/enumpure/$(DEPDIR) src/tools/gt/$(DEPDIR) src/tools/lcp/$(DEPDIR) src/tools/liap/$(DEPDIR) src/tools/logit/$(DEPDIR) src/tools/lp/$(DEPDIR) src/tools/simpdiv/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-info-am \ uninstall-libgambitincludeHEADERS uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ check-am clean clean-binPROGRAMS clean-generic clean-libtool \ clean-recursive ctags ctags-recursive dist dist-all dist-bzip2 \ dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-recursive distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-libgambitincludeHEADERS install-man \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-info-am \ uninstall-libgambitincludeHEADERS osx-bundle: make all -rm -rf Gambit.app -mkdir Gambit.app -mkdir Gambit.app/Contents -mkdir Gambit.app/Contents/MacOS -mkdir Gambit.app/Contents/Resources cp contrib/mac/Info.plist Gambit.app/Contents echo -n 'APPL????' > Gambit.app/Contents/PkgInfo cp gambit Gambit.app/Contents/MacOS/gambit # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gambit-0.2010.09.01/missing0000755000076500007650000002623311425044435012047 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2009-04-28.21; # UTC # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, # 2008, 2009 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # 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. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and \`g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; tar*) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar*) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case $firstarg in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case $firstarg in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gambit-0.2010.09.01/mkinstalldirs0000755000076500007650000000672211425044435013257 00000000000000#! /bin/sh # mkinstalldirs --- make directory hierarchy scriptversion=2009-04-28.21; # UTC # Original author: Noah Friedman # Created: 1993-05-16 # Public domain. # # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' IFS=" "" $nl" errstatus=0 dirmode= usage="\ Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... Create each directory DIR (with mode MODE, if specified), including all leading file name components. Report bugs to ." # process command line arguments while test $# -gt 0 ; do case $1 in -h | --help | --h*) # -h for help echo "$usage" exit $? ;; -m) # -m PERM arg shift test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } dirmode=$1 shift ;; --version) echo "$0 $scriptversion" exit $? ;; --) # stop option processing shift break ;; -*) # unknown option echo "$usage" 1>&2 exit 1 ;; *) # first non-opt arg break ;; esac done for file do if test -d "$file"; then shift else break fi done case $# in 0) exit 0 ;; esac # Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and # mkdir -p a/c at the same time, both will detect that a is missing, # one will create a, then the other will try to create a and die with # a "File exists" error. This is a problem when calling mkinstalldirs # from a parallel make. We use --version in the probe to restrict # ourselves to GNU mkdir, which is thread-safe. case $dirmode in '') if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then echo "mkdir -p -- $*" exec mkdir -p -- "$@" else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. test -d ./-p && rmdir ./-p test -d ./--version && rmdir ./--version fi ;; *) if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && test ! -d ./--version; then echo "mkdir -m $dirmode -p -- $*" exec mkdir -m "$dirmode" -p -- "$@" else # Clean up after NextStep and OpenStep mkdir. for d in ./-m ./-p ./--version "./$dirmode"; do test -d $d && rmdir $d done fi ;; esac for file do case $file in /*) pathcomp=/ ;; *) pathcomp= ;; esac oIFS=$IFS IFS=/ set fnord $file shift IFS=$oIFS for d do test "x$d" = x && continue pathcomp=$pathcomp$d case $pathcomp in -*) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr else if test ! -z "$dirmode"; then echo "chmod $dirmode $pathcomp" lasterr= chmod "$dirmode" "$pathcomp" || lasterr=$? if test ! -z "$lasterr"; then errstatus=$lasterr fi fi fi fi pathcomp=$pathcomp/ done done exit $errstatus # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gambit-0.2010.09.01/NEWS0000644000076500007650000000013311350032206011124 00000000000000The latest Gambit news is available on the Gambit website, http://econweb.tamu.edu/gambit gambit-0.2010.09.01/README0000644000076500007650000000041011435216077011321 00000000000000 This is the README file for Gambit, software tools for game theory. The latest information on Gambit can be obtained from the Gambit website at http://www.gambit-project.org Instructions on installing Gambit can be found in the file INSTALL in this directory. gambit-0.2010.09.01/src/0000777000076500007650000000000011441457116011317 500000000000000gambit-0.2010.09.01/src/gui/0000777000076500007650000000000011441457115012102 500000000000000gambit-0.2010.09.01/src/gui/analysis.cc0000644000076500007650000003077311435216100014150 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/analysis.cc // Declaration of analysis storage classes // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include #include "tinyxml.h" // for XML parser for Load() #include "libgambit/libgambit.h" #include "analysis.h" #include "gamedoc.h" using namespace Gambit; //========================================================================= // class gbtAnalysisProfileList //========================================================================= // Use anonymous namespace to make these helpers private namespace { class gbtNotNashException : public Exception { public: virtual ~gbtNotNashException() { } std::string GetDescription(void) const { return "Output line does not contain a Nash equilibrium"; } }; template MixedStrategyProfile OutputToMixedProfile(gbtGameDocument *p_doc, const wxString &p_text) { MixedStrategyProfile profile(p_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); if (tok.GetNextToken() == wxT("NE")) { if (tok.CountTokens() == (unsigned int) profile.Length()) { for (int i = 1; i <= profile.Length(); i++) { profile[i] = ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } return profile; } } throw gbtNotNashException(); } template MixedBehavProfile OutputToBehavProfile(gbtGameDocument *p_doc, const wxString &p_text) { MixedBehavProfile profile(p_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); if (tok.GetNextToken() == wxT("NE")) { if (tok.CountTokens() == (unsigned int) profile.Length()) { for (int i = 1; i <= profile.Length(); i++) { profile[i] = ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } return profile; } } throw gbtNotNashException(); } } // end anonymous namespace template void gbtAnalysisProfileList::AddOutput(const wxString &p_output) { try { if (m_isBehav) { MixedBehavProfile profile(OutputToBehavProfile(m_doc, p_output)); m_behavProfiles.Append(profile); m_mixedProfiles.Append(MixedStrategyProfile(profile)); m_current = m_behavProfiles.Length(); } else { MixedStrategyProfile profile(OutputToMixedProfile(m_doc, p_output)); m_mixedProfiles.Append(profile); if (m_doc->IsTree()) { m_behavProfiles.Append(MixedBehavProfile(profile)); } m_current = m_mixedProfiles.Length(); } } catch (gbtNotNashException &) { } } template void gbtAnalysisProfileList::BuildNfg(void) { for (int i = 1; i <= m_behavProfiles.Length(); i++) { m_mixedProfiles.Append(MixedStrategyProfile(m_behavProfiles[i])); } } template int gbtAnalysisProfileList::NumProfiles(void) const { if (m_doc->IsTree()) { return m_behavProfiles.Length(); } else { return m_mixedProfiles.Length(); } } template void gbtAnalysisProfileList::Clear(void) { m_behavProfiles = List >(); m_mixedProfiles = List >(); m_current = 0; } //------------------------------------------------------------------------- // gbtAnalysisProfileList: Saving and loading profile lists //------------------------------------------------------------------------- // Use anonymous namespace to make these helpers private namespace { template MixedStrategyProfile TextToMixedProfile(gbtGameDocument *p_doc, const wxString &p_text) { MixedStrategyProfile profile(p_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); for (int i = 1; i <= profile.Length(); i++) { profile[i] = ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } return profile; } template MixedBehavProfile TextToBehavProfile(gbtGameDocument *p_doc, const wxString &p_text) { MixedBehavProfile profile(p_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); for (int i = 1; i <= profile.Length(); i++) { profile[i] = ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } return profile; } } // end anonymous namespace // // Load a profile list from XML. Pass a node pointing to an // entry in the workbook file // template void gbtAnalysisProfileList::Load(TiXmlNode *p_analysis) { Clear(); TiXmlNode *description = p_analysis->FirstChild("description"); if (description) { m_description = wxString(description->FirstChild()->Value(), *wxConvCurrent); } for (TiXmlNode *node = p_analysis->FirstChild("profile"); node; node = node->NextSiblingElement()) { const char *type = node->ToElement()->Attribute("type"); if (!strcmp(type, "behav")) { MixedBehavProfile profile = TextToBehavProfile(m_doc, wxString(node->FirstChild()->Value(), *wxConvCurrent)); m_behavProfiles.Append(profile); m_isBehav = true; m_current = m_behavProfiles.Length(); } else { MixedStrategyProfile profile = TextToMixedProfile(m_doc, wxString(node->FirstChild()->Value(), *wxConvCurrent)); m_mixedProfiles.Append(profile); m_isBehav = false; m_current = m_mixedProfiles.Length(); } } } template std::string gbtAnalysisProfileList::GetPayoff(int pl, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { if (m_doc->IsTree()) { return ToText(m_behavProfiles[index].GetPayoff(pl), m_doc->GetStyle().NumDecimals()); } else { return ToText(m_mixedProfiles[index].GetPayoff(pl), m_doc->GetStyle().NumDecimals()); } } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetRealizProb(const GameNode &p_node, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { return ToText(m_behavProfiles[index].GetRealizProb(p_node), m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetBeliefProb(const GameNode &p_node, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (!p_node->GetPlayer()) return ""; try { if (m_behavProfiles[index].GetInfosetProb(p_node->GetInfoset()) > Rational(0)) { return ToText(m_behavProfiles[index].GetBeliefProb(p_node), m_doc->GetStyle().NumDecimals()); } else { // We don't compute assessments yet! return "*"; } } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetNodeValue(const GameNode &p_node, int p_player, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { return ToText(m_behavProfiles[index].GetNodeValue(p_node)[p_player], m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetInfosetProb(const GameNode &p_node, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (!p_node->GetPlayer()) return ""; try { return ToText(m_behavProfiles[index].GetInfosetProb(p_node->GetInfoset()), m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetInfosetValue(const GameNode &p_node, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (!p_node->GetPlayer() || p_node->GetPlayer()->IsChance()) return ""; try { if (m_behavProfiles[index].GetInfosetProb(p_node->GetInfoset()) > Rational(0)) { return ToText(m_behavProfiles[index].GetInfosetValue(p_node->GetInfoset()), m_doc->GetStyle().NumDecimals()); } else { // In the absence of beliefs, this is not well-defined in general return "*"; } } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetActionProb(const GameNode &p_node, int p_act, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (p_node->GetPlayer() && p_node->GetPlayer()->IsChance()) { GameInfoset infoset = p_node->GetInfoset(); return infoset->GetActionProb(p_act); } if (!p_node->GetPlayer()) return ""; try { const MixedBehavProfile &profile = m_behavProfiles[index]; if (!profile.IsDefinedAt(p_node->GetInfoset())) { return "*"; } return ToText(profile.GetActionProb(p_node->GetInfoset()->GetAction(p_act)), m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetActionProb(int p_action, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { const MixedBehavProfile &profile = m_behavProfiles[index]; if (!profile.IsDefinedAt(profile.GetGame()->GetAction(p_action)->GetInfoset())) { return "*"; } return ToText(profile[p_action], m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetActionValue(const GameNode &p_node, int p_act, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (!p_node->GetPlayer() || p_node->GetPlayer()->IsChance()) return ""; try { if (m_behavProfiles[index].GetInfosetProb(p_node->GetInfoset()) > Rational(0)) { return ToText(m_behavProfiles[index].GetActionValue(p_node->GetInfoset()->GetAction(p_act)), m_doc->GetStyle().NumDecimals()); } else { // In the absence of beliefs, this is not well-defined return "*"; } } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetStrategyProb(int p_strategy, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { const MixedStrategyProfile &profile = m_mixedProfiles[index]; return ToText(profile[p_strategy], m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetStrategyValue(int p_strategy, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { const MixedStrategyProfile &profile = m_mixedProfiles[index]; GameStrategy strategy = profile.GetGame()->GetStrategy(p_strategy); return ToText(profile.GetStrategyValue(strategy), m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template void gbtAnalysisProfileList::Save(std::ostream &p_file) const { p_file << "\n"; p_file << "\n"; p_file << (const char *) m_description.mb_str() << "\n"; p_file << "\n"; if (m_doc->IsTree()) { for (int j = 1; j <= NumProfiles(); j++) { const MixedBehavProfile &behav = m_behavProfiles[j]; p_file << "\n"; for (int k = 1; k <= behav.Length(); k++) { p_file << behav[k]; if (k < behav.Length()) { p_file << ","; } else { p_file << "\n"; } } p_file << "\n"; } } else { for (int j = 1; j <= NumProfiles(); j++) { const MixedStrategyProfile &mixed = m_mixedProfiles[j]; p_file << "\n"; for (int k = 1; k <= mixed.Length(); k++) { p_file << mixed[k]; if (k < mixed.Length()) { p_file << ","; } else { p_file << "\n"; } } p_file << "\n"; } } p_file << "\n"; } // Explicit instantiations template class gbtAnalysisProfileList; template class gbtAnalysisProfileList; gambit-0.2010.09.01/src/gui/analysis.h0000644000076500007650000001536511435216100014012 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/analysis.h // Declaration of analysis storage classes // // 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 ANALYSIS_H #define ANALYSIS_H class gbtGameDocument; // // This file contains classes which manage the output of analysis tools. // Currently, one class is supported, which is simply a list of profiles // output by, e.g., an algorithm to compute Nash equilibria. // Future classes will be adapted to other types of output (e.g., // output of stable sets or convex components of equilibria, etc.) // class TiXmlNode; class gbtAnalysisOutput { protected: gbtGameDocument *m_doc; wxString m_label, m_description, m_command; public: /// @name Lifecycle //@{ /// Construct a new output group gbtAnalysisOutput(gbtGameDocument *p_doc) : m_doc(p_doc) { } /// Clean up an output group virtual ~gbtAnalysisOutput() { } //@} /// @name General data access //@{ /// Get the label (short description) of the list const wxString &GetLabel(void) const { return m_label; } /// Set the label (short description) of the list void SetLabel(const wxString &p_label) { m_label = p_label; } /// Get the description of the list const wxString &GetDescription(void) const { return m_description; } /// Set the description of the list void SetDescription(const wxString &p_desc) { m_description = p_desc; } /// Get the command used to generate the list const wxString &GetCommand(void) const { return m_command; } /// Set the command used to generate the list void SetCommand(const wxString &p_command) { m_command = p_command; } /// The number of profiles in the list virtual int NumProfiles(void) const = 0; /// Get the index of the currently selected profile virtual int GetCurrent(void) const = 0; /// Set the index of the currently selected profile virtual void SetCurrent(int p_index) = 0; /// Are these behavior or strategy profiles natively? virtual bool IsBehavior(void) const = 0; //@} virtual std::string GetPayoff(int pl, int p_index = -1) const = 0; virtual std::string GetRealizProb(const Gambit::GameNode &, int p_index = -1) const = 0; virtual std::string GetBeliefProb(const Gambit::GameNode &, int p_index = -1) const = 0; virtual std::string GetNodeValue(const Gambit::GameNode &, int pl, int p_index = -1) const = 0; virtual std::string GetInfosetProb(const Gambit::GameNode &, int p_index = -1) const = 0; virtual std::string GetInfosetValue(const Gambit::GameNode &, int p_index = -1) const = 0; virtual std::string GetActionValue(const Gambit::GameNode &, int act, int p_index = -1) const = 0; virtual std::string GetActionProb(const Gambit::GameNode &, int act, int p_index = -1) const = 0; virtual std::string GetActionProb(int p_action, int p_index = -1) const = 0; virtual std::string GetStrategyProb(int p_strategy, int p_index = -1) const = 0; virtual std::string GetStrategyValue(int p_strategy, int p_index = -1) const = 0; virtual void AddOutput(const wxString &) = 0; /// Map all behavior profiles to corresponding mixed profiles virtual void BuildNfg(void) = 0; /// Write a profile list to XML savefile virtual void Save(std::ostream &) const = 0; }; //! //! This class manages a list of profiles, computed, e.g., by an //! algorithm for finding Nash equilibria. It maintains two lists //! of profiles, one with the behavior representation and the other //! with the mixed representation. //! template class gbtAnalysisProfileList : public gbtAnalysisOutput { private: bool m_isBehav; int m_current; Gambit::List > m_behavProfiles; Gambit::List > m_mixedProfiles; public: //! //! @name Lifecycle //! //@{ /// Construct a new profile list for the specified document gbtAnalysisProfileList(gbtGameDocument *p_doc, bool p_isBehav) : gbtAnalysisOutput(p_doc), m_isBehav(p_isBehav), m_current(0) { } /// Cleanup the profile list virtual ~gbtAnalysisProfileList() { } //@} //! //! @name General data access //! //@{ /// Are these behavior or strategy profiles natively? bool IsBehavior(void) const { return m_isBehav; } /// The number of profiles in the list int NumProfiles(void) const; std::string GetPayoff(int pl, int p_index = -1) const; /// Return the realization probability of the node for the given /// profile. (index == -1 for currently selected profile) std::string GetRealizProb(const Gambit::GameNode &, int p_index = -1) const; std::string GetBeliefProb(const Gambit::GameNode &, int p_index = -1) const; std::string GetNodeValue(const Gambit::GameNode &, int pl, int p_index = -1) const; std::string GetInfosetProb(const Gambit::GameNode &, int p_index = -1) const; std::string GetInfosetValue(const Gambit::GameNode &, int p_index = -1) const; std::string GetActionValue(const Gambit::GameNode &, int act, int p_index = -1) const; std::string GetActionProb(const Gambit::GameNode &, int act, int p_index = -1) const; std::string GetActionProb(int p_action, int p_index = -1) const; std::string GetStrategyProb(int p_strategy, int p_index = -1) const; std::string GetStrategyValue(int p_strategy, int p_index = -1) const; /// Get the index of the currently selected profile int GetCurrent(void) const { return m_current; } /// Set the index of the currently selected profile void SetCurrent(int p_index) { m_current = p_index; } //@} //! //! @name Adding profiles to the list //! //@{ void AddOutput(const wxString &); /// Map all behavior profiles to corresponding mixed profiles void BuildNfg(void); /// Remove all profiles from the list void Clear(void); //@} //! //! @name Saving and loading profile lists //! //@{ /// Build a profile list from XML savefile void Load(TiXmlNode *analysis); /// Write a profile list to XML savefile void Save(std::ostream &) const; //@} }; #endif // ANALYSIS_H gambit-0.2010.09.01/src/gui/bitmaps/0000777000076500007650000000000011441457130013536 500000000000000gambit-0.2010.09.01/src/gui/bitmaps/about.xpm0000644000076500007650000000166511350032206015312 00000000000000/* XPM */ static char * about_xpm[] = { "24 24 15 1", " c None", ". c #000000", "+ c #EEF63E", "@ c #EAF13D", "# c #F0F83F", "$ c #C9D034", "% c #E9F03D", "& c #E5EC3C", "* c #E8F03D", "= c #A9AE2C", "- c #ECF33E", "; c #EFF73F", "> c #CED636", ", c #B1B72E", "' c #CCD334", " ", " . . ", " .+. .+. ", " ..@#$.. ..@#$.. ", " .######%. .######%. ", " .####&. .####&. ", " .*###=. .*###=. ", " .#-.;>. .#-.;>. ", " .,. .'. .,. .'. ", " . . . . ", " ", " ", " ", " . . ", " .+. .+. ", " ..@#$.. ..@#$.. ", " .######%. .######%. ", " .####&. .####&. ", " .*###=. .*###=. ", " .#-.;>. .#-.;>. ", " .,. .'. .,. .'. ", " . . . . ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/adddecimal.xpm0000644000076500007650000000140511350032206016237 00000000000000/* XPM */ static char * adddecimal_xpm[] = { "24 24 3 1", " c None", ". c #000000", "+ c #314E6C", " ", " ", " ", " .. ", " . . ", " . . +++++++++++ ", " . . +++++++++++ ", " . . ++ ", " . . ++ ", " .. ++++++ ", " ++++ ", " ++ ", " ", " .. .. .. ", " . . . . . . ", " . . . . . . ", " . . . . . . ", " . . . . . . ", " . . . . . . . ", " . .. .. .. ", " ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/calc.xpm0000644000076500007650000000676411350032206015107 00000000000000/* XPM */ static char * calc_xpm[] = { "24 24 142 2", " c None", ". c #000000", "+ c #484848", "@ c #9B9B9B", "# c #D7D7D7", "$ c #C0C0C0", "% c #8A8A8A", "& c #313434", "* c #515151", "= c #4E4E4E", "- c #303032", "; c #8C8C84", "> c #515D51", ", c #424C42", "' c #495449", ") c #434D43", "! c #6A7367", "~ c #2F3031", "{ c #6B7B6B", "] c #384038", "^ c #4D594D", "/ c #606F60", "( c #2E2F30", "_ c #2E2E30", ": c #4C4C48", "< c #676761", "[ c #393935", "} c #2D2D2F", "| c #6C6C6C", "1 c #121212", "2 c #6D6D6D", "3 c #2D2C2E", "4 c #8A8D8D", "5 c #2D2F2F", "6 c #161617", "7 c #545356", "8 c #303031", "9 c #A5A8A9", "0 c #636869", "a c #626667", "b c #616566", "c c #606365", "d c #5F6264", "e c #5E6162", "f c #5D5F61", "g c #5C5E60", "h c #5B5D5F", "i c #5A5C5E", "j c #595A5D", "k c #58595B", "l c #57575A", "m c #565659", "n c #555457", "o c #2C2B2D", "p c #A5A7A8", "q c #7B7B7B", "r c #ACACAC", "s c #2B2A2C", "t c #A4A6A7", "u c #565656", "v c #8E8E8E", "w c #979797", "x c #676767", "y c #B5B5B5", "z c #A0A0A0", "A c #2B2A2B", "B c #A3A6A6", "C c #4D4F51", "D c #5D5E60", "E c #4A4B4D", "F c #5A5B5C", "G c #474749", "H c #575759", "I c #434345", "J c #413F42", "K c #2A292B", "L c #A3A5A6", "M c #4C4F50", "N c #494A4C", "O c #464748", "P c #535255", "Q c #525054", "R c #514F52", "S c #504E51", "T c #2A282A", "U c #A2A4A5", "V c #929292", "W c #818181", "X c #737373", "Y c #29282A", "Z c #3A3A3A", "` c #808080", " . c #757575", ".. c #8D8D8D", "+. c #A2A3A5", "@. c #858788", "#. c #848687", "$. c #6A6B6D", "%. c #595A5C", "&. c #828284", "*. c #818184", "=. c #565558", "-. c #555558", ";. c #7F7E81", ">. c #7E7E80", ",. c #525154", "'. c #BABABA", "). c #292629", "!. c #A1A2A3", "~. c #292628", "{. c #A4A4A4", "]. c #727272", "^. c #282528", "/. c #48494B", "(. c #464648", "_. c #454547", ":. c #434144", "<. c #434143", "[. c #403D40", "}. c #4F4B4F", "|. c #7B787B", "1. c #7A7679", "2. c #797578", "3. c #232022", "4. c #2B2E2E", "5. c #3A3B3C", "6. c #3A3A3C", "7. c #39393B", "8. c #38383A", "9. c #383739", "0. c #363637", "a. c #373538", "b. c #363537", "c. c #363437", "d. c #383638", "e. c #353235", "f. c #343134", "g. c #333133", "h. c #332F32", "i. c #322F31", "j. c #312D31", "k. c #171818", " ", " . . . . . . . . . . . . . . . . . ", " + @ # $ @ @ @ @ @ @ @ @ @ @ @ @ % & ", " * = = = = = = = = = = = = = = = = - ", " * ; ; > > > > > > > , ' ) > ! ; ; ~ ", " * ; ; { { { { { { { ] > ^ / { ; ; ( ", " * ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; _ ", " * : ; ; ; ; ; ; ; ; ; ; ; ; ; < [ } ", " | 1 . . . . . . . . . . . . . . 2 3 ", " 4 5 . . . . . . . . . . . . . 6 7 8 ", " 9 0 a b c d e f g h i j k l m n 7 o ", " p . q q . . q q . . q q . . r r . s ", " t . u u . . v w . . x u . . y z . A ", " B C . . D E . . F G . . H I . . J K ", " L M . . E N . . G O . . I P Q R S T ", " U . V u . . W x . . X X . . r r . Y ", " U . Z Z . . Z | . . ` .. . ..... Y ", " +.f @.#.$.%.&.*.=.-.;.>.,.. y '.. ). ", " !.. q q . . q q . . q q . . ..... ~. ", " !.. u u . . u V . . X {.. . ].].. ^. ", " h /.. . (._.. . :.<.. . [.}.|.1.2.3. ", " 4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k. ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/close.xpm0000644000076500007650000000136111350032206015276 00000000000000/* XPM */ static char * close_xpm[] = { "24 24 2 1", " c None", ". c #000000", " ", " ", " ", " ", " ", " ", " . . ", " . ... ", " .. .... ", " .. ... ", " ..... ", " ... ", " ..... ", " ....... ", " ... .... ", " ... .... ", " ... .. ", " ", " ", " ", " ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/color.xpm0000644000076500007650000000314411350032206015310 00000000000000/* XPM */ static char * color_xpm[] = { "24 24 60 1", " c None", ". c #000000", "+ c #FF4B39", "@ c #FF6353", "# c #FF5B4B", "$ c #FF3B21", "% c #FF4D3B", "& c #FF6F64", "* c #FF7770", "= c #FF5D4C", "- c #FF3418", "; c #FF6454", "> c #FF8F8F", ", c #FF4C35", "' c #FF5F4F", ") c #FF4E31", "! c #FF432B", "~ c #FF523B", "{ c #FF290C", "] c #2FC31C", "^ c #15B215", "/ c #000700", "( c #FF391E", "_ c #FF4E37", ": c #FF2B0E", "< c #1BF21B", "[ c #1AFF1A", "} c #16C116", "| c #074207", "1 c #000500", "2 c #20202B", "3 c #38628D", "4 c #4174A8", "5 c #58587D", "6 c #1BDE1B", "7 c #39FF39", "8 c #1BE21B", "9 c #1DC41D", "0 c #030304", "a c #598EC0", "b c #679BCC", "c c #4177AA", "d c #504E75", "e c #1BD61B", "f c #1BDA1B", "g c #020405", "h c #85B8E8", "i c #477EB2", "j c #285E95", "k c #2FB619", "l c #1DC61D", "m c #30B316", "n c #132432", "o c #235B8F", "p c #2FB419", "q c #464665", "r c #2E6399", "s c #444469", "t c #4F4F76", "u c #464469", " ", " ", " ", " ", " ", " .... ", " .+@#$. ", " .%&*&=-. ", " .;*>*;,. ", " .'&*&=). ", " ..!=;=~{. ", " .]^/(_):... ", " .]<[}|1.2345. ", " .6[7[890abacd. ", " .e<[ c #424242", ", c #666666", "' c #7A7A7A", ") c #2E2E2E", "! c #A2A2A2", "~ c #383838", "{ c #707070", "] c #CBCBCB", "^ c #A9A9A9", "/ c #0F0F0F", "( c #3B3B3B", "_ c #0A0A0A", ": c #151515", "< c #5B5B5B", "[ c #262626", "} c #1A1A1A", "| c #616161", "1 c #4E4E4E", "2 c #ACACAC", "3 c #A5A5A5", "4 c #8C8C8C", "5 c #A1A1A1", "6 c #FFFFFF", "7 c #F2F2F2", "8 c #C3C3C3", "9 c #F1F1F1", "0 c #C9C9C9", "a c #242424", "b c #9C9C9C", "c c #3C3C3C", "d c #5D5D5D", "e c #575757", "f c #747474", "g c #494949", "h c #464646", "i c #C1C1C1", "j c #505050", "k c #989898", "l c #C2C2C2", "m c #646464", "n c #565656", "o c #606060", "p c #C0C0C0", "q c #A6A6A6", "r c #BFBFBF", "s c #BEBEBE", "t c #909090", "u c #2F2F2F", "v c #1F1F1F", "w c #727272", "x c #090909", "y c #7E7E7E", "z c #2C2C2C", "A c #868686", "B c #797979", "C c #6C6C6C", "D c #C8C8C8", "E c #CACACA", "F c #BDBDBD", "G c #8E8E8E", "H c #F0F0F0", "I c #C7C7C7", "J c #9B9B9B", "K c #3E3E3E", "L c #111111", "M c #656565", "N c #6B6B6B", "O c #F3F3F3", "P c #F8F8F8", "Q c #EFEFEF", "R c #D1D1D1", "S c #D2D2D2", "T c #CECECE", "U c #919191", "V c #B4B4B4", " ", " .................... ", " .++++++@++++++++++#. ", " .+$%&*%=-;>,')!~{]^. ", " .+/(_:<=%[}<%;|;1]^. ", " .+-----=------]]]]^. ", " .2!===34!!5%%55555'. ", " .677777877777779990. ", " .6abcd78@ef7gh@ijk0. ", " .6@77778l@emlmno990. ", " .677777877777799990. ", " .-plll8qppplirspprt. ", " .677777l77777999990. ", " .6uvwxyl7zfA9Bmdi90. ", " .6fAyl7i7fC9@tt999D. ", " .699977i9999999999]. ", " .Espppi=sssppFFssFG. ", " .699999p999999999HI. ", " .6JKLMir9cgmt|iNJHI. ", " .699OP9F9999999HHH0. ", " .QRRRSTU---]]]IEEDV. ", " .................... ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/deldecimal.xpm0000644000076500007650000000140511350032206016253 00000000000000/* XPM */ static char * deldecimal_xpm[] = { "24 24 3 1", " c None", ". c #000000", "+ c #314E6C", " ", " ", " ", " ", " .. .. ", " . . . . ", " . . . . ", " . . . . ", " . . . . ", " . . . . . ", " . .. .. ", " ", " ++ ", " .. ++ ", " . . + ++ ", " . . ++ ++ ", " . . +++++++++++ ", " . . +++++++++++ ", " . . ++ ", " .. + ", " ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/dice.xpm0000644000076500007650000001244411350032206015101 00000000000000/* XPM */ static char * dice_xpm[] = { "24 24 257 2", " c None", ". c #000000", "+ c #120A09", "@ c #9E5649", "# c #D87C67", "$ c #DA8270", "% c #D9806D", "& c #CD6F5E", "* c #A94E43", "= c #130806", "- c #1E100C", "; c #BA6254", "> c #D7806E", ", c #D88270", "' c #D77C6B", ") c #D88271", "! c #DB8874", "~ c #D8846F", "{ c #C35F50", "] c #874338", "^ c #B17A71", "/ c #D67B67", "( c #DA8371", "_ c #D87B6C", ": c #C97766", "< c #D88373", "[ c #D9796A", "} c #D97E6D", "| c #D77E6B", "1 c #A85349", "2 c #69362F", "3 c #1E0D0B", "4 c #CE9B93", "5 c #D67C69", "6 c #D98573", "7 c #D98372", "8 c #473B25", "9 c #D5C8A2", "0 c #D77B6C", "a c #DE8373", "b c #D57E6B", "c c #A95542", "d c #703630", "e c #813E33", "f c #D6BDB6", "g c #D57A64", "h c #DB8572", "i c #D87E6F", "j c #D88171", "k c #D98272", "l c #DD806E", "m c #D47B66", "n c #944034", "o c #372823", "p c #994E43", "q c #CFBFBA", "r c #D58578", "s c #D77B67", "t c #DC8773", "u c #DA8674", "v c #DA8070", "w c #D98271", "x c #DC836F", "y c #BD614E", "z c #6B302B", "A c #31332D", "B c #954437", "C c #A64E42", "D c #AC5E52", "E c #CE968F", "F c #C56558", "G c #CE6E5E", "H c #D57965", "I c #D1725F", "J c #BB594A", "K c #AD524D", "L c #3D382F", "M c #231914", "N c #7D6D47", "O c #ECCFAD", "P c #D88672", "Q c #D8987C", "R c #632B21", "S c #783636", "T c #6D2D32", "U c #733134", "V c #702F2F", "W c #8B4139", "X c #9D4539", "Y c #AF4A3E", "Z c #AC524A", "` c #994841", " . c #414139", ".. c #C36F61", "+. c #C67565", "@. c #784B3B", "#. c #BDAF85", "$. c #D67D6A", "%. c #090403", "&. c #6A342D", "*. c #6F2E32", "=. c #652C2D", "-. c #692932", ";. c #652A2F", ">. c #6B302F", ",. c #793733", "'. c #A1453A", "). c #654036", "!. c #D19577", "~. c #DC8272", "{. c #1E0E09", "]. c #5D2B25", "^. c #672E2D", "/. c #642B2D", "(. c #5B262C", "_. c #58232A", ":. c #6C2A34", "<. c #7D3D33", "[. c #50352C", "}. c #C26F5B", "|. c #96875E", "1. c #D79782", "2. c #D57F70", "3. c #BFA677", "4. c #DD8270", "5. c #381814", "6. c #572520", "7. c #5D2A27", "8. c #542828", "9. c #5C2E2D", "0. c #743D32", "a. c #140806", "b. c #D67B66", "c. c #D77E6E", "d. c #726544", "e. c #CF8470", "f. c #070505", "g. c #5F362C", "h. c #A7614F", "i. c #9B5549", "j. c #6B352E", "k. c #140807", "l. c #35342F", "m. c #89554B", "n. c #D17664", "o. c #A0825A", "p. c #E09781", "q. c #D87B6B", "r. c #DA856F", "s. c #CC6F5D", "t. c #9C4639", "u. c #1B0D09", "v. c #151716", "w. c #8A4D40", "x. c #D17965", "y. c #D8806E", "z. c #54492F", "A. c #B68C75", "B. c #D67A6B", "C. c #8B5847", "D. c #D8CA97", "E. c #D77863", "F. c #AA5A51", "G. c #21110D", "H. c #343835", "I. c #040201", "J. c #CFA199", "K. c #D77D6E", "L. c #D77A6B", "M. c #D87E6E", "N. c #C67162", "O. c #825D48", "P. c #D67F6D", "Q. c #A35040", "R. c #7F3933", "S. c #1F2120", "T. c #693027", "U. c #D0A8A0", "V. c #C7705D", "W. c #B6A672", "X. c #DE927F", "Y. c #D87F6F", "Z. c #D88070", "`. c #DE8371", " + c #D77865", ".+ c #A34B3A", "++ c #52312B", "@+ c #834137", "#+ c #CFB9B4", "$+ c #D3715E", "%+ c #73523D", "&+ c #D37E6D", "*+ c #D98171", "=+ c #BC7164", "-+ c #AD9D6C", ";+ c #E49F87", ">+ c #CC745D", ",+ c #80342E", "'+ c #31302A", ")+ c #A04E42", "!+ c #C49E98", "~+ c #E2C8C5", "{+ c #D57F6E", "]+ c #D87B67", "^+ c #D9826E", "/+ c #D98771", "(+ c #B26554", "_+ c #D77C67", ":+ c #A94C41", "<+ c #46302A", "[+ c #34332E", "}+ c #883B2F", "|+ c #95463F", "1+ c #833B37", "2+ c #8E443A", "3+ c #A65244", "4+ c #B25346", "5+ c #B85649", "6+ c #B35043", "7+ c #BB5348", "8+ c #A7514C", "9+ c #3F3E36", "0+ c #232522", "a+ c #421E15", "b+ c #713332", "c+ c #722E35", "d+ c #692C30", "e+ c #702A34", "f+ c #703130", "g+ c #7A3532", "h+ c #9C463A", "i+ c #A84840", "j+ c #7B433A", "k+ c #393E39", "l+ c #723527", "m+ c #622B2A", "n+ c #682D2E", "o+ c #682B30", "p+ c #5F262D", "q+ c #662B30", "r+ c #62252F", "s+ c #8B4237", "t+ c #583C32", "u+ c #3B413E", "v+ c #3F1C16", "w+ c #622B26", "x+ c #66302D", "y+ c #5A272B", "z+ c #502128", "A+ c #6A2E33", "B+ c #703931", "C+ c #552C25", "D+ c #201513", "E+ c #27100D", "F+ c #301411", "G+ c #371B16", "H+ c #2B130E", " . . ", " + @ # $ % & * = ", " - ; > , ' ) ! ~ { ] ", " ^ / ( _ : < [ } | 1 2 ", " 3 4 5 6 7 8 9 0 a b c d ", " e f g h 7 i j k l m n o . . ", " p q r s t u v w x y z A + @ # $ % & * = ", " B C D E F G H I J K L M ; > N O ) P Q { ] ", " R S T U V W X Y Z ` .^ / ( ..+.< @.#.$.1 2 ", " %.&.*.=.-.;.>.,.'.).3 4 5 !.7 8 9 0 ~.b c d ", " {.].^./.(._.:.<.[.e f }.|.1.i 2.3.4.m n o ", " 5.6.7.8.9.0.a.p q r b.t u c.d.e.y z A ", " f.g.h.i.j.k.. B C D E F G H I J K L l.", " m.n.o.p.q.r.s.t.u.R S T U V W X Y Z ` .v.", " w.x.y.z.A.B.C.D.E.F.G.&.*.=.-.;.>.,.'.).H. ", " I.J.$.7 K.L.M.N.O.P.Q.R.{.].^./.(._.:.<.[.S. ", " T.U.V.W.X.Y.Z.Z.`. +.+++ 5.6.7.8.9.0.a. ", " @+#+$+%+&+*+=+-+;+>+,+'+ . . . ", " )+!+~+{+]+^+/+(+_+:+<+[+ ", " }+|+1+2+3+4+5+6+7+8+9+0+ ", " a+b+c+d+e+f+g+h+i+j+k+. ", " l+m+n+o+p+q+r+s+t+u+ ", " v+w+x+y+z+A+B+C+ ", " D+E+F+G+H+ "}; gambit-0.2010.09.01/src/gui/bitmaps/efg.ico0000644000076500007650000000137611350032206014706 00000000000000 è( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøˆˆÿÿÿÿÿÿÿÿÿÿÿÿªªªÿÿÿÿÿÿÿÿÿÿÿúªªªÿÿÿÿÿÿÿÿÿˆˆˆªÿÿÿÿÿÿÿÿÿÿÿù™"ª¨ÿÿÿÿÿÿÿÿÿÿÿ™™"ª¨ÿÿÿÿÿÿÿÿÿùŸÿ"ªˆˆˆÿÿÿÿÿÿ™ÿÿ"ÿúªªªÿøˆˆÿùŸÿÿ÷ÿªªªÿÿ™™˜ˆ™ÿÿÿ"ÿÿÿÿÿù™™Ÿ™˜ÿÿÿ"ÿÿˆˆˆ™ÿÿÿ™˜ÿÿ"ÿúª¡˜ÿÿÿÿ™ˆÿÿ"ÿÿªª¡˜ÿÿÿù˜ÿ÷ú¯ÿñ™ˆˆˆÿÿ™ˆÿ"ªÿÿÿwù™™˜ÿÿù˜ˆ"z¯ÿÿñÿ™™Ÿÿÿÿ™™"ªÿÿñÿÿÿÿÿÿÿù™"ªˆÿÿñÿøˆˆÿÿÿÿÿÿú¨ÿñÿ™™˜ÿÿÿÿÿÿÿªˆÿÿwù™™Ÿÿÿÿÿÿÿÿú¨ˆ™ÿÿÿÿÿÿÿÿÿÿÿªª¡˜ÿÿÿÿÿÿÿÿÿÿÿúª¡˜ÿÿøøˆˆÿÿÿøˆˆ™ˆˆˆñÿÿù™™˜ÿÿÿñÿÿÿÿ™™Ÿÿÿˆˆñˆˆÿÿÿÿÿÿÿñÿñÿÿÿÿÿÿÿÿñÿÿÿÿÿÿÿÿÿÿˆˆñˆˆˆˆÿÿÿÿÿÿñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgambit-0.2010.09.01/src/gui/bitmaps/exit.xpm0000644000076500007650000000672411350032206015152 00000000000000/* XPM */ static char * exit_xpm[] = { "24 24 140 2", " c None", ". c #000000", "+ c #D6D6D4", "@ c #BDBDBC", "# c #A8A8A4", "$ c #92928F", "% c #727370", "& c #61615E", "* c #20201F", "= c #F1F1EF", "- c #E6E6E4", "; c #DADAD7", "> c #CFCFCD", ", c #C4C4C1", "' c #A8A8A5", ") c #767674", "! c #777774", "~ c #1E1E1D", "{ c #B9B9B7", "] c #AEAEAC", "^ c #8F8F8D", "/ c #262626", "( c #414140", "_ c #E9836C", ": c #DEDEDC", "< c #C5C5C2", "[ c #636362", "} c #040504", "| c #040604", "1 c #050705", "2 c #E87B62", "3 c #E67056", "4 c #D5D5D3", "5 c #DBDBD8", "6 c #D0D0CE", "7 c #080A07", "8 c #0A0C09", "9 c #0A0D09", "0 c #0B0E0A", "a c #F0B0A1", "b c #EB8D77", "c c #DF421E", "d c #E97E66", "e c #CBCBC8", "f c #0C0F0B", "g c #0F130D", "h c #10140E", "i c #11150F", "j c #EFA392", "k c #BFBFBD", "l c #5D5D5C", "m c #10150F", "n c #141912", "o c #161C14", "p c #171D15", "q c #B7B7B4", "r c #0C0C0C", "s c #192017", "t c #1C2319", "u c #1D241A", "v c #CD8484", "w c #990000", "x c #701616", "y c #A6A6A5", "z c #181E16", "A c #1E261B", "B c #212A1E", "C c #222B1F", "D c #4F0000", "E c #AEAEAB", "F c #1D261B", "G c #242E21", "H c #273224", "I c #283325", "J c #580000", "K c #B5B5B3", "L c #293426", "M c #2D3929", "N c #2E3A2A", "O c #7C4343", "P c #6A0000", "Q c #720000", "R c #BDBDBB", "S c #232C20", "T c #2A3526", "U c #303C2B", "V c #33402E", "W c #C5C5C3", "X c #1E261C", "Y c #303D2C", "Z c #374532", "` c #394834", " . c #500000", ".. c #CDCDCB", "+. c #1B2319", "@. c #253022", "#. c #303E2D", "$. c #394934", "%. c #3D4E38", "&. c #9D9D9B", "*. c #565655", "=. c #2C3828", "-. c #40503A", ";. c #43553E", ">. c #BABAB7", ",. c #777776", "'. c #323830", "). c #232C1F", "!. c #313E2D", "~. c #3B4A36", "{. c #43553D", "]. c #485B42", "^. c #4A5E44", "/. c #F0F0EE", "(. c #E5E5E3", "_. c #C6C6C3", ":. c #ACACAB", "<. c #8B8B8A", "[. c #32392F", "}. c #2C3728", "|. c #3F503A", "1. c #465840", "2. c #4B5E44", "3. c #4E6347", "4. c #506549", "5. c #DADAD8", "6. c #7A7D78", "7. c #333C30", "8. c #475A41", "9. c #4F6348", "0. c #53694C", "a. c #566C4E", "b. c #576D4F", "c. c #91968F", "d. c #3B4736", "e. c #42543C", "f. c #51674A", "g. c #586F50", "h. c #5B7353", "i. c #5C7454", " ", " . . . . . . . . . . . . . . . . ", " . + @ # $ % & & & * . . . . . . ", " . = - ; > , ' ) ! ~ . . . . . . ", " . . = - ; > , { ] ^ / . . . . . . ", " . . . = - ; > , { { { ( . . . . . . ", " . _ . : - ; > < { { { [ } | 1 1 1 . ", ". . . . . . 2 3 . 4 5 6 < { { { [ 7 8 9 0 0 . ", ". a 2 2 2 2 b c d . e 6 < { { { [ f g h i i . ", ". j c c c c c c c 3 . k < { l { [ m n o p p . ", ". j c c c c c c c c 3 . q { l r [ n s t u u . ", ". v w w w w w w w w w x . y r { [ z A B C C . ", ". v w w w w w w w w D . E { { { [ F G H I I . ", ". v w w w w w w w J . K < { { { [ C L M N N . ", ". O P P P P Q w J . R 6 < { { { [ S T U V V . ", ". . . . . . Q J . W 5 6 < { { { [ X H Y Z ` . ", " . .. ..- 5 6 < { { { [ +.@.#.$.%.. ", " . . . = - 5 6 < { ] &.*.B =.Z -.;.. ", " . . = - 5 6 >.&.,.'.).!.~.{.].^.. ", " . /.(._.:.<.[.}.Z |.1.2.3.4.4.. ", " . 5.k 6.7.Z -.8.9.0.a.a.b.b.b.. ", " . c.d.e.^.f.g.h.i.i.i.i.i.i.i.. ", " . . . . . . . . . . . . . . . . ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/font.xpm0000644000076500007650000000314611350032206015142 00000000000000/* XPM */ static char * font_xpm[] = { "24 24 61 1", " c None", ". c #8F814C", "+ c #6D6239", "@ c #52492B", "# c #6A5D38", "$ c #37311D", "% c #000000", "& c #010101", "* c #9E8E54", "= c #322C1A", "- c #70653B", "; c #463F24", "> c #645A35", ", c #0E0C07", "' c #6B6139", ") c #1B180D", "! c #50482B", "~ c #2C2818", "{ c #302B1A", "] c #595030", "^ c #252112", "/ c #292516", "( c #1E1B10", "_ c #5F5532", ": c #70643B", "< c #827544", "[ c #3D3721", "} c #292416", "| c #2C2717", "1 c #252114", "2 c #413922", "3 c #3E3721", "4 c #5C5331", "5 c #1A170E", "6 c #1E1A10", "7 c #403922", "8 c #584F2F", "9 c #16140C", "0 c #312B1A", "a c #0F0D07", "b c #2D2818", "c c #322D1A", "d c #231F11", "e c #3C3620", "f c #5A5230", "g c #332E1B", "h c #12100A", "i c #4F472A", "j c #413A23", "k c #302B19", "l c #342E1B", "m c #4A4227", "n c #6E633A", "o c #080704", "p c #2F2919", "q c #4C4529", "r c #51472B", "s c #242113", "t c #322D1B", "u c #5E5432", "v c #211E12", " ", " ", " ", " ", " .+@ ", " #$% & ", " *=% ", " -; >, ", " ' ) !& ", " ~ {% ", " ]^/ ({& _ ", " : / <[$ }|12 ", " 3 { 4&5 ", " 6 &7 8&9 (0 ", " abc de f&gb&hc ", " i&j k&l ", " m&/ 8&/ ", " m&/ 8&/ ", " m&9 nop ", " q&&rs5t ", " u/v pj ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/gambit.bmp0000644000076500007650000013201411350032206015406 00000000000000BMþ³6(,–&9"')'o'i „ „1k^cJUMXgs„„ Š –"9OUZ”ePŒrkŒksˆsk”k{„„„s”ssœs“¯&6¥BB¬ÊÍ33È99ÎAPšCOÇZZœSS¶ccccœZZ½Wwoo`q­ƒŒ„œ„~€¦|€Ä””””œ”””œœœœ••©µÅ¥µ ¶ Ê Ì Ø Þóïçï÷÷ÿÿ¾!-»6æ+å.ÿü%÷)-û/B­FO­O[­[N½NIàIEÿEZûZl°y‹¬˜rØv•Öšmûo…û…”ù–œÿœ¥¥©­­­¤¦Ã­µ­œ½½§Ó¬§ü§·ººµµÆºÇ½½½Ë½ÊÎÆÎÆÎÎηعÁØÅÁêÁµÿµÁûÁÆÿÆÎÿÎÞçÞ âçïïïï÷÷÷ÿÿÿÚçï))Ö11Ö!!Þ))â!!ï))ï÷!!÷))÷ÿ!!ÿ))ÿ>>Þ33ñCDñ11ÿ==ÿJJ÷JJÿPTâggÚbbíRRÿ^^ûccÿkk÷xxÝ‚‰Üuuñ‚†ñkkÿssÿÿŒŒû——ܪ­Ø  ï””ÿœœÿ­­÷©©ÿZÞÞµºáµ»ð½½Ö½½æ½½÷µµÿÆÆÖÆÆæÎÎÚÎçÖÆÆ÷½½ÿÆÆÿÎÎçÎÎïÎÎ÷ÎÎÿÖÖÖÖÞÖÖçÖÖïÖÖ÷ÖÖÿÖÖÖÞÖïÞÖ÷ÞÖÖçÖççÖÖïÖÖ÷ÖÖÿÞÞÞÞçÞÞïÞÞ÷ÞÞÿÞÞÞçÞÞïÞÞ÷ÞÞÿççççïçç÷ççÿçççïçïïçç÷ççÿïïïï÷ïïÿïïï÷ï÷÷ïïÿ÷÷÷÷ÿ÷÷÷ÿ ¿¿¿¿¿¿¿¿¿ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÑÃnha74ôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôô447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûééäÕÕÕÈuurof\\ZYY447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûäÕÈusrg`_^^[[[[UUUSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSST447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÕÈsrg^^]XXXWVVVMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMKRSST447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕsr`^]XWOOOOOOOGEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEELMKRST447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûééééäÕur`^]WQOööööööööööööööööööööööööööööööööööööööööööööööööFLMKUT47ahóÃÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéäÕÕÈussr`^]]WWONööööööööööööööööööööööööööööööööööööööööööööööööGMMVUYYZ7ahhóÃÑÑÚûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕÕusrg_^^]]XWQQOIööööööööööööööööööööööööööööööööööööööööööööööööGPVV[[\djónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕurg^^]XWWQQOONIöööööööööööööööööööööööööööööööööööööööööööööööööOQWX[\foÄÑÑÑÚÚèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûäÈsg^]XWONNIIIIöööööööööööööööööööööööööööööööööööööööööööööööööööOQX]^`rÇãèèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèèèèÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚãããÓÓÕÕÕÕur`^]XWOIööIIINNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOWX]^`ruÕûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÚÚÑÑÑÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃnnqoqorgg`^]]XWQOIöINOQQWWWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX]^^grsÈäûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÚÑÑÃnóhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdf\\\^^]]XWWQQONööNOQWX]]^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^`grsuÈÕäûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÑÑÃóhh7777777777777777777777777777777777777777777777777ZZY[[VVWWQQQOONNIööOQWX]^`rssssssssssssssssssssssssssssssssssssssssssssssssuÈÕÕÕäééûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÚÑÃóha74ôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôSUKMLEööööööööööIOWX]_gsÕûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûååáÙÐÐе²«c:322++++++++++**...TSRKMLLFöööBFFEEELLVX]^`ruÕûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåáÐж·®®­©¥¢¢œœ,,)))))))))))&&(SSSSSSSSSSSSSSRKKMLLEFööFEELLLMKKV[[\gqÇäûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåÙж°®©¨¦Ÿž››”””%‰‰‰‰‰‰‰‰‰‰$ && KKKKKKKKKKKKKKKKMLLLEEFöööFLLMKKRSTY[\foqÓãûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûáн°­¨ š—“’’ŒŒŒ††††††††††††…# ;==??ALEEEEEEEEEEEEFFFBöööFELMKRST1ZdfjnÅãûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåååååн°­§Ÿ˜“õõõõõõõõõõõõõõõõõõõ|# ;<î>@BööööööööööööööööööööFLLKRSTô47ahóÃÑÚûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåááÙÐн¶°®¨§Ÿ˜—Žõõõõõõõõõõõõõõõõõõõ|# ;<î>@BööööööööööööööööööööFLLKRSTô447ahhnÃÑÑÑÑÚÚèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåÙж°®­¨¨¦Ÿš˜—’‘õõõõõõõõõõõõõõõõõõõ|# ;<î>@BööööööööööööööööööööFLLKRSTô44477ahhónnÃÑÑÚÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûáн·®©¨ žš˜—“’Ž‘õõõõõõõõõõõõõõõõõõõõ|# ;<î>@BööööööööööööööööööööFLLKRSTôô44447777hhónÃÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÙ·®¨ š—Ž‘‘‘õõõõõõõõõõõõõõõõõõõõõõ|# ;<î>@BööööööööööööööööööööFLLKRSTôôôôôô444447hhnÃÑÚûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåååááÙÙн°­¨ š—Žõõõ‘‘ŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŒˆ ;==??LGGOOOOOOOOOONNNIIöööFELMKRSTô447ahóÃÑÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚèèèèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåáÐн¶·°­¨§Ÿš˜“‘õõŽ’“—˜˜šžžžžžžžžžžžžžžžžžžž›''& ;JJKKMVVVVWWWWXXXWWWQOONIööELLMKKRSSTô4477ahhnÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÃÑÑÑÚÚèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåáж°®©¨§ Ÿš˜—’ŽõŽ“—˜ž §¨©©©©©©©©©©©©©©©©©©©¥£/-KKRUU[[[[[^^^^^^^]XWWQONööFELLLMKKKRSSTôô44777ahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhónÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåз®©¨ š˜—““’Ž‘õõ’˜š §©®·½½½½½½½½½½½½½½½½½½½³«eZYRSTY[\\\\ffgorssg_^]XWQOöööFFEEELLLMKRSSôôô4444477777777777777777777777777777777777777777777777777ahónÑÑÚûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåж®¨¦ž—Žõõõõõõõõõõ‘“˜ ¨­·ÂÙûûûûûûûûûûûûûûûûûûûß»o\YTSYZZhjmnÄÄÅÛãééÕsg^]XWOööööööööööFELKKSTôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôô477hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûååáÙÙÐÐн°­¨¦ž˜“‘õõ‘ŽŽ’““˜ž¦¨®°½ÐåûûûûûûûûûûûûûûûûûûûãÅo\YTSZdónÃÑÑÑÚÚèûûÕusg^]]WQQOOONNIIööELLKKRST447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèèèÚÚÚÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåáÐж·°®­¨§Ÿš˜“Žõ‘’“—˜šŸ §¨­®·½ÐÙåûûûûûûûûûûûûûûûûûûûãÅo\YTSRTYZdfnÑÑÑÑÚÚèèûûäÕusg`^^]XXWWQOONööFELLMKKRSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTT447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÚÑÑÑÃÃnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåж°®©¨¦Ÿžš˜—“Ž‘õ‘’—˜ž §¨®®°¶½ÂÐÙáûûûûûûûûûûûûûûûûûûûûãÅo\YTSRTYZfpÅÑÚÚÚèèèûûûéäÕÈusrg`_^]XWWQOIöBFELLLLMKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKRSST447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÚÑÑÃnóhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhûûûûûûûûûûûûûûûûûûûûûûûûûûûûûáж®­¨ š—“’’Ž‘‘õõŽ“˜Ÿ§©®·ÂÐÐÐÙááååûûûûûûûûûûûûûûûûûûûûãÅo\YTSSTY\opÛèèèûûûûûûûûééäÕÕÕÕÈsg_^]XWOIöööBFFFEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEELLMKRST447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÑÑnóha744444444444444444444444444444444444444444444444ûûûûûûûûûûûûûûûûûûûûûûûûûûåååн°©§Ÿ˜’õõõõõõõõ’˜Ÿ§©°½ÐûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YYSTYYfoÅãûûûûûûûûûûûûûûûûûûûäÈr`^]WQOIIöööööööööööööööööööööööööööööööööööööööööööööööööööööööELMKUSô47ahónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûååååÚ̸iha64ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûåááÙÐн¶°®¨¦Ÿ˜—Žõ‘ŽŽ’“—˜˜ž¦¨­°¶ÐÙûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÓpof\YTSRRRRRRTYY\fjÄÛÚèèèèûûûûûûûûûûûûûûéÕsr`^]]WWQQQOONIöööööööööööööööööööööööööööööööööööööööööööööööööGMMVUYYZ77hhónÑÑÚûûûûûûûûûûûûûûûûûûûûûåáÙÐÐн¶³«ª::33/+((((((((((((((((((((((((((((++.....ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûáÙж°®­©¨¦Ÿš˜—’‘õõ‘Ž“˜˜žŸ¦§¨­®·½ÂÐáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÓÓpof\\ZYYYYYTTTYZZdfjnÑÑÑÚÚÚèèûûûûûûûûûûûûéÕÈusg`^^]]XWWQOOIööööööööööööööööööööööööööööööööööööööööööööööööGPVV[[\dhhónÃÑÑÚèûûûûûûûûûûûûûûûûûûûûåáÐн·°®­¨¤¤¤œœœ''!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)))(+...ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûÙн·®©¨ žš˜˜“’Ž‘õŽ“˜ž §©®°·¶ÂÐÐÙáåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÓÓÅpqoofffddZZZZ1ZZZdfjjmnÃÑÑÑÚÚèèûûûûûûûûûûûûäÕÕÈussrg_^]XWQONööööööööööööööööööööööööööööööööööööööööööööööööOQWX[\foÃÑÑÑÑÚÚèèûûûûûûûûûûûûûûûûûûûûåÙ¶°­¨§Ÿžš––––•‰‹ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ$%!))(+.ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûÙ°­¨ š—ŽŽ‘‘õõõ’˜ž¦¨®·ÂÙÙáááååûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéééãããÓÛÓÄÄnpjjhddhhhjjjóónnÃÑÑÑÚèûûûûûûûûûûûûûéééäääÕÕsg_^]WQNööööööööööööööööööööööööööööööööööööööööööööööööOQW]^`rÇãèèèèûûûûûûûûûûûûûûûûûûûûûûûûáж®©§Ÿ˜“ŽŽ‘‘‘ŽŽŽ†Š$%!)+.ôôôôôôôôôèèèèèèèèèèèåååáááÙÙн°­¨ š—Žõõõ‘‘‘Ž’˜ž¦©®¶ÐáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéééãããÓÛÓÄÄnpjjhdddhhhhhhhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûéÕsg_^]WQOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOQW]^_guÕûûûûûûûûûûûûûûûûûûûûûûåååáááÙж®©§Ÿ˜“‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ†‹%',/20444444444ÃÃÃÃÃÃÃÃÃÃɺ¹¹¹µ¶³·°­¨§Ÿš˜’‘õõ‘Ž’“—˜˜šŸ¦¨­®·ÂÐáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÓÓÅpqoofffddZZZZ1ZZZZdddhhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûÕÈsg`^]]XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX]^^`rsÈÕûûûûûûûûûûûûûûûûûûûûåáÙÐн¶·®©¨¦ž˜—Žõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ†•”›œ39aaaaaaaaaahhhhhhhhhhhic«ªª¥¥¨§ Ÿš˜—’ŽõŽ“˜˜ž §¨©®®·½ÂÐÙåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÓÓpof\\ZYYYYYTTT1ZZddhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûäÕÈssgg_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_ggsuÈÕäûûûûûûûûûûûûûûûûûûûûåÙн·®®©¨¦ žš˜“’‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ–›œ¢£cióóóóóóóóó777777777789333œ›–˜˜—“’Ž‘õõ‘’˜š §©®·½ÂÂÐÐÙáåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÓpof\YTSRRRRRZZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûéäÕÕÕÈussssssssssssssssssssssssssssssssssssssssssssssssssuÈÕÕääéûûûûûûûûûûûûûûûûûûûûáн°®¨§Ÿ˜˜—“’’Ž‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ‘“–¤¥ª²¹ÑÑÑÑÑÑÑÑÑôôôôôôôôôô.+)'%‹ŠŽõõõõõõõõ‘—𠍮·ÂÙåååûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YYSRZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûééééééééééééééééééééééééééééééééééééééééééééééééééééûûûûûûûûûûûûûûûûûûûûûûûûûûÙ·­¨ ˜“‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ‘“𠍮·Âáûûûûûûûûû..........+()!‰ˆŠ†õõõ†††–¤©¬½ÐåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèèèÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚ×ØØØÐÐж®©¨ š—Žõõõ‘‘ŽŽ’“““““““““““““““““““““““““““““““““““““““˜ž¦¨­°½Ðåûûûûûûûûû)))))))))))!%$ˆŠ†õõõ†††ŠŠˆ‰%œ¢£ª³¼ØåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèèÚÑÑÑÃÃnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn¸¹´²³¯¬®®©¨¦Ÿš—’‘õõ‘Ž’—˜˜žŸ                                      ¦¨©®·½ÐÙåûûûûûûûûû‰‰‰‰‰‰‰‰‰‰$ˆŠŠ††~õõ††Šˆ‰%!),/3:«²¿×åûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÚÑÑÃnóhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhbcc:££¢¤¡ Ÿš˜˜“’ŽõŽ“˜šŸ¦¨©®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®°·½ÂÐÙáûûûûûûûûûû†††††††††††††õõõ†Š$%!)(+229ci¹ÌÚåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÚÑÃnóha7444444444444444444444444444444444444444444444446223,œ›––““’’Ž‘‘õõ’˜š ¨­°¶ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÐÐÐÙÙáååûûûûûûûûûûõõõõõõõõõõõõõõõõõõõõ††ˆ%!)+.477hhnÑÑèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÛÄmjd75.()!‰ˆ†õõõõõõõõõõ‘“𠍮·Âáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõõõõõõõõõõõ††ˆ%!)+.4477hhóÃÑÑÑÚÚÚèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéäÕÕÈÈussof\\YYY***************++++())%‰ˆŠ†õõõ†††††‹”¤¥¬¶Ðáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõõõõõõõõõõõ††ˆ%!)+.ô4477ahhónnÃÑÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕÕusrg`^^^[[[[UUURRRRRRRRRRRRRRRRRRRRS&&&&&&&&&&&&&&&!!!!!%‰ˆŠ††~õõ†††Šˆ‰$%,¢£ª²¹Øáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõõõõõõõõõõõ††ˆ%!)+.ô44447777ahónÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûäÕurg_^]XXWWVVVMMMMMMMMMMMMMMMMMMMMMMKKK $$$ˆŠŠ†††õõ††Šˆ‰%))/33:«´¹×åûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõõõõõõõõõõõ††ˆ%!)+.ôôôôô444447ahóÃÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdhónÃÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÕur`^]XWOOOOOGGGGGEEEEEEEEEEEEEEEEEEEDJJ ##xyõõõõõ†Š$%))+.029ci¸ÉÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû‘‘‘‘‘‘‘‘‘‘‘‘‘õõõõ~†ˆ‰!)(+....ô47ahónÑÚèèèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSZdjnnÃÑÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûéééäääÕur`^]XWOIööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ô47ahóÃÑÚèèèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûššššššššššš˜˜—’Ž‘õõ†Šˆ‰%!)((++....ô447ahhónÑÑÑÑÚÚèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSRTYZdjmÃÑÑÑÚÚèèûûûûûûûûûûûûûûûûûûûûûéäÕÕÈussr`^]]XWQOöööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ô477ahhóÃÑÑÑÑÚÚèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¨¨¨¨¨¨¨¨¨¨¨¦Ÿž˜—’Žõ††Šˆ$‰%!))(++..ô44477ahhhónÃÑÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSRTYZdjÄÑÑÚÚÚèèûûûûûûûûûûûûûûûûûûûûûûäÕusrg_^^]]XWWQONöööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ô44477ahhhónÃÑÑÚÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¶¶¶¶¶¶¶¶¶¶°®¨§Ÿš—’õõ~††††Šˆ‰%))(+.ôô44444777ahónÃÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSSTY\fpÛÚèèèèèûûûûûûûûûûûûûûûûûûûûûûéÕusg_^]XWWQQOOONIöööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ôô44444777ahónÃÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûååååååååååÙ½°­¨Ÿ˜“‘õõõõõõõõõõ†Šˆ%!)+.ôôôôôôôôôô47ahnÃÑÚûûûûûûûûûûûûûûûûûûûûûûûûûûûûûãÅo\YTSSTZ\oÄãûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕsg^]XWOIIIIööööööööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ôôôôôôôôô447hhnÃÑÚûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåн°­¨ ž˜’’ŽŽ‘‘õõ†Šˆ$!)(+......ô447ahóÃÑÑÚÚèèèèûûûûûûûûûûûûûûûûûûûûûûèÓqf\YTTRTY\foÄÚèèèûûûûûûûûûûûûûûûûûééääÕÕÕÕur`^]XWQNööIINNOOOOQQQQQQQQQQQQQQQQQQQQQQQQQQQQPMK  ##ŠŒ’’ŽŽ‘‘õõ†Šˆ%!)(+......ô477ahóÃÑÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚûûûûûûûûûûåÙн·®©¨¦Ÿžš˜—“Ž‘õ~†Šˆ‰%!))((++...ô4477ahhónÃÑÑÑÑÚèèûûûûûûûûûûûûûûûûûûûûéÓÅpo\\YYTTTTTTYZdfjnÅÚÚÚèèèèûûûûûûûûûûûûéäÕÕussgg`^]]XWQONöINOQQWWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXVU $%”›Ÿž˜˜—“Ž‘õ††Šˆ‰%!))((++...ô4477ahhónnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnûûûûûûûûûûåáÙж·°®­¨§ ž˜—’‘õõ†††ŠŠˆ‰%!))(+..ôô444777ahhónÃÑÑÚèûûûûûûûûûûûûûûûûûûûûéãÓÅpoof\\\\ZZZYY1ZddjjnÃÑÑÑÑÚÚèèûûûûûûûûûûûéÕÈsrg_^]]XWWWQONIöIOQWWX]^^_____________________________\YY--&  !',œ¥©©¨¦Ÿš˜“Žõõ†††Šˆˆ‰%!))(+..ôô44477aahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhûûûûûûûûûûûååáÙÙÐн·®¨¦Ÿ˜“Žõõõ~††††ˆ‰%))+..ôôô44444477ahónÃÑÚèûûûûûûûûûûûûûûûûûûûûéèãÓÛÓÅpppojfffddZZdddjjjmnnÃÑÑÑÚÚèûûûûûûûûûûûäÕsg_^]XWQQOOONNIööNQWX]^`gsuuuuuuuuuuuuuuuuuuuuuuuuuuuuqoe92+& !),3ª¯¶½°®¨¦ž˜“‘õõõ††††Šˆ‰!))+.ôôô44444477777777777777777777777777777777777777777777777ûûûûûûûûûûûûûûûûûûûûн®©§ž˜’õõõõõõõõõõõ†Š$%))+.447hhnÑÑèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÚÑÅÑÃnóhhhhhhhhhhónÃÃÑÑÚèûûûûûûûûûûûäur_^]WQIööööööööööOWX]^gsÕéûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/)   &/3c«Îååж®©¦ž˜Žõõõõõõõõõõ†Š‰%)(+.ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûÙ¶®­¨ ž˜—“’’Ž‘õõ~†Š$%!)(++.....ô477hhóÃÑÑÑÚÚÚèèûûûûûûûûûûûûûéããÓÓÅppqojoffddZZZZddddhhhónÃÃÑÑÚèûûééäÕÕÕÈusrg^]]WQOIöIINOOOQQWW]^^gruÕéûûûûûûûûûûûûûûûûûûûûûûûûûûûûå×¹«c:3/&! &&/2:c´ºÚåμ¯¬¨§ š˜—“’’Ž‘õõ††Š‰%!)(+++++++++++++++++++++++++++++++++++++++.....ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûáж°®­¨§ Ÿš˜—“Ž‘õõ††Šˆ‰%!!))(++..ô4477ahhónnÃÑÑÑÚèûûûûûûûûûûûéãÓÅqoff\\\ZZYYYY1ZZddhhónÃÃÑÑÚèûûéÕÕusrg`_^]]XWQOOIöNOQQWWX]]^^`gsuÕäûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåå×¹´«c:33/////((+((/2:cik¸ÑÖ̹µ¯¬©©¨§ Ÿš˜—“Ž‘õõ††Šˆ‰%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!))((+...ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûåáÙн¶·®­¨§ š˜“Žõ††††Šˆˆ‰%!)(+..ôô444777aahónÃÑÑÚèûûûûûûûûûûéÓÄof\\YTSSTTSRRR1ZZdhónÃÃÑÑÚèûûäÕsrg_^]XXWWQQOOIööOQWWX]^_ggssuÈÕäéûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûè××ι¹«««ccc::9222299ciikm¸Ãºº¹µµ³¯°®­¨§Ÿš˜“Žõõ†††ŠŠˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ‰%!))+..ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûûååáááÙÙз®¨¦ž˜’õõõõ~††ˆ‰!)(+.ôôôô4444447ahónÑÑèûûûûûûûûûûèÓpf\YTS1ZdhónÃÃÑÑÚèûûÕur`^]XWOOONNNIIöööOQW]^_gsÕÕÕÕääééûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåååå××Ú×Ì̺¸kkibcbbhhiiióón¸¸ºÌÌÎØÐн°­¨ š—’õõõõõ~†††††††††††††††††††††††††††††††††††††††Š‰%))+.ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûá·®¨¦ž˜Ž‘‘õõõõ†ˆ‰!)(+...ô47ahónÑÚèèèèèèèèèèÛpf\YTRZdhómnnÄÅÓÓÕäur`^]XQOöööööIIINNOQW]^`ruÕûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåååååååÚÖÌɸmkihhhhhhhhhhónnÃÑÑÚèûûÙ·®¨ š—Ž‘‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ†Š‰')/.0444444444ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûáн·®©¨ ž˜˜—“’Ž‘õõ††ˆ‰%!)((++....ô447ahhónÑÑÑÑÑÑÑÑÑÑnfdZYTRZdhjjjjooorrr`^^]XWQNööINOOQQWWX]]^`rsÕäûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåå××ι¹´««cccc99999988abhhhónnÃÑÑÚèûûáн·®©§ ž˜˜—“’Ž‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ†‹”›,39a777777777ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåÙж·®­¨¨¦Ÿž˜—’Žõ††Šˆ$‰%!))(++..ô44477ahhhhhhhhhhhhhZZZdhjfff\\_^^^]]XWWQONöINOQWWX]^^_ggsuÈÕéûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåå×¹¹««::3333///++++22298abhónnÃÑÑÚèûûåÙж°®­¨¨¦Ÿš˜—’‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ•›œ¢£cióóóóóóóóóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåáÙÐн¶°®¨§Ÿš˜’‘õõ~†††ŠŠˆ‰%))(+.ôô4444777777777777771Zdhjf\\[[]XXWWQQOOONIöIOQWX]^_gssuÈÕÕÕäéûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåÚ¹´«:3/)!!&&!!&&& &&++298bhónnÃÑÑÚèûûåáÙÙÐн¶°­¨§Ÿš—’õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ‘“–ž¡¥ª²ºÑÑÑÑÑÑÑÑÑûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåååååáÙ½°­¨ š“‘õõõõõõõõ††ˆ%!)(.ôôôôôôôôô4444444444Zdhjf\[[VVQONIIIIöööööNQWX^_gsÕäéééééûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûå×´«:3)!  &(+29ahónnÃÑÑÚèûûûûûåååååáн°­¨Ÿ˜“‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ‘“˜ ¨­·¼×èèèèèèèèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåн°­¨¦ž˜’’ŽŽ‘‘õõ†Šˆ$!)(+....................RTTYZd\\[[VVMPIööööFFFFEEMVX]^gsÈäûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+298hónnÃÑÑÚèûûûûûûûûûûûåн°­¨ š—’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’—š ¨­°½ÐåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåÙн·®©¨¦Ÿž˜˜—“Ž‘õõ~†Šˆ‰%!))))))))))))))))))))&& KRSU[[[[VVVMPOIööFEELLLMMVV[[_gqÓéûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+298hónnÃÑÑÚèûûûûûûûûûûûåÙж°®©¨ ŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸŸ ¨©®°¶ÐÙåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûáÙж·®®­¨§ ž˜—’‘õõ~††Šˆˆ‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰$ & ;JKKKVVVVVMPPONööFELLMKKRRUY[\fo»Óéûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+298hónnÃÑÑÚèûûûûûûûûûûûåáÙж·®®­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­®®·¶ÂÐÙáåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûååáÙÐÐн°®¨¦Ÿ˜“Žõõõ†††††††††††††††††††††††…# ;==JLLMPPOOGNIIööFELMKRST1ZdfpÄÛèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+298hónnÃÑÑÚèûûûûûûûûûûûûåááÙÐÐÐÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÐÐÐÙááåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÙ½°©§Ÿ˜’õõõõõõõõõõõõõõõõõõõõõõõõõõõõõ|# ;<î>@BöööööööööööELMKRS447hónÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+298hónnÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÙж®­¨ ž˜—“’’Ž‘õõõõõõõõõõõõõõõõõõõõ|# ;<î>@BöööööööööööELMKRSô477hhóÃÑÑÑÚÚèèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+298hónnÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûèèÚÚÚÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûáж°®©¨§ Ÿš˜—“Ž‘õõõõõõõõõõõõõõõõõõõõ|# ;<î>@BöööööööööööELMKRSô4477ahhónÃÃÑÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+298hónnÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûèèÚÑÑÑÃnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåáÙн¶°®­¨§ ž˜“Žõõõõõõõõõõõõõõõõõõõ|# ;<î>@BöööööööööööELMKRSô4444777ahhónÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+298hónnÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûèÚÑÑÃnhhaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûååááÙÙÐз®¨¦ž˜’õõõõõõõõõõõõõõõõõõõ|# ;<î>@BöööööööööööELMKRSôôôô4444447ahóÃÑÑèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+298hónnÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûèÑÑnóha744444444444444444444444444444444444444444444444ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûáж®¨¦ž˜Ž‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‡… ;==??AENNIIIIöööööFLMKRSTô47ahóÃÑÚèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &&+29chónÃÑÑÑÚèûûûûûûûûûûûûûûûååååáá×̸iba80............................ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåз®©¨ ž˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜™›',/-RRRRRRRRRRRRRUVVVVWWWQQOONIööFELMKKRSTTô447ahhóÃÑÑÑÑÚÚèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &(/29imÃÑÑÑÑÚÚèûûûûûûûûûûûûåáÙÐн¶·¯¬ª£333/((((((((((((((((((((((((((((((++....ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåÙж°®­¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¥¥£::9ZZYYYYYYYYYYY[[[[[[^^^]]XWWQOOIöBFELLMKKKRSSTô44477ahhóónÃÑÑÚÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &(2:ckÉÑÑÑÚÚèèèûûûûûûûûûûûåáн·®®©¨¤¤¡œœ›''!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!))(++..ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåáÙÐн¶····················³³²´llooooooooooooooooorrrrg_^]XWQONööFFEELLLLMKRSSTôô44447777ahónÃÑÑèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&  &)3:c¹ÖÚÚèèèèûûûûûûûûûûûûûåж®­¨¦Ÿš˜–––••‹‹ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠˆ‰%))(+.ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûååååááááááááááááááááááááááááååååããããããããããããããäääääääÕsg_^]WQNöööööööBFFELMKRSTôôôôôôôô4447ahóÃÑÚûûûûûûûûûûûûûûûûûûûûûûûûûûûûûåδc3/&   &/3c«¹åûûûûûûûûûûûûûûûûûûûáж®©§Ÿ˜’‘‘‘‘†Šˆ%!)(.ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕsg_^]WQOOONNIIöööFELMKRSTô447ahóÃÑÚÚèèèèûûûûûûûûûûûûûûûûûûûûûûûå×¹«:3/&  &)3:c´ÌÚèèûûûûûûûûûåååááÙÙз®¨¦ž˜“‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ†‹%',/20444444444ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕÈsg`^^]XWWWQOONIööELLMKKRSSTTô4477ahhónÃÑÑÑÚÚèèûûûûûûûûûûûûûûûûûûûûå×ι«c:3/))((&&&&&&&+22:c´ºÖÚÚÚèèèèûûûåáÙн¶·°®©§ ž˜—Žõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ†•”›œ3:aaaaaaaaaaûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûäÕÈusrg`^^]XWWQONööFEELLMMKKRSSTôô44477aahhónÃÑÑÚèûûûûûûûûûûûûûûûûûûûûûåÚι´««c::332222/+2299cik¸ÃÑÑÑÚÚÚèèûûáÙн·®­¨§¦Ÿž˜˜“’‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ–›œ¢£«kóóóóóóóóóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéääÕÕÈÈusg`^]XWQOöööFFFEELLLMKRSSôôô44444777ahónÃÑÚèûûûûûûûûûûûûûûûûûûûûååå××Î̹¹´´«cicc8988cbiiimnnÃÑÑÑÚÚèûûáж°­¨¦ž˜—““’Ž‘‘õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ‘“–¤¥¬²ÌÑÑÑÑÑÑÑÑÑûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÕsg^]XWOöööööööööööELMKSTôôôôôôôôôô447hhnÑÑèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèÚÚÑÑÃnóihhhhiiióóónnÃÑÑÚèûûÙ°­§Ÿ˜’õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ‘“𠍮·ÐáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÕÈsg^^]WQQQOOONIIööELLKKRSTô477hhóÃÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÖÖÖÌÌ̹¹¹¹´iiicc88aabbhhhhómm¸¹¹¹¼Â·®©§Ÿš—Žõõ‘ŽŽ’““——————————————————————————————————————˜Ÿ¦¨®°½ÐåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûäÕusg`^^]]XWWQQONööFELLMKKRSSSTô4477ahhónnnnnnnnnnnnnnnnnnnmmkiicccc::::32222222298abhhiki«««¬¬®­¨§ ž˜—’‘õõ‘Ž“—˜šž ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦§¨­®·½ÐÙåûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéäÕÈusrgg_^]XWWQOIöBFEELLLMKKRSSTôô444777aaaaaaaaaaaaaaaaaaaaaaa9922//)))(((&&&&(++2298bhiicªªª¥¤¦Ÿžš˜—“’ŽõŽ“˜šŸ§¨­®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®®·¶½ÂÐÙáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûééääÕÕÕÈsg_^]XWOIöööBFFFEEELMKRSTôôôô44444444444444444444444440..+(&&  &&+229ahicc£¢œ–˜“’’Ž‘‘õõ’˜ž¦¨­°½ÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÙÙááååûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûäÈs`^]XQOIIIIööööööFLLKRST&   &(/29bic£¢œ›–‘õõõõõõõõõõ‘—𠍮·ÐáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕsr`^]]WWWQQOONIööFELMKKRSTTTTTTTTTTTTTTTTTTTTTTTTTTTTT   !),33£¢œ›–Œõõ††††Š‹”¤¥¬¶ÐáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕÕusg`_^]]XWWQOOIöBFELLMKKRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR   %''œœ››–••ŒŽõõ††Šˆˆ‰%',¢£ª²¹ØáûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕÕÈussrg_^]XWWONööFFEELLLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMKK  ˆ$‰•–••ŒŒ‘õõ††Š$%!))/33c«´¹×åûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûééééäääÕsg_^]WQNööööööBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDJJ  íí#xyŽ‘õõõõõ†Š‰%))+.06abi¸ÉÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéÕsg_^]WQOOONNIIöööööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ô47ahónÑÑÚèèèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÕÈsg`^^]XWWWQOONIöööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ô447ahhónÃÑÑÑÑÚèèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûäÕÈusrg_^^]XWWQONöööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ô44477aahhónÃÑÑÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûéääÕÕÈuusg`^]XWQOöööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ôô44444777ahhnÃÑÚèûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÕsg^]XWOIööööööööööööööööööööööööööööB@J  ííí"vwõõõõõõõõõõ†ˆ‰!)(.ôôôôôôôôôô47ahóÃÑÚûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûäÈsg^^]WQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQMKR && $$ˆ‹•““’ŽŽ‘õõ†Šˆ$!)(+......ô477ahónÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûäÕusg`^^]]]]]]]]]]]]]]]]]]]]]]]]]]]]]][[YYY2////////////,,œœœœ  žš˜—“’‘õ††Šˆ‰%!)))(++...ô4477ahhónnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÑóóóóóóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûóÚûûûûûûûûépdddsrg``````````````````````````````gfffeeccccccccccccªªªªª¬¬¬®­¨§ ž˜—’õõ~††ŠŠˆ$‰%!)(+..ôô444777ahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhûûûûûûûûûûûûûûûûûûûûûûûûûûÃô ÿÿÿ ôhÑûûûûûûûûûûûûûûûûà ÿ 7Úûûûûûûn ÿÿ hûûûûûûÑôôôôôôôôôôôôôóûÑôôôôôôôôôôôôô7ûÑôôôôôôôôôôôôôóûûûûû½7ûûûûû7 ÿÿqÈÈÈÈÈÈÈÈÈÈÈ1ÈÈÈÇÇÊÊÍk ÿÿ cÎÎÎÎÎÎÎÎÎÎÎÐÐз®¨§Ÿ˜“‘õõõ††††ˆ‰%))+.ôôôô4444444444444444444444444444444444444444444444444444ûûûûûûûûûûûûûûûûûûûûûûûÑ íwõõõõõõõõõõví ÿhûûûûûûûûûûûû9íwõwíûûûû:íwõõíÿ ÚûûûÙ¤ hС 7С óûûûûûõwÿnûà íõõõõõõvûûûûûûûûû¨% 7ûûûûûûû9võõvíÿÑûûûûûûûûûûûûåн®©§ž˜’õõõõõõõõ†Š$%))+.ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûûÚ. võõõõõõõ’˜˜˜‘õõõõõõõvÿnûûûûûûûûªõõõõõõõw ÿÃû·õõõõõõõí ûûûÙšõõõõõõõõõõõ–½ûÙ õõõõõõõõõõõ•®ûÙšõõõõõõõõõõõ–½ûûûûûûõõõvÿvõõõŽ˜“õõõõw ÿÚûûûûûûû¨“õõõõõõõõõõõ–®ûûûûûûû3õõõõõõõõ"ÚûûûÑÚÚÚèèûûåÙ¶®­¨¦ž˜˜—“’Ž‘‘õõ††Š$%!)(((((((((((((((((((((((((((((((((((((((++.....ôôôôôôôôôûûûûûûûûûûûûûûûûûûûûcwõõõõõ½ûûûûûûá· ‘õõõõõõwÿûûûûûûûÐõõõõõõõõõõvaõõõõõõõõíÿôûûûûÐõõõõõõõõõ ûûûûûÂõõõõõõõõõûûûûû°õõõõõõõõõ ûûûûûûûûõõõõõwõõwªûûûÙ“õõõõvÚûûûûûûûû¨õõõõõõõõõ ûûûûûûûûªõõõõõõõõõõ†ûûûûûûûûûûûûûж·®­¨§¦Ÿž˜—“Ž‘õõ††Šˆ‰$%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)))(+...ôôôôôôôôôûûûûûûûûûûûûûûûûûûû&võõõõõõ›áûûûûûûûûûûû¨õõõõõõõõõÿûûûûûûûšõõõõõõõõõõõwõõõõõõõõõõœôûûûûû˜õõõõõõõv ûûûûûû“õõõõõõõv ûûûûûû“õõõõõõõv ûûûûûûûûõõõõõõõõõ ûûûûûá‘õõõõvûûûûûûûûûõõõõõõõõíûûûûûûûÐõõõõõõõõ ½§õŒÿhûûûûûûûûûûûûûÙн¶·°®¨§ ž˜“Žõõ~†††ŠŠˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ$%!))(+.ôôôôôôôôôûûûûûûûûûûûûûûûûûÚõõõõõõwªûûûûûûûûûûûûû¨õõõõõõõõõÿûûûûûûû‘õõõõõõõõõ˜“õõxõõõõõõõõ ¨ûûûûûû˜õõõõõõõí ûûûûûû˜õõõõõõõí ûûûûûû˜õõõõõõõí ûûûûûûûûõõõõõõõõ"ôûûûûûû¨õõõõõvÿôûûûûûûûû˜õõõõõõõ ôûûûûûûû õõõõõõõhûû°õ/ôûûûûûûûûûûûûûûûáááÙÙ·®¨¦ž˜’õõõõõ†Š$%!)+.ôôôôôôôôôûûûûûûûûûûûûûûûûÎvõõõõõõõ+ûûûûûûûûûûûûûû¨õõõõõõõõõÿûûûûûûûõõõõõõõõv¹ûûÙ—õõõõõõõõí ûûûûûûûû õõõõõõõí ûûûûûû§õõõõõõõí ûûûûûû õõõõõõõí ûûûûûûûûõõõõõõõõ óûûûûûûÙõõõõõõ ÿÑûûûûûûû˜õõõõõõõ ôûûûûûûû“õõõõõõõóûûû­¨ûûûûûûûûûûûûûûûûûûûûûÙ°­¤–õõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ†‹%',/20444444444ûûûûûûûûûûûûûûûáxõõõõõõõûûûûûûûûûûûûûûû¨õõõõõõõõõÿûûûûûûû‘õõõõõõõ ûûûûûšõõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû“õõõõõõûûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûèûûÙ¼¯©¤”Šxvvvvwwõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ†•”›œ39aaaaaaaaaaûûûûûûûûûûûûûûû†õõõõõõõv7ûûûûûûûûûûûûûûû¨õõõõõõõõõÿûûûûûûûšõõõõõõí ûûûûû¨õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûûšõõõõõõÿÚûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûèèû×¼¯ª¢œ%ˆíí"vvvwõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ–›œ¢£cióóóóóóóóóûûûûûûûûûûûûûû›õõõõõõõõûûûûûûûûûûûûûûûû¨õõõõõõõõõÿûûûûûûûÂõõõõõõíÿÚûûûû¨õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû¨õõõõõõõ7ûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûèû׿«:3,! íííí"vvwõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ‘“–¤¥ª²¹ÑÑÑÑÑÑÑÑÑûûûûûûûûûûûûûÂõõõõõõõõwûûûûûûûûûûûûûûûû¨õõõõõõõõõÿûûûûûûûû—õõõõõõôûûûû¨õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû¨õõõõõõõ ûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûû×¹«:3)! ííí"vvõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõõ‘“𠍮·ÂáûûûûûûûûûûûûûûûûûûûûûûŽõõõõõõõõ7ûûûûûûûûûûûûûûûû¨õõõõõõõõõÿûûûûûûûûá“õõõõõ Ãûûû¨õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû·õõõõõõõíûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûû:3)! ##††††ŒŒ’““““““““““““’’ŒŽŽ~~wwwww~~~†††Œ–¤©¬¶Ðáûûûûûûûûûûûûûûûûûûûûû®õõõõõõõõõÑûûûûûûûûûûûûûûûû¨õõõõõõõõõÿûûûûûûûûûá“õõõõwÃûû¨õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû½õõõõõõõvÿûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû $$‰%”””››žŸ          Ÿž––•‹Š#x""####ˆˆ$$%›œ£ª¯¼Øåûûûûûûûûûûûûûûûûûûûûû’õõõõõõõõõûûûûûûûûûûûûûûûûû¨õõõõõõõõõÿÚûûûûûûûûûû¦õõõõwÃû¨õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû½õõõõõõõõÿóûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû!!),,œœ¢¢¥©®®®®®®®®®®­¥¤›%$#í !!),/3:«²¿×åûûûûûûûûûûûûûûûûûûûûÙõõõõõõõõõõ ûûûûûûûûûûûûûûûûû§õõõõõõõõõ4ûûûûûûûûûûû“õõõwÿ4¨õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû½õõõõõõõõóûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûèûûûûûûûûûûûûûûûûûûûû©õõõõõõõõõí ûûûûûûûûûûûûûûûûÑvõõõõõõõõõ7ûûûûûûûûûûûû®’õõõÿõõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû½õõõõõõõõóûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûšõõõõõõõõõíôûûûûûûûûûûûûû "õõõõõõõõõõwÿÿ7ûûûûûûûûûûᨑõõ"íõõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû½õõõõõõõõóûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû’õõõõõõõõõ ôûûûûûûûûûûûû¦•Œõõõõõõõõõõõõõõõ¢Ñûûûûûn ÿÿnûᨑõõõõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû½õõõõõõõõÃûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõ ôûûûûûûûûûûûûн½½½½½½½½½½½½½½½½½Ùûûûûû3íõõvÿhûûá®’õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûûûûõõõõõõõõóûûûûûûû½õõõõõõõõûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõ ôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¬õõõõõõûûûû¨õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõí ûûûûûû¨õõõõõõõíôûûûûûûûûõõõõõõõõóûûûûûûû©õõõõõõõõûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõ ôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûá‘õõõõõõvÿûûûû¨õõõõõõõí ûûûûûûûû¨õõõõõõõí ûûûûûû§õõõõõõõí ûûûûûû§õõõõõõõ ôûûûûûûûûõõõõõõõõóûûûûûûû¨õõõõõõõvûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõ ôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû½õõõõõõõõûûûû¨õõõõõõõí ûûûûûûûû¨õõõõõõõíÚûûûûû˜õõõõõõõíÚûûûûû˜õõõõõõõ ôûûûûûûûûõõõõõõõõóûûûûûûûšõõõõõõõ Ãûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõ ôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÐõõõõõõõvnûûûû¨õõõõõõõíôûûûûûûûû¨õõõõõõõvûûûûû˜õõõõõõõvûûûûû˜õõõõõõõ hûûûûûûûûõõõõõõõõhûûûûûûûŽõõõõõõõ ûûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõõõ ôûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû‘õõõõõõ+ûûûûû¨õõõõõõõ 7ûûûûûûûû¨õõõõõõõõ"ÿ ÚûûûõõõõõõõõvÿÚûûûõõõõõõõÃûûûûûûûûõõõõõõõõÃûûûûûÐõõõõõõõvnûûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû˜õõõõõõõõõ ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¨õõõõõ ûûûûûû§õõõõõõõûûûûûûûûû˜õõõõõõõõõí4ó2õõõõõõõõvõ"ôó2õõõõõõõõûûûûûûûûûõõõõõõõõwnûûûû•õõõõõõõ&ûûûûûûûû˜õõõõõõõ ôûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû õõõõõõõõõí ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû“õõõõÿaûûûûûŒõõõõõõvÃûûûûûûûûû˜õõõõõõõvwõvwõõõõõõõ"«‘õw wõõõõõõõv7ûûûûûûûûûõõõõõõõõõÿôô õõõõõõõÚûûûûûûûû‘õõõõõõõ ôûûûû õõõõõõõõ ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû®õõõõõõõõõíÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûá“õõõÿ7óh&õõõõõõw«ûûûûûûûûûÃwõõõõõõõí ‘õõõõõõõõõõõõ+ûБõõõõõõõõõõõõ ûûûûûûûûûûõõõõõõõõ õõv võõõõõõõxÎûûûûûûûûcõõõõõõõõ ôûûû¦ííõõõõõõõõvííííí ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÙõõõõõõõõõõÿÃûûûûûûûûûûûûûûûûûûûûûûûûûÑ ûûûûûûûûûûû¨õõõ"õõõõõõ¹ûûûûûûûûûcíõõõõõõõõí Гõõõõõõõõõõ›ûûûá“õõõõõõõõõõˆûûûûûûûûûûûõõõõõõõõ£‘õõõõõõõõõõŒáûûûûûûûûvõõõõõõõõ ôûûû°‘õõõõõõõõõõõõõõõõí ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû—õõõõõõõõõ7ûûûûûûûûûûûûûûûûûûûûûûûûÙŠÿûûûûûûûûûûûûÙ¨’õõõõõõõõõõžáûûûûûûûûû½õõõõõõõõõõ˜ûûá¦õõõõõõõ¬ûûûûûû¨‘õõõõõõõûûûûûûûûûûûûõõõõõõõõóÙ õõõõõõõ®ûûûûûûûûûõõõõõõõõõõõ¨ûûûûûГõõõõõõõõõõõõõõõ˜ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû®õõõõõõõõõûûûûûûûûûûûûûûûûûûûûûûûû©õÿûûûûûûûûûûûûûûûÙ®¨˜˜˜˜§®Ùûûûûûûûûûûûûûûûûûûûûûûûûûûûá© ˜˜ ®áûûûûûûûûá®§˜˜š©ÙûûûûûûûûûûûûûõõõõõõõõóûûÙ©š˜˜§·ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûášõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû’õõõõõõõõûûûûûûûûûûûûûûûûûûûûûûûûŽõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûžõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÂõõõõõõõõwÿ7ûûûûûûûûûûûûûûûûûûûûûû©õõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû­õõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûžõõõõõõõõûûûûûûûûûûûûûûûûûûûûûáõõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûn ÿÿ nûûûûûûûûûûû¨õõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûá“õõõõõõõ"ÿ7ûûûûûûûûûûûûûûûûûûûû”õõõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûûû3íõõíÿaûûûûûûûûûûûžõõõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûБõõõõõõõÚûûûûûûûûûûûûûûûûûû£õõõõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûû¬õõõõõõÚûûûûûûûûûûû—õõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûБõõõõõõwÚûûûûûûûûûûûûûûûû3õõõõõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûáõõõõõõw7ûûûûûûûûûûûá‘õõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûБõõõõõõvÑûûûûûûûûûûûûûÚ&õõõõõõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûû®õõõõõõõõôûûûûûûûûûûûûÂõõóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûá—õõõõõõv7ûûûûûûûûûûÚ8õõõõõõõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûõõõõõõõõóûûûûûûûûûûûûûûûûûûûûûû¨õõõõõõõõ 7ûûûûûûûûûûûûû õóûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¨‘õõõõõwÿóÑûûûÃ7wõõõõõõõõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¬õõõõõõõõóûûûûûûûûûûûûûûûûûûûûûû®õõõõõõõõÚûûûûûûûûûûûûûᑽûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÙ õõõõõõv ÿÿÿwõõõõ˜®½šõõÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûà võõõõõõõõóûûûûûûûûûûûûûûûûûûûûûûá‘õõõõõõw8ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÙ¨’õõõõõõõõõõõõõõõ˜®áûûûû—õÿûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûИõõõõõõõõõõ:Úûûûûûûûûûûûûûûûûûûûûûûû°õõõõõõ£ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûÙ®§˜’õõõõõ“˜§·áûûûûûûûÐõûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûá½½½½½½½½½½½áûûûûûûûûûûûûûûûûûûûûûûûûûšõõšÂûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû9X  J¼Jgambit-0.2010.09.01/src/gui/bitmaps/gambit.ico0000644000076500007650000000137611350032206015410 00000000000000 è( @€€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷wwÿÿÿÿÿÿÿÿÿÿÿÿªªªÿÿÿÿÿÿÿÿÿÿÿúªªªÿÿÿÿÿÿÿÿÿwwwªÿÿÿÿÿÿÿÿÿÿÿù™"ª§ÿÿÿÿÿÿÿÿÿÿÿ™™"ª§ÿÿÿÿÿÿÿÿÿùŸÿ"ªwwwÿÿÿÿÿÿ™ÿÿ"ÿúªªªÿ÷wwÿùŸÿÿøÿªªªÿÿ™™—w™ÿÿÿ"ÿÿÿÿÿù™™Ÿ™—ÿÿÿ"ÿÿwww™ÿÿÿ™—ÿÿ"ÿúª¡—ÿÿÿÿ™wÿÿ"ÿÿªª¡—ÿÿÿù—ÿøú¯ÿñ™wwwÿÿ™wÿ"ªÿÿÿˆù™™—ÿÿù—w"Нÿÿñÿ™™Ÿÿÿÿ™™"ªÿÿñÿÿÿÿÿÿÿù™"ªwÿÿñÿ÷wwÿÿÿÿÿÿú§ÿñÿ™™—ÿÿÿÿÿÿÿªwÿÿˆù™™Ÿÿÿÿÿÿÿÿú§wq™ÿÿÿÿÿÿÿÿÿÿÿªª¡—ÿÿÿÿÿÿÿÿÿÿÿúª¡—ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ™www÷ww÷ÿ÷÷ÿ÷÷wù™™—ÿÿ÷ñ™™Ÿÿÿÿÿññÿwÿwñññ÷÷ññÿ÷ÿÿññwwñwñqwñÿÿÿññgambit-0.2010.09.01/src/gui/bitmaps/gambit.xpm0000644000076500007650000000243211350032206015434 00000000000000/* XPM */ static char * gambit_xpm[] = { "32 32 7 1", " c #800000", ". c Gray100", "X c #808080", "o c Red", "O c Green", "+ c #c0c0c0", "@ c #008000", " .. .. ... . ... . ", " XXX X .XX . . X XXX .. X.X XX", " X...X X.. X X . X X.. X. X.. X.", " X. . X X.X X .X. X.. X.", " X.. X XXX X X.. X XXX .. X.. X.", " X.. X X.. X X.. X X.. X. X.. X.", " X X.. X X.. X .X. ooooo.", ".XXXXX.X...X.X...X.XXXX..ooooooX", "........................ooXXXXXX", ".................OOOO ooXX.....", "................OOOOO ooX......", "...............OOXXXX +oo......", "..............OOXX....++.oooooo.", ".............OOXX.... ...oooooX", ".......ooo@@OOXX..... +...XXXXX", "......oooo@@OOX...... +........", ".....ooXXX@@+OO...... +..ooooo.", "....ooXX..@@+.OO......++.ooooooX", "...ooXX....++..OO.... .ooXXXXXX", "..ooXX....@@....OOOOO ooXX.....", "oooXX.....@@+....OOOO ooX......", "oooX......@@+.....XXXXXXoo......", "XXoo......@@+............oooooo.", "...oo......++...OOOOOO....oooooX", "....oo....@@...OOOOOOOX....XXXXX", ".....oo...@@+.OOXXXXXXX.........", "......oooo@@OOOXX...............", ".......ooo@@OOOX................", "........XXXXXXOO................", "...............OOOOOOO..........", "................OOOOOOX.........", ".................XXXXXX........."}; gambit-0.2010.09.01/src/gui/bitmaps/gambitbig.xpm0000644000076500007650000027106311350032206016126 00000000000000/* XPM */ static char * gambitbig_xpm[] = { "300 150 257 2", " c None", ". c #000000", "+ c #100000", "@ c #260000", "# c #390000", "$ c #221313", "% c #272927", "& c #276F12", "* c #690805", "= c #7F0C08", "- c #840808", "; c #84100C", "> c #6B311A", ", c #635E18", "' c #4D554A", ") c #736758", "! c #008400", "~ c #0C8408", "{ c #0A8A0A", "] c #069606", "^ c #398F22", "/ c #55904F", "( c #65945A", "_ c #728C50", ": c #6B8C6B", "< c #738873", "[ c #6B946B", "} c #7F7F7B", "| c #848484", "1 c #739473", "2 c #739C73", "3 c #931313", "4 c #AF120F", "5 c #A53626", "6 c #AC4242", "7 c #CA0000", "8 c #CD1612", "9 c #C83333", "0 c #CE3939", "a c #9A5041", "b c #C74F43", "c c #9C5A5A", "d c #B65353", "e c #906363", "f c #9C6363", "g c #BD5A5A", "h c #8D7757", "i c #906F6F", "j c #AD7160", "k c #8C8381", "l c #849C84", "m c #A6807E", "n c #C4807C", "o c #949494", "p c #949C94", "q c #9C9494", "r c #9C9C9C", "s c #A99595", "t c #B59090", "u c #C59090", "v c #08A508", "w c #00B500", "x c #0CB60C", "y c #00CA00", "z c #0CCC0A", "A c #05D800", "B c #10DE0D", "C c #00F300", "D c #08EF08", "E c #10E710", "F c #10EF10", "G c #08F708", "H c #10F710", "I c #00FF00", "J c #08FF08", "K c #21BE16", "L c #36BB2D", "M c #1AE61A", "N c #2EE52B", "O c #10FF10", "P c #1EFC1E", "Q c #29F725", "R c #2FFB2D", "S c #46AD42", "T c #4FAD4F", "U c #5BAD5B", "V c #4EBD4E", "W c #49E049", "X c #45FF45", "Y c #5AFB5A", "Z c #79B06C", "` c #98AC8B", " . c #76D872", ".. c #9AD695", "+. c #6FFB6D", "@. c #85FB85", "#. c #96F994", "$. c #9CFF9C", "%. c #A9A5A5", "&. c #ADADAD", "*. c #C3A6A4", "=. c #ADB5AD", "-. c #BDBD9C", ";. c #ACD3A7", ">. c #A7FCA7", ",. c #BABAB7", "'. c #C6B5B5", "). c #BDC7BA", "!. c #CBBDBD", "~. c #CECABD", "{. c #C6CEC6", "]. c #CECECE", "^. c #B9D8B7", "/. c #C5D8C1", "(. c #C1EAC1", "_. c #B5FFB5", ":. c #C1FBC1", "<. c #C6FFC6", "[. c #CEFFCE", "}. c #DE0000", "|. c #E70000", "1. c #DE0808", "2. c #E20C0C", "3. c #E71010", "4. c #EF0000", "5. c #EF0800", "6. c #EF0808", "7. c #EF1010", "8. c #F70000", "9. c #F70808", "0. c #F71010", "a. c #FF0000", "b. c #FF0808", "c. c #FF1010", "d. c #DA1E18", "e. c #E71818", "f. c #EF1B15", "g. c #D62929", "h. c #D63131", "i. c #DE2121", "j. c #E22929", "k. c #EF2121", "l. c #EF2929", "m. c #F71818", "n. c #F72121", "o. c #F72929", "p. c #FF1818", "q. c #FF2121", "r. c #FF2929", "s. c #DE3E3E", "t. c #F13333", "u. c #F14443", "v. c #FF3131", "w. c #FF3D3D", "x. c #F74A4A", "y. c #FF4A4A", "z. c #E25450", "A. c #DA6767", "B. c #ED6262", "C. c #FF5252", "D. c #FB5E5E", "E. c #FF6363", "F. c #F76B6B", "G. c #DD7878", "H. c #DC8982", "I. c #F17575", "J. c #F18682", "K. c #FF6B6B", "L. c #FF7373", "M. c #FF7F7F", "N. c #FB8C8C", "O. c #DC9797", "P. c #D8ADAA", "Q. c #EFA0A0", "R. c #FF9494", "S. c #FF9C9C", "T. c #F7ADAD", "U. c #FFA9A9", "V. c #DEDE5A", "W. c #E1BAB5", "X. c #F0BBB5", "Y. c #D6BDBD", "Z. c #E6BDBD", "`. c #F7BDBD", " + c #FFB5B5", ".+ c #D6C6C6", "++ c #E6C6C6", "@+ c #DACECE", "#+ c #D6E7CE", "$+ c #F7C6C6", "%+ c #FFBDBD", "&+ c #FFC6C6", "*+ c #E7CECE", "=+ c #EFCECE", "-+ c #F7CECE", ";+ c #FFCECE", ">+ c #D6D6D6", ",+ c #D6DED6", "'+ c #D6E7D6", ")+ c #D6EFD6", "!+ c #D6F7D6", "~+ c #D6FFD6", "{+ c #DED6D6", "]+ c #DEEFD6", "^+ c #DEF7D6", "/+ c #E7D6D6", "(+ c #E7E7D6", "_+ c #EFD6D6", ":+ c #F7D6D6", "<+ c #FFD6D6", "[+ c #DEDEDE", "}+ c #DEE7DE", "|+ c #DEEFDE", "1+ c #DEF7DE", "2+ c #DEFFDE", "3+ c #E7DEDE", "4+ c #EFDEDE", "5+ c #F7DEDE", "6+ c #FFDEDE", "7+ c #E7E7E7", "8+ c #E7EFE7", "9+ c #E7F7E7", "0+ c #E7FFE7", "a+ c #EFE7E7", "b+ c #EFEFE7", "c+ c #F7E7E7", "d+ c #FFE7E7", "e+ c #EFEFEF", "f+ c #EFF7EF", "g+ c #EFFFEF", "h+ c #F7EFEF", "i+ c #F7F7EF", "j+ c #FFEFEF", "k+ c #F7F7F7", "l+ c #F7FFF7", "m+ c #FFF7F7", "n+ c #0000A0", "o+ c #000000", "p+ c #BF0000", "q+ c #00BF00", "r+ c #BFBF00", "s+ c #0000BF", "t+ c #BF00BF", "u+ c #00BFBF", "v+ c #C0C0C0", "w+ c #808080", "x+ c #FF0000", "y+ c #00FF00", "z+ c #FFFF00", "A+ c #0000FF", "B+ c #FF00FF", "C+ c #00FFFF", "D+ c #FFFFFF", "E+ c #000000", "F+ c #000000", "G+ c #000000", "H+ c #000000", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+S.L.w.q.x+x+x+x+x+r.w.L. +d+D+D+D+D+D+D+D+<+x+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+%+%+%+%+%+%+%+%+%+%+%+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+;+y.x+x+y.;+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+M.q.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+w.S.d+D+D+D+D+v.x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+<+w.x+x+x+x+x+x+x+x+x+x+u 7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+U.x+x+x+x+x+x+H.D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+E.x+x+x+x+x+x+}.- # @ H+H+H+@ * 4 |.x+x+x+x+w.S.%+y.x+x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+>+' }.x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+p.x+x+x+x+x+x+|.s D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.p.x+x+x+x+x+|.* H+% } v+[+D+D+D+>+r ) * |.x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+Q.x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+S.x+x+x+x+x+x+x+x+* 7+D+D+D+D+D+D+D+D+D+D+D+D+D+d+p.%+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+v.x+x+x+x+x+x+}.@ $ r D+D+D+D+D+D+D+D+D+D+7+s 3 x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+- r D+D+D+D+D+D+D+D+D+D+D+D+D+E.x+* v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+<+p.x+x+x+x+x+x+}.+ % [+D+D+D+D+D+D+D+D+D+D+D+D+D+7+a x+x+x+x+x+x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+S.x+x+x+x+x+x+x+x+* w+D+D+D+D+D+D+D+D+D+D+D+D+;+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+<+p.x+x+x+x+x+x+|.+ % 7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+n x+x+x+x+x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+0.x+x+x+x+x+x+|.+ r D+D+D+D+D+D+D+D+D+D+D+d+p.x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+<+p.x+x+x+x+x+x+x+* $ 7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+H.x+x+x+x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+Q.x+x+x+x+x+x+* $ 7+D+D+D+D+D+D+D+D+D+D+D+v.x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+r.x+x+x+x+x+x+x+7 H+r D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+s.x+x+x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+n p+x+x+p+# H+%.D+D+D+D+D+D+D+D+D+D+D+C.x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+C.x+x+x+x+x+x+x+x+* % D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+0.x+x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+].' H+H+' ].D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+;+x+x+x+x+x+x+x+x+|.H+r D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+N.x+x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+R.x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+q.x+x+x+x+x+x+x+x+4 $ D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+m.x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+C.x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+S.x+x+x+x+x+x+x+x+x+* ) D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+N.x+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+S.M.w.w.w.w.L.S.6+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+N.E.w.w.E.S.d+D+D+D+D+D+D+D+D+d+S.L.w.w.y.N.6+D+D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+6+N.y.w.w.L. +D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+y.x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+v.x+x+x+x+x+x+x+x+x+@ r D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+i.H+D+D+D+D+D+D+D+D+D+D+D+D+6+M.q.x+x+x+x+x+x+x+x+x+x+C.d+D+D+D+D+D+D+D+D+D+%+x+x+x+x+x+x+x+x+x+x+w.D+D+d+K.x+x+x+x+x+x+x+0.Q.D+D+D+D+D+D+M.p.x+x+x+x+x+x+x+B.D+D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+6+E.x+x+x+x+x+x+x+0.S.D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+x+x+x+M.D+D+D+D+D+<+r.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+w.D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+6+x+x+x+x+x+x+x+x+x+x+H+>+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+[+' D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+7 * # # 4 x+x+x+x+x+x+0.++D+D+D+D+D+D+D+D+D+*.p+x+x+x+x+x+x+x+x+p+' <+r.x+x+x+x+x+x+x+x+x+x+z.D+D+D+d+r.x+x+x+x+x+x+x+x+x+x+g.D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# H.p.x+x+x+x+x+x+x+x+x+x+k.d+D+D+D+D+D+D+D+D+# }.x+x+x+x+x+x+x+x+- w+D+D+D+U.p.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+S.x+x+x+x+x+x+x+x+x+p+H+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+r.x+x+x+* H+% r v+,.a x+x+x+x+x+x+|.P.D+D+D+D+D+D+D+D+D+>+|.x+x+x+x+x+x+x+p+> p.x+x+x+x+x+x+x+x+x+x+x+x+f D+<+p.x+x+x+x+x+x+x+x+x+x+x+x+5 D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+- x+x+}.- - }.x+x+x+x+x+x+x+1._+D+D+D+D+D+D+D+D+*.x+x+x+x+x+x+x+x+- w+D+D+D+K.l.p+p+x+x+x+x+x+x+x+x+}.p+p+p+p+p+- ' D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+E.x+x+x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+r.x+x+x+x+H+%.D+D+D+D+D+k.x+x+x+x+x+x+}.>+D+D+D+D+D+D+D+D+D+w.x+x+x+x+x+x+x+}.|.x+}.* # * |.x+x+x+x+x+x+x+7 P.p.x+|.- # * |.x+x+x+x+x+x+x+}.r D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+x+0.# H+% w+w+> x+x+x+x+x+x+x+4 7+D+D+D+D+D+D+D+D+p.x+x+x+x+x+x+x+- w+D+D+D+D+) ' ' x+x+x+x+x+x+x+x+# % ' ' ' ' ' ) D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+w.x+x+x+x+x+x+x+x+x+- ' D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+- D+D+D+D+D+D+L.x+x+x+x+x+x+x+= D+D+D+D+D+D+D+D+D+w.x+x+x+x+x+x+x+x+x+p++ % o v+m x+x+x+x+x+x+x+x+}.x+7 + $ w+v+m x+x+x+x+x+x+x+x+% D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+|.@ $ ].D+D+D+D+t.x+x+x+x+x+x+x+a D+D+D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+p.x+x+x+x+x+x+f D+D+D+D+D+M.x+x+x+x+x+x+x+- r D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+7 H+' 7+D+D+D+n.x+x+x+x+x+x+x+x+}.H+% 7+D+D+D+n.x+x+x+x+x+x+x+# >+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# $ >+D+D+D+D+D+<+x+x+x+x+x+x+x+}.].D+D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+<+x+x+x+x+x+x+x+}.].D+D+D+D+M.x+x+x+x+x+x+x+p+w+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+}.+ % D+D+D+D+D+w.x+x+x+x+x+x+x+}.+ % D+D+D+D+D+w.x+x+x+x+x+x+x+- ,.D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# ,.D+D+D+D+D+D+D+m.x+x+x+x+x+x+x+> D+D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+%+x+x+x+x+x+x+x+x+% D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+% 7+D+D+D+D+D+w.x+x+x+x+x+x+x+p+% 7+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+y.x+x+x+x+x+x+x+- >+D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+p.x+x+x+x+x+x+}.H+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+L.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+L.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+}.} D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+Q.x+x+x+x+x+x+# % D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+w+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+N.x+x+x+x+x+x+x+x+% D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+D+D+D+D+D+<+%+%+%+%+%+%+%+%+%+%+%+%+%+%+%+%+%+%+6+D+D+D+D+D+n p+x+x+}.# H+,.D+D+d+S.q.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+%+x+x+x+x+x+x+x+x+@ D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+q.x+x+x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+D+D+D+D+D+K.t.k.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+n.G.[+D+D+D+D+D+].' H+H+% ].D+d+M.p.x+x+x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+%+x+x+x+x+x+x+x+x+# >+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+y.x+x+x+x+x+x+x+x+x+p+w+D+D+D+D+D+D+D+D+D+D+D+D+D+) ' % 7 x+x+x+x+x+x+x+x+x+x+|.* H+H+% r D+D+D+D+D+D+D+D+D+D+d+M.p.x+x+7 p+x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+%+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+N.x+x+x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+[+}.x+x+x+x+x+x+x+x+x+* $ r D+D+D+D+D+D+D+D+D+D+D+D+S.q.x+x+x+* H+3 x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+%+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+6+x+x+x+x+x+x+x+x+x+x+' D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+L.x+x+x+x+x+x+x+x+x++ o D+D+D+D+D+D+D+D+D+D+D+;+r.x+x+x+|.@ H+o M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+%+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+q.x+x+x+x+x+x+x+x+x+@ D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+7+D+D+D+D+D+D+D+D+D+D+K.x+x+x+x+|.@ $ >+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+%+x+x+x+x+x+x+x+x+H+v+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6 6 d g g A.A.G.G.J.N.S.S.S.S.S.S.S.S.S.S.R.J.I.B.z.0 9 8 4 p+4 4 4 4 5 5 6 6 d g j n u P.W.*+4+h+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+S.x+x+x+x+x+x+x+x+x+* [+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+D+D+d+r.x+x+x+x+|.@ $ >+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+%+x+x+x+x+x+x+x+}.H+D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+- - 3 3 4 4 4 9 9 h.0 s.s.s.z.z.C.D.E.E.E.E.E.E.E.E.E.E.D.C.u.u.t.j.i.8 1.7 7 8 8 8 8 g.g.9 9 0 z.A.H.O.T.$+5+h+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+m.x+x+x+x+x+x+x+x+4 r D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+D+d+r.x+x+x+x+x+- $ >+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+ +x+x+x+x+x+x+x+p+% D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+u n d 6 3 - - - 4 4 4 4 8 8 e.e.e.e.k.k.n.n.q.r.r.r.r.r.r.r.r.r.r.r.r.q.q.k.m.m.7.7.|.|.|.|.|.7.7.7.e.e.e.k.u.B.I.N.Q.`.<+d+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+;+x+x+x+x+x+x+x+x+|.) D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+D+v.x+x+x+x+x+x++ w+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+* ' D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+4+++P.u n d 6 3 - - 4 p+p+p+7 }.}.8.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+p.r.y.E.M.S. +;+d+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+z.x+x+x+x+x+x+x+x+* D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+;+x+x+x+x+x+x+p+H+7+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x++ r D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+D+4+*+P.u n g 6 5 4 p+p+p+p+7 }.}.|.8.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+p.r.u.B.I.J.O.W.++[+[+[+[+[+[+[+[+[+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+e.x+x+x+x+x+x+x+}.r D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+y.x+x+x+x+x+x+p+' D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+y.x+x+x+x+x+x+4 H+7+D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+k+D+4+$+T.O.G.A.0 g.4 p+p+7 }.}.}.|.8.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.n.u.z.A.G.H.*.'.v+v+v+v+v+v+v+v+v+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+1.x+x+x+x+x+x+x+3 D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+p.x+x+x+x+x+x+x+' D+D+D+D+D+y.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+M.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+r.x+x+x+x+x+x+@ ) D+D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+# v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+D+D+6+$+T.N.I.B.s.i.1.}.}.}.}.|.|.8.8.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.e.t.s.z.A.n t %.%.%.%.%.%.%.%.%.%.", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+_+}.x+x+x+x+x+x+x+f D+D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+}.++D+D+6+v.x+x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+E.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+L.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+E.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+- v+D+D+D+D+D+D+6+x+x+x+x+x+x+- H+[+D+D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+r.x+x+x+x+x+x+x+# v+D+D+D+R.M.D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+;+U.R.I.B.u.n.0.8.8.8.8.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.e.j.0 b g j m k o o o o o o o o o ", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+7+4 x+x+x+x+x+x+|.O.D+D+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+p.x+x+x+x+x+x+x+x+x+w.r.x+x+1.x+x+x+x+x+x+x+x+> ;+M.D+D+D+D+D+D+w.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+w.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+w.x+x+x+x+x+x+x+p+' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+7 w+D+D+D+D+D+D+M.x+x+x+x+x+}.H+w+D+D+D+D+D+D+D+D+w.x+x+x+x+x+x+x+- w+D+D+D+D+D+D+D+E.x+x+x+x+x+x+x+4 ,.D+D+U.x+j w+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+d+d+6+6+;+ +S.M.K.C.w.q.0.x+x+x+x+x+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.e.i.9 0 6 d f i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+a }.x+x+x+x+x+x+z.d+D+D+D+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+H+D+D+D+D+D+D+D+y.x+x+x+x+x+x+x+x+x+x+x+|.* # x+x+x+x+x+x+x+x+x+x+A.w+D+D+D+D+D+w.x+x+x+x+x+x+x+}.' D+D+D+D+D+D+r.x+x+x+x+x+x+x+}.' D+D+D+D+D+D+r.x+x+x+x+x+x+x+}.' D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+x+> D+D+D+D+D+d+p.x+x+x+x+}.+ % D+D+D+D+D+D+D+D+D+x+x+x+x+x+x+x+x+p+} D+D+D+D+D+D+D+<+x+x+x+x+x+x+x+x+5 %+L.x+k.H+,.D+D+D+D+D+D+D+D+D+D+D+D+D+6+<+;+%+`. +U.S.M.L.E.C.w.r.m.x+x+8.0.7.e.e.e.i.i.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.9 0 6 d d c f i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+*.3 |.x+x+x+x+x+0.B.%+D+D+D+D+D+D+d+ +E.p.x+x+x+x+x+x+|.4 # H+D+D+D+D+D+D+D+<+x+x+x+x+x+x+x+x+x+x+}.@ $ %.0.x+x+x+x+x+x+x+x+p+H+w+D+D+D+D+<+x+x+x+x+x+x+x+x+x+> D+D+D+D+D+;+x+x+x+x+x+x+x+x+x+* D+D+D+D+D+U.x+x+x+x+x+x+x+x+x+> D+D+D+D+D+D+D+D+x+x+x+x+x+4 |.x+x+|.O.D+D+D+6+r.x+x+x+x+}.+ % 7+D+D+D+D+D+D+D+D+M.x+x+x+x+x+x+x+x+x+> D+D+D+D+D+D+D+D+O.x+x+x+x+x+x+x+x+x+x+e.+ % D+D+D+D+D+D+D+D+D+D+D+D+D+<+;+`. +S.R.M.L.K.D.C.w.v.r.m.p.x+x+0.e.e.i.g.h.9 0 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d d d c f i i i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+7+i - }.x+x+x+x+x+x+x+q.w.w.w.p.x+x+x+x+x+x+x+}.4 # H+$ ) ].D+D+D+D+D+D+D+D+O.x+x+x+x+x+x+x+|.- H+% >+D+ +x+x+x+x+x+x+x+p++ ' D+D+D+6+y.x+x+x+x+x+x+x+x+x+x+x+u.%+D+6+E.x+x+x+x+x+x+x+x+x+x+x+t.S.D+6+y.x+x+x+x+x+x+x+x+x+x+x+u.%+D+D+D+D+D+D+x+x+x+}.# H+) }.x+x+x+m.w.r.x+x+x+x+|.- H+% 7+D+D+D+D+D+D+D+M.r.x+x+x+x+x+x+x+x+x+x+x+u.S.D+D+D+D+D+D+D+n x+x+x+x+x+x+x+x+7 + % 7+D+D+D+[+7+7+7+k+k+D+D+h+6+;+`.S.R.M.K.C.w.w.v.r.q.m.p.p.0.x+x+e.e.i.9 0 6 d c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c f f i i i i i } } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+[+} % - p+|.x+x+x+x+x+x+x+x+x+x+}.p+- # @ H+$ ) ,.D+D+D+D+D+D+D+D+D+D+D+D+t p+|.x+|.p+* + $ } D+D+D+D+u p+|.x+x+p+# H+' 7+D+D+D+6+I.5 - - - - - - - - - - - > ,.<+F.5 - - - - - - - - - - - 5 r <+F.5 - - - - - - - - - - - > v+D+D+D+D+D+x+|.* H+% ].D+>+; p+x+x+x+x+x+x+}.* + $ } D+D+D+D+D+D+D+D+D+M.0 3 - - - - - - - - - - - 5 r D+D+D+D+D+D+D+t 4 }.x+x+}.p+# H+% [+D+D+D+D+D+D+D+D+D+D+D+D+h+<+%+S.N.L.C.w.q.0.0.x+x+x+x+x+x+x+x+8.e.i.9 0 d d f i } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+>+w+' $ @ # # # # # # H+H+H+% ' w+,.[+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+>+' $ H+$ ' r 7+D+D+D+D+D+D+].' $ H+H+' ,.D+D+D+D+D+D+[+w+w+w+w+w+w+w+w+w+w+w+w+w+v+D+[+w+w+w+w+w+w+w+w+w+w+w+w+w+r D+[+w+w+w+w+w+w+w+w+w+w+w+w+w+v+D+D+D+D+D+%++ $ r D+D+D+D+D+r ' @ # # # H+H+% < (.~+~+~+~+~+~+~+~+~+~+~+: : : : : : : : : : : : : : l ~+~+~+!+!+]+]+(+!.' $ H+H+$ ' *._+_+_+_+_+_+_+_+_+_+_+<+<+<+;+ +S.M.L.D.w.r.p.x+x+x+8.0.0.0.e.e.e.e.g.h.0 d d f i } w+w+w+w+o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o ", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+[+v+v+v+v+v+v+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+v+7+D+D+D+D+D+D+D+D+l+/.=.=.=.:._.>.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.>.;.;.;.-.-.*.*.*.*.*.*.*.*.*.*.*.*.O.O.O.O.O.Q.Q.Q.S.R.M.L.E.C.w.v.q.0.x+x+0.7.e.e.i.i.g.9 h.0 6 d c f i i } w+w+o o o r r r %.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+2+[.:.>.$.@.@.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+. . .Z Z Z m j j j j j j j j j j j j g g A.A.A.A.B.B.E.E.C.y.w.v.r.q.p.0.x+8.e.e.i.g.h.0 6 d d d c f f i i i } w+o o r r %.,.,.v+].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+~+:.>.@.@.+.X R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R N L S / _ , a a 5 5 5 5 5 5 5 5 5 5 5 5 5 9 9 g.j.l.t.r.r.q.m.m.p.0.0.x+x+0.e.i.g.9 6 d c f i i i i i i } } } w+o r r %.,.v+].[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+2+:.>.@.+.Y X P J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+w+w+w+w+w+w+w+w+w+o r %.,.v+>+[+7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+g+g+2+2+~+[.[.:.>.$.@.+.Y X R P y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+w+o o o o o r r r %.,.,.].>+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+2+~+[.:._.>.#.@.@.+.Y X X R P O y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+o o o r r %.%.,.,.v+].>+[+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+2+~+:.>.$.@.@.+.Y X X X R P P O J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+o o r %.,.,.v+].>+[+[+[+[+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+:.>.#.@.+.X R P P P O O J J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+o r %.,.v+].[+[+7+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+l+l+g+g+g+2+:.>.#.@.+.X R O y+y+y+y+y+y+C G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E K K ^ & , , > = - - - - - - - - - - - - p+p+4 8 1.2.m.p.0.0.0.0.x+x+x+x+x+0.e.i.h.0 d d f i k q %.&.'..+{+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+2+~+[.:.:._.>.#.@.+.Y X X P O y+y+G G F F M M M M N N N N N N N N N N N N N N N N N N N N N N N N N N N N L L ^ ^ , , > > = - - - - - - - - - - - 3 3 4 4 g.9 h.t.u.t.t.n.k.k.p.0.x+x+0.e.e.i.9 0 6 d d j n n *.P.Y.++4+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+2+[.:.>.$.#.@.+.+.Y X X R P P J y+C G F M M N L L S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S ^ , , , > > = - - - - - - - - - - - 3 3 5 5 0 b b A.A.z.z.u.t.t.k.m.0.x+x+0.e.e.i.g.g.h.0 b g G.H.O.W.++5+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+:._.$.@.+.+.X X X R R P P O J y+y+G F M N L L S T U U U U U U U U U U U U U U U U U U U U U U U U U U U U U ( _ _ ) , > > ; = - - - - - - - - - - - 3 5 5 6 d g n n H.G.A.B.z.u.l.k.0.x+x+8.0.0.e.e.e.e.i.j.s.B.I.J.Q.`.<+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+~+:.$.@.+.Y R P J J J J y+y+y+y+y+y+G M M L S T U [ < < < < < < < < < < < < < < < < < < < < < < < < < < < < < } ) ) ) a > > ; = - - - - - - - - - - - 3 5 a c j m t &.'.*.H.G.A.z.u.n.p.x+x+x+x+x+x+x+x+x+x+p.v.y.E.M.S. +<+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+g+g+2+2+2+~+:.>.#.@.+.Y X P J y+y+y+C G G G F F F M N L S T U [ < < w+w+w+w+o o o o o o o o o o o o o o o o o o o o o o o o o k i i f c a a 5 5 3 3 3 3 3 3 3 3 3 5 a a f m m t %.,.'.*.*.H.G.A.B.u.w.r.q.q.m.p.p.0.0.x+x+0.q.w.C.K.M.R.U.%+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+<+6+6+d+d+h+h+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+g+2+~+[.:._.>.>.#.@.+.Y X X R P J y+C G F F M M M N L L S T T U [ [ < < w+w+o o o r r r %.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.t t m m j j d d d c c c a a a a c f f m m t s &.,.'.'.*.O.O.O.J.I.K.D.C.y.w.v.r.q.m.0.x+0.m.r.w.y.D.L.M.R.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S. +`.%+;+<+6+d+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+2+[.:.>.$.@.@.+.+.Y X X R R P O y+y+G F M M N L L S T T T U [ [ [ < < < w+o o r r %.,.,.v+].].].].].].].].].].].].].].].].].].].{.{.!.'.'.*.*.*.*.u u u u n m m m m m m m m t s %.&.,.,.'.!.'.P.P.P.Q.Q.S.R.M.L.E.C.w.v.q.p.x+x+p.m.r.v.w.y.C.E.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.K.L.M.R.S. +%+<+6+h+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+2+~+:.>.@.@.+.X R R R P P P O J J y+y+F M M L L S T U [ [ [ [ < < < < < < w+o r r ,.,.v+>+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+3+3+3+/+/+/+++++++++Y.'.'.'.*.*.s s %.%.&.&.,.,.,.,.v+{.{..+++++++$+;+;+ +S.N.L.D.y.v.m.x+x+0.0.p.m.m.q.r.r.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.w.D.K.M.S.U.%+<+h+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+2+:.>.@.+.Y X P y+y+y+y+y+y+y+y+y+y+y+F M N L T U [ < w+w+w+w+w+w+w+w+w+w+o o r ,.,.].[+[+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+7+7+[+[+>+].v+'.,.,.,.,.'.'.'.v+v+v+].].>+[+[+7+k+D+D+6+;+U.R.L.D.w.q.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+p.r.y.E.M.S. +<+d+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+g+g+2+2+~+~+[.:.>.$.@.+.Y X R P y+y+y+G G G F F M M M N L S T T [ [ < w+w+w+o o o o o r r r %.,.v+].>+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+4+4+_+/+++++Y.Y.P.*.'.*.*.s t s s *.&.'.'.'.{.].].>+[+[+[+7+7+k+D+D+d+<+`.U.R.M.K.C.w.v.r.r.q.m.p.p.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+p.r.u.B.I.J.Q.W./+[+[+[+[+[+[+[+[+[+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+2+~+[.:._.>.$.@.@.+.Y X X R P O y+y+G F F M M N N L L S T T U [ [ < < w+w+o o o r r %.%.,.,.v+].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+7+_+++Y.P.P.*.u u n n m m m m j f m m t t *.'.!..+>+[+[+[+7+7+7+k+k+D+D+d+6+<+%+ +S.R.M.L.K.D.C.w.w.r.q.p.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.n.u.z.A.G.H.P.!.v+v+v+v+v+v+v+v+v+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+~+:.>.$.@.@.+.Y X X X R P P O J y+y+F M M N L L S T T U U [ [ [ < < < w+o o r r %.,.,.v+].>+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+4+_+++P.*.u n j d d c c a a a a a a a f m m u *.Y.@+3+7+7+7+k+k+k+k+D+D+D+h+d+6+<+;+%+`. +U.S.N.L.E.C.w.v.m.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.e.t.s.z.A.n u %.%.%.%.%.%.%.%.%.%.", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+:.>.#.@.+.X R P P P O O J J y+y+y+G F M N L S T U [ [ < < < < < < < < w+o o r %.,.v+>+[+7+7+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+4+++P.u n j a 5 3 3 3 3 3 3 3 3 3 3 5 a d n u *.Y./+7+k+k+D+D+D+D+D+D+D+D+D+h+h+h+d+d+6+6+<+;+ +S.M.K.C.w.r.p.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.e.j.0 b g j m k o o o o o o o o o ", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+h+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+h+h+h+h+f+f+f+f+f+f+f+f+f+f+f+f+f+f+g+g+g+g+g+g+g+2+:.>.#.@.+.X R O y+y+y+y+y+y+y+C G G F M N L S T U [ < w+w+w+w+w+w+w+w+o o o r %.,.v+>+[+7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - 3 5 a j n *.P.++h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+`.S.N.L.D.w.q.p.p.p.p.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.e.i.g.0 6 d c i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+6+<+<+;+%+`. + + + + + + + + + + + + + + + + + + + +X.X.W.Y.~.~.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^._._._._.>.#.@.+.Y X R P O y+y+G G F F M M M M N L S T T U [ < < w+w+o o o o r r r r %.,.v+].>+[+[+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - ; 5 a d n u *.++3+7+7+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+h+<+;+`.S.R.M.K.D.y.w.u.u.u.t.t.j.j.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.g.h.0 d d c f i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+6+<+;+`.U.S.R.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.J.J.H.u u t ` ` Z Z Z Z Z Z Z Z Z Z Z . . . . . .@.@.@.+.+.Y X X R P P J y+C G F M M N L L L S T T U [ [ [ < < w+o o o r r %.,.,.v+v+].>+[+[+7+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - ; 5 a c m u *.!.{+[+[+[+7+7+k+k+k+D+D+D+D+D+D+D+D+D+D+D+h+d+<+;+%+ +S.S.N.M.I.I.F.A.A.z.b b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d d c f f i i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+<+;+ +S.N.M.E.C.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.x.z.b g j h _ _ / S S S S S S S S S S S S S V W W W W X X X R R P P O J y+y+G F M N L L S T U U [ [ [ [ < < < < w+o o r %.,.,.v+>+[+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - ; 3 a c j m t '.{.>+[+[+[+[+7+7+k+D+D+D+D+D+D+D+D+D+D+D+D+h+d+6+<+<+;+%+`. +T.Q.O.H.n n n j c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c f f i i i i } } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+`.S.M.K.C.w.m.p.p.p.p.p.p.p.p.p.p.p.p.p.p.p.p.p.p.p.f.d.5 5 > , , & & { { { { { { { { { { { v x x z z B F O O J J J J y+y+y+y+y+G M N L S T U [ < < < < < < < < < < w+o r %.,.v+>+[+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t *.,.v+].>+[+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+h+d+d+4+/+.+'.&.%.s k } i i i i i i i i i i i i i i i i i i i i i i i i i i i i } } } } } } } } } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+d+d+6+6+<+<+;+ +S.M.K.C.w.q.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+F M N L S T [ [ < w+w+w+w+o o o o o o r %.,.v+>+[+[+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t s ,.v+].].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+[+[+].v+,.%.r o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o ", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+6+<+;+%+`.U.S.R.M.L.E.C.w.r.m.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+F M N L S T [ [ < w+o o o o r r r %.,.,.v+].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t s ,.v+].].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+7+[+[+>+].,.,.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+;+`.U.S.N.M.L.E.D.y.w.v.r.m.p.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+F M N L S T [ [ < w+o o r r %.,.,.v+].>+>+[+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t s ,.v+].].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+k+7+[+[+[+>+].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+<+`.S.R.M.E.C.w.v.r.q.q.m.p.0.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+F M N L S T [ [ < w+o r r ,.,.v+>+[+[+[+7+7+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t s ,.v+].].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+k+7+7+7+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+%+U.N.L.D.w.q.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+F M N L S T [ [ < o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t s ,.v+].].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+d+6+<+<+<+;+%+U.S.M.K.D.w.r.m.x+x+x+8.0.0.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.d.8 5 5 , , & & ~ ! ! ! ! ! ! ! ! ! ! ! ] v x x K M M N Q Q P P H O J J y+y+G F M N L S T U [ 2 l ` =.;./.,+8+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t s ,.v+].].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+h+d+d+6+<+<+<+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+<+<+<+6+d+d+h+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+6+<+;+`. +S.S.R.M.L.E.C.w.v.q.p.x+x+0.7.e.e.i.g.g.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.h.9 5 a , , , & & ~ ! ! ! ! ! ! ! ! ! ! ! { v K L L L W W W W W N Q Q P O y+y+G F M M N L L S S V Z ...;.^.#+|+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t s ,.v+].].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+h+d+6+<+;+`. +S.S.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.S.S. +`.;+<+6+d+h+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+6+<+%+ +S.N.M.K.D.C.w.w.v.r.m.p.0.x+x+7.e.i.g.h.0 6 d d d d d d d d d d d d d d d d d d d d a a ) , , & & & ~ ! ! ! ! ! ! ! ! ! ! { { ^ L S T V . . . .W W W N Q P J y+y+G F F M M M N N W W . .#.>.(.|+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t s ,.v+].].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+h+6+<+`.U.S.N.M.E.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.D.E.M.N.S.U.`.<+6+h+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+<+%+U.R.M.K.C.w.q.q.m.m.p.p.0.0.x+x+0.e.i.g.9 6 d c f i i i i i i i i i i i i i i i i i i i i ) ) / ^ ^ & & ~ ! ! ! ! ! ! ! ! ! ! { ^ ^ S U U Z ` =..... . .W W N Q J y+y+y+y+G G G G F F N W Y +.@.>.:.~+g+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j a 5 3 - - - - - - - - - - - 3 a a f m t s ,.v+].].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+h+<+%+U.R.M.E.y.v.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.v.y.E.M.R.U.%+<+h+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+h+h+d+6+%+U.R.M.E.y.r.p.x+x+x+x+x+x+x+x+8.0.e.e.g.0 6 d c i } w+w+w+w+w+w+w+w+w+o o o o o o o o o o < < : / / ^ ^ ~ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.).;... . .W W R P O J J J J y+y+y+y+y+O R X Y @.#.>.:.2+g+l+l+l+l+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+4+Y.P.u n d 6 3 3 ; - - - - - - - - 3 5 a c f m t %.,.v+].].>+[+[+7+k+D+D+D+D+D+h+h+h+h+h+d+<+%+U.R.M.D.w.r.p.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+p.r.w.E.M.R. +$+4+k+k+k+k+k+k+k+k+k+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+6+<+<+;+%+`.U.S.M.L.D.y.w.q.p.x+x+0.0.7.e.e.e.i.i.g.h.0 d d c f i } w+w+o o o o r r r r r r r r r r r r r r l 2 [ / / ^ ~ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.).;..... . .+.Y Y X X R R P P P O J y+J P R X Y +.@.#.>.:.:.[.~+2+2+2+g+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+7+++Y.P.u n j d 6 6 a a 6 6 a a a 5 a a f f m t s &.,.v+].].>+[+[+7+k+D+D+h+d+6+6+<+<+;+%+`.U.R.M.L.D.y.v.q.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+p.r.u.C.F.J.O.W.@+[+[+[+[+[+[+[+[+[+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+6+<+;+`. +S.R.M.M.K.D.C.w.v.q.m.0.x+8.0.e.e.i.g.9 h.0 6 d d c f f i i } w+o o o r r %.,.,.,.,.,.,.,.,.,.,.,.,.,.` ` 2 [ / ^ ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.).;.;.;.....#.@.@.@.+.+.Y X X R P O y+J O P R X X Y +.@.@.#.>.>.:.[.~+2+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+4+++++P.P.u u n n n n j j j f f f f m m m t s %.&.,.v+].].>+[+[+7+k+D+D+h+6+<+;+`.U.S.R.M.M.K.D.y.w.v.q.p.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.n.t.z.A.G.H.*.'.v+v+v+v+v+v+v+v+v+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+%+ +S.N.M.E.C.w.w.v.r.q.m.p.0.x+x+0.e.e.g.h.0 6 d c c f f i i i i } } w+o o r %.,.,.v+].[+[+[+[+[+[+[+[+[+[+].;.=.` Z U S ^ ~ ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.).).).).^.^.^._._._.$.@.@.+.Y X R O y+y+J O P P R R X X Y +.+.@.$._.:.2+g+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+4+4+_+++++Y.P.P.*.*.*.*.t t t t t t s s %.&.,.,.,.v+].].>+[+[+7+k+D+D+d+<+%+ +S.N.L.E.C.w.w.v.r.q.m.p.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.e.j.s.z.g n t %.r r r r r r r r r ", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+;+ +S.M.K.C.w.m.p.p.0.0.0.0.x+x+x+x+0.e.g.h.6 d c f i i i } } } } } } } w+o r %.,.v+].[+7+k+k+k+k+k+k+k+k+k+k+8+/.;...Z U S ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+{.].].,+'+|+|+2+g+[._.$.@.+.Y R P y+y+y+y+y+J J J O O P R X +.@.$._.[.2+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+h+h+h+h+7+3+/+{+.+{.!.'.,.,.,.,.,.,.,.,.,.,.v+].].>+[+[+7+k+D+D+6+;+ +S.M.E.y.v.m.p.p.0.0.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.e.i.h.b d j i k o o o o o o o o o ", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+d+d+d+6+6+<+;+ +S.M.K.C.w.q.0.x+x+x+x+0.0.0.0.7.e.e.g.h.6 d c f i } w+w+w+w+o o o o o o r %.,.v+].[+[+k+D+D+D+D+D+D+D+D+D+D+k+|+/.;...Z U T ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / ( 2 l ` =.,.v+].>+>+[+[+7+k+D+D+2+[._.$.@.+.Y X P P P O O O J J y+y+y+P R X +.@.#.>.:.2+2+2+2+g+g+l+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+h+4+4+7+4+/+/+@+.+!.!.'.&.*.&.&.,.,.'.'.'.v+v+]..+.+@+/+/+_+5+<+<+%+U.R.M.E.y.v.q.x+x+x+x+x+0.0.0.0.7.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.i.h.0 d d f i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+6+<+;+%+`. +S.R.M.L.E.y.w.r.m.0.x+8.0.e.e.e.e.i.g.g.h.0 6 d c f i i } w+w+o o o r r r %.%.,.v+].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+l+|+,+^.;.....Z U T T U U T / / S S S / ( 2 2 l ` ` =.,.v+].>+>+[+[+7+k+D+D+g+2+:._.>.#.@.+.Y Y X X R R P P J y+y+P R X X Y +.@.#.>.>.:.:.[.~+2+g+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+4+4+_+++++P.P.P.*.*.*.u u t m m m m t t *.'.'.!.{..+>+@+@+++Z.Z.X.T.U.S.R.M.L.D.y.w.r.m.x+x+8.0.e.e.e.i.i.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.h.0 6 d d f i i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+;+`.U.S.R.M.L.E.D.y.w.v.r.m.p.x+x+0.e.e.i.g.h.0 6 6 d d c f f i i } } w+o o r r %.,.,.v+].].>+[+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+l+f+|+'+(.^.;.;.......` ` Z Z Z Z 2 2 2 2 l ` ` =.=.,.,.v+].>+>+[+[+7+k+D+D+l+2+2+[.:._.>.$.#.@.+.+.Y X R P P J y+O P R R X X Y +.+.@.@.$.>.:.[.2+g+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+4+++Y.P.*.u n n j j j j j c c f c c j m u *.'.!..+[+3+/+++Z.T.Q.N.N.M.L.E.D.y.w.v.r.m.p.x+x+0.e.e.i.g.h.0 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d d c c f i i i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+;+`.S.R.M.E.C.w.v.r.q.q.m.p.0.0.x+x+7.e.i.9 0 6 d c f f i i i i i } } } w+o r r ,.,.v+>+[+[+[+7+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+l+f+f+|+|+'+/./.(.^.).^.;.;.=.=.` ` ` ` =.=.=.=.,.,.,.v+].>+>+[+[+7+k+D+D+l+l+g+2+2+2+~+[.:._.>.@.+.+.X R P J y+J J O P P P R R X X +.@.@.>._.[.2+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+4+++P.*.u n j a 6 5 5 5 5 5 5 5 5 5 a a j m u *.Y.@+7+h+_+$+T.Q.M.L.E.y.w.v.r.q.q.m.p.0.0.x+x+e.e.i.h.0 6 d c f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f i i i i i } } } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+<+%+S.N.L.C.w.q.x+x+x+x+x+x+x+x+x+x+x+e.i.9 0 d d f i } } } } } } } } } } o o r ,.,.].[+[+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+7+[+'+[+>+].v+,.,.,.,.,.,.,.,.,.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+g+[._.#.@.+.X R J y+y+y+y+y+y+y+y+y+y+P X Y +.@.>.:.2+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+_+Y.*.n j d 5 3 - - - - - - - - - - 3 5 a j n *.P._+h+h+<+`.S.N.K.C.w.m.x+x+x+x+x+x+x+x+x+x+8.e.i.h.0 d c f i } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+h+h+d+6+6+<+<+;+%+ +S.M.K.D.w.r.m.x+x+x+8.0.0.7.e.e.e.e.g.h.0 d d f i i w+w+w+o o o o o o r r %.,.v+].>+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+k+f+|+8+|+'+/././.^.).;.;.;.=.=.` ` =.=.=.).).).{.].].>+[+[+[+7+7+k+D+D+D+D+D+D+D+D+D+D+D+g+2+:.>.#.@.+.Y X R R P P P O O J y+y+O R X Y +.@.$.>.:.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.(.^.-.t m f a 5 ; - - - - - - - - - - - 3 6 d g n O.T.`.%+U.S.M.K.C.w.r.p.x+x+x+0.0.0.e.e.e.e.i.g.h.6 d d f i } w+w+w+o o o o o o r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r ", "D+D+D+D+D+D+D+D+D+D+h+d+6+<+;+`. +U.S.R.M.L.E.C.w.v.q.p.x+x+0.e.e.e.i.i.g.h.0 6 d d c f i i } w+w+o o o r r r %.,.,.v+].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+f+|+'+/.^.^.;.........` ` ` Z 2 Z 2 2 l ` =.=.).).].>+[+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+l+2+~+:._.>.#.@.+.+.Y X X X R P O J y+J P R X X Y +.@.@.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#...Z Z h h a > ; - - - - - - - - - - - 3 5 6 b g A.J.N.N.M.K.D.y.w.r.m.0.x+x+0.e.e.e.i.g.g.h.0 6 d d c f i i } w+w+o o o r r %.%.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.", "D+D+D+D+D+D+D+D+D+D+h+6+<+%+ +S.N.M.K.D.C.y.w.v.r.m.p.0.x+8.7.e.i.g.h.0 6 d d c c f f i i i } w+o o r r %.,.,.v+].>+[+[+[+[+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+|+'+/.^.....Z Z U U U U U U / / / / / ( Z ` =.;.).].'+7+7+7+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+l+g+2+2+[.:.:.>.>.$.@.+.+.Y X R P O y+J O P R R X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y W V _ _ , , > ; - - - - - - - - - - - 3 4 4 9 0 s.z.B.D.C.w.w.v.r.m.p.0.x+0.e.e.i.g.h.0 6 d d c c f f i i i } w+o o r r %.,.,.v+].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", "D+D+D+D+D+D+D+D+D+D+h+<+%+U.R.M.E.C.w.q.q.m.m.p.p.0.0.x+x+0.e.i.g.9 6 d c f i i i i i i } } } w+o o r %.,.v+>+[+[+7+7+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+|+(.;...Z U U S ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / U Z ..;.^.,+7+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+g+g+2+2+2+2+[._.$.@.+.Y X R O y+y+J J O O P P P P R R R R R R R R R R R R R R R R R R R R R R R R R R R R Q N L ^ ^ , , > = - - - - - - - - - - - - 4 4 8 8 i.k.n.q.q.m.m.p.p.0.0.x+x+0.e.i.g.0 6 d c f i i i i i i } } } w+o r r %.,.v+>+[+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+", "h+h+h+h+h+h+h+h+h+h+6+%+U.R.M.D.w.r.p.x+x+x+x+x+x+x+x+x+x+e.i.g.0 6 d f i } w+w+w+w+w+w+w+w+w+w+o r %.,.].>+[+7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! { ^ T U ` ..^.,+f+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+:.>.@.+.Y X P J J J J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+w+w+w+w+w+w+w+w+o o r ,.,.].>+[+7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "`.`.`.`.`.`.`.`.`.`.U.S.M.L.D.y.v.q.0.x+x+8.0.7.e.e.e.e.i.g.h.0 d d c f i } w+w+o o o o o r r r %.,.v+].>+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! { ^ T U Z ..;./.8+7+k+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+[.:.>.#.@.+.Y X X R R P P P O J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+w+o o o o o r r r %.,.v+].>+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "M.M.M.M.M.M.M.M.M.M.M.K.D.C.w.v.q.m.0.x+0.0.e.e.i.g.9 h.0 6 d d c f f i i } w+o o o r r %.,.,.,.v+].>+[+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! { ^ S U Z ` =.).,+[+[+7+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+2+[.:._.>.#.@.@.+.+.Y X X R P O y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+o o o r r %.,.,.,.v+].>+[+[+7+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "y.y.y.y.y.y.y.y.y.y.y.w.w.v.q.m.p.0.x+x+0.e.i.g.h.0 6 d c c f f i i i i } } w+o o r %.,.,.v+].[+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ S U Z ` =.).{.>+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+g+2+2+~+[.:.:._.$.@.+.+.Y X R P y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+o r r %.,.,.v+>+[+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "p.p.p.p.p.p.p.p.p.p.p.p.p.0.0.0.x+x+x+x+7.e.g.h.6 d c f i i i i } } } } } } w+o r %.,.v+].[+7+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.).].].>+[+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+l+g+g+g+2+[._.$.@.+.Y X P J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+C A K ^ & , , > = - - - - - - - - - - - - p+p+p+7 }.|.8.x+x+x+x+x+x+x+x+x+x+0.e.g.h.6 d c i } w+o r %.,.v+>+[+7+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+e.e.g.0 6 d f i } w+w+w+w+w+o o o o o r %.,.v+>+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+2+[._.$.@.+.Y X P P P P P H H H H H F F F F F F F F F F F F F F F F F F F E K K ^ ^ , , > > - - - - - - - - - - - 3 4 4 4 8 8 1.2.0.0.0.0.0.x+x+x+x+x+0.e.i.9 0 d d f i k m t *.'..+{+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+e.e.g.0 6 d f i } w+o o o o r r r r %.,.v+].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+2+[._.>.#.@.+.Y Y X X W W W N N N N N N N N N N N N N N N N N N N N N N L L L ^ ^ , , , > > > > > > > > > > > > 5 5 5 5 5 9 9 9 g.i.i.e.e.e.0.0.x+x+0.e.e.i.g.h.0 d d j n n u P.Y.++4+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+e.e.g.0 6 d f i } w+o o r r %.,.,.v+].].>+[+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+2+[.:._.>.$.@.@.@. . . . .V V V S S S S S S S S S S S S S S S S S S S S T / / / _ ) ) ) a a a a a a a a a a a a a a a 6 6 6 6 6 0 h.g.i.e.e.7.8.x+x+0.e.e.e.i.g.h.9 0 g G.H.O.W.++5+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+e.e.g.0 6 d f i } o o r r ,.,.v+>+[+[+[+7+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+g+2+2+~+~+[.:.:.^.;.....Z Z Z 2 [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ ( : : ) ) ) ) e e e e e e e e e e e e e e e f f f f c d d 0 h.g.i.e.0.x+x+x+0.0.e.e.e.e.e.j.s.B.I.J.Q.`.<+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+e.e.g.0 6 d f i } o r r ,.,.].[+[+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+8+,+{.).=.r p | < < < < < < < < < < < < < < < < < < < < < < < < } } } } } } } } } } } } } } } } } } } } } } } } i c d 6 h.g.e.0.x+x+x+x+x+x+x+x+x+x+p.r.y.E.M.S. +;+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "e.e.e.e.e.e.e.e.e.e.e.e.e.0.0.0.8.x+x+x+0.e.i.9 0 6 d c f m m t *.'.++/+7+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+7+[+>+].v+,.%.r o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o q m m n g A.z.u.u.r.r.q.q.m.p.p.0.x+x+0.q.w.y.E.M.R.U.`.;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+;+<+<+<+6+6+d+h+h+D+D+D+D+D+D+D+D+D+D+", "h.h.h.h.h.h.h.h.h.h.9 g.i.i.e.e.7.0.x+x+0.e.e.i.g.h.0 6 d g j n u P.W.*+4+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+7+[+[+>+].v+,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.&.*.*.u H.H.G.I.F.E.D.y.w.w.r.q.m.0.x+0.m.r.w.y.D.K.M.N.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.U. +%+;+<+6+d+D+D+D+D+D+D+D+D+D+D+", "d d d d d d d d d d d 6 0 9 g.i.e.0.x+x+x+0.e.e.e.i.i.g.h.0 A.G.H.O.X.$+5+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+k+7+[+[+[+>+>+].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].]..+++Y.W.X.T.Q.S.S.N.M.K.D.y.v.q.p.x+x+p.m.q.v.w.w.C.D.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.K.M.N.S. +%+<+6+h+D+D+D+D+D+D+D+D+D+", "i i i i i i i i i i f c d 6 h.g.i.e.0.x+x+x+8.0.0.0.e.e.e.l.u.B.I.N.Q.%+<+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+k+k+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+4+5+5+5+<+<+<+`.S.N.M.E.y.v.m.x+x+x+0.p.p.m.m.q.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.w.C.K.M.R.U.%+<+h+D+D+D+D+D+D+D+D+D+", "w+w+w+w+w+w+w+w+w+w+} i f d b 0 j.i.m.0.0.x+x+x+x+x+x+x+x+p.v.y.E.M.S. +;+6+h+h+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z Z T ^ ^ { { { { { { { { ! ! ^ ^ S / ( 2 ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+;+ +R.M.E.w.r.p.0.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+p.r.y.E.M.S. +;+d+D+D+D+D+D+D+D+D+D+", "r r r r r r r r r r s t n n n A.B.z.u.w.w.v.r.q.m.p.0.x+x+p.q.w.y.E.L.N.S. +%+;+;+<+<+6+d+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+|+/.^.;...Z U T S S S S S ^ ^ ^ ^ ^ ^ / ( 2 2 ` ` =.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+g+2+2+2+~+[.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.[.~+2+2+g+g+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+%+U.S.M.L.D.w.w.v.r.q.q.m.p.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+p.r.u.B.I.J.O.W.++[+[+[+[+[+[+[+[+[+", ",.,.,.,.,.,.,.,.,.,.,.'.*.P.O.O.J.J.M.L.E.D.y.w.v.q.m.0.x+0.m.r.w.w.C.E.L.M.N.S.S. +%+;+<+6+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+|+|+/.^.;.....` Z Z Z Z Z U ( U U ( ( 2 2 l ` ` =.=.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+2+~+:.:.>.>.#.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.#.>.>.:.[.~+2+g+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+6+<+%+ +S.S.N.M.K.E.C.y.w.r.q.p.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.n.u.z.A.G.H.*.'.v+v+v+v+v+v+v+v+v+", ">+>+>+>+>+>+>+>+>+>+{+@+++++++Z.`.X. +U.R.M.L.D.y.w.q.p.x+x+p.m.q.r.v.w.w.y.D.K.M.R.S. +;+<+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+|+|+'+/.(.^.^.;.;.;.=.=.` ` ` ` l ` ` ` ` =.=.=.,.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+2+~+:.>.$.@.+.+.Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y +.@.@.$._.:.~+2+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+6+<+<+;+%+`. +S.N.M.K.C.w.v.m.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.e.t.s.z.A.n t %.%.%.%.%.%.%.%.%.%.", "k+k+k+k+k+k+k+k+k+k+k+h+h+h+d+d+d+6+6+<+%+U.R.M.E.y.v.m.x+x+x+0.0.0.p.p.p.m.q.w.C.K.N.S.`.<+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+l+f+f+f+|+8+|+,+,+]./.).).,.=.=.=.,.,.,.,.,.,.,.v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+:.>.#.@.+.X R P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P R X +.@.#.>.[.2+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+d+d+d+6+<+`.S.N.L.D.w.r.p.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+0.e.j.0 b g j m k o o o o o o o o o ", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+;+U.R.M.E.y.v.m.m.p.p.0.0.0.x+x+x+0.q.w.C.K.M.S. +;+6+6+d+d+d+h+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+l+f+f+f+|+8+|+,+,+]./.).).,.=.=.,.,.,.).).).v+v+].].>+[+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+l+g+g+g+2+2+:.>.#.@.+.X R O y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+P R X +.@.$._.!+f+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+`.S.N.L.D.w.r.m.m.p.p.p.m.m.m.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.e.i.9 0 6 d f i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+<+%+ +S.N.M.E.C.y.w.w.r.q.m.p.0.x+0.m.r.w.C.E.L.N.S.U. +`.;+<+<+6+d+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+|+|+'+/.(.^.^.;.;.;.=.=.` ` ` ` l ` ` ` =.;.).).{.].>+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+g+2+2+~+[.:.:._.>.#.@.+.Y X R P O y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+P R X Y ...;.^.>+[+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+6+;+`.U.R.M.L.D.C.y.u.u.u.u.t.h.j.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.9 0 6 d d c f i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+6+<+;+`.U.S.R.N.M.K.D.y.w.v.q.p.x+x+p.m.r.w.w.C.D.K.L.M.R.S. +%+;+<+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+|+|+/.^.;.....` Z Z Z Z Z U ( U U ( ( Z ` ` =.;.).].[+[+[+7+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+l+2+~+[.:.>.$.@.@.+.+.Y X X R P P J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+H Q W W . ...=.,.,.v+].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+<+<+%+ +U.S.R.M.I.I.I.A.A.A.b b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d d d c f i i i } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+d+6+<+<+;+%+`.U.S.M.K.D.w.v.m.0.x+0.p.m.m.q.r.v.w.w.C.K.M.R.U.`.<+6+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+|+/.^.;...Z U T S S S S S ^ ^ ^ ^ ^ S U Z Z ..;.).,+8+7+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+:._.$.@.+.+.X X R R R P P O J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+H N N W V Z Z ` r r ,.,.v+].[+[+7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+6+<+<+<+;+%+`.X.P.O.u u n n j f c c c c c c c c c c c c c c c c c c c c c c c c c c c c f f i i i i i } } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+<+%+U.N.L.D.w.q.0.x+x+x+x+x+x+x+x+0.0.q.w.D.L.N.U.%+<+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z Z T ^ ^ { { { { { { { { ! ! ^ ^ U Z Z ;.^.'+f+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+~+_.$.@.+.X R P J J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+F M N L V T ( 1 w+o r %.,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+h+7+/+.+'.,.%.q o } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } w+w+w+w+w+w+w+w+w+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+`.S.R.M.E.y.v.r.q.q.m.p.p.0.0.x+x+m.r.w.D.L.N.S. +;+<+<+<+6+d+d+h+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! { ^ T U Z ..^./.8+k+k+k+D+D+D+D+D+D+D+D+l+l+g+2+2+2+2+~+:.>.#.@.+.Y X P J y+y+y+C G G G F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F M M N L S T U [ < < o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+[+[+].v+,.%.r o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o ", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+<+;+`.U.S.N.M.K.D.C.y.w.v.r.m.p.0.x+p.q.v.w.C.E.L.M.S.S.U.`.%+;+<+6+d+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! { ^ S U Z ` ;./.'+[+7+7+7+k+k+k+D+D+D+l+g+2+~+[.:._.>.$.#.@.+.Y X X R P J y+C G F M M M M N L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L S T T U [ [ < < o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+7+[+[+>+].v+,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+<+<+;+`. +U.S.R.M.L.D.y.w.r.m.0.x+0.p.q.r.v.w.y.D.E.L.M.R.S. +%+<+6+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ S U Z ` =.;.].[+[+[+[+7+7+k+k+D+D+g+2+[.:.>.$.@.@.+.Y Y X X R P P O y+y+G F M M N L L S T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T U U [ [ [ < < < o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+7+[+[+[+>+>+].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+d+6+6+<+<+<+%+U.R.M.K.C.w.r.p.x+x+0.0.p.m.m.q.r.r.w.C.K.M.S.U.%+<+h+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+f+'+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / 2 2 ` =.v+].>+[+[+[+7+7+k+D+D+2+[.:.>.@.+.+.X R R P P P O O J J y+y+F M M L L S T U [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ : < < < < < < o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+k+k+7+7+7+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+[+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+<+`.S.M.K.C.v.m.x+x+x+x+x+x+x+x+x+x+p.r.w.E.M.R. +;+6+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+b+#+^...Z U T ^ { ! ! ! ! ! ! ! ! ! ! ~ ^ ^ / ( Z ` ` ,.).{.].,+,+'+8+f+l+l+2+:.>.@.+.Y X P y+y+y+y+y+y+y+y+y+y+G F M L L T U [ < w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+o r r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+<+;+ +S.N.M.E.y.w.v.r.r.q.m.p.0.x+x+0.q.w.y.E.L.N.S. +%+%+%+%+%+%+%+%+%+%+%+%+%+%+%+%+%+%+%+X.P.-.` Z ( / ^ ~ ! ! ! ! ! ! ! ! ! ! { ^ ^ S T U Z .........;.;.>.^._.:.:.>.#.@.+.Y X R P y+y+y+G G F F F M M M N L S T T [ [ < w+w+w+o o o o o r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r %.,.v+].[+[+7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+<+;+`.U.S.N.M.L.E.D.y.w.v.q.m.0.x+0.m.r.v.w.C.E.L.M.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.J.H.j h _ _ ^ ^ ~ ! ! ! ! ! ! ! ! ! ! { { ^ L L S V V . . . . .@.@.@.@.@.@.@.+.Y X X R P O y+y+G F M M M N L L L S T T U [ [ < < w+w+o o r r r %.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.v+].>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+<+<+;+%+`. +U.R.M.L.D.y.w.r.p.x+x+0.m.q.r.v.w.w.y.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.z.b b a , , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v K K L L N W W W W X X X X Y Y Y X X X R P P O J y+y+F M M N L L S T T U [ [ [ [ < < < w+o o r r %.,.,.].>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+d+d+6+6+<+%+U.R.M.E.y.v.m.x+x+x+0.0.0.p.p.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.k.g.5 5 , , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v x x z z M H H P P P P P P P P P P O O O J J y+y+y+G F M N L S T U [ < < < < < < < < < w+o o r %.,.v+>+[+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+k+k+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+6+;+ +S.M.E.y.v.m.p.p.p.0.0.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+G M M L S T U [ < w+w+w+w+w+w+o o o o o r ,.,.].>+[+7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+%+ +S.N.M.E.C.y.w.v.r.q.m.p.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+G M M L S T U [ < w+w+o o o o r r r r ,.,.v+].>+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+6+<+;+`.U.S.R.M.M.K.D.y.w.v.q.p.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+G M M L S T U [ < w+o o o r r %.,.,.v+].].>+[+[+7+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+d+6+<+<+;+%+`.U.S.M.L.D.w.v.m.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+G M M L S T U [ < w+o o r %.,.,.].>+[+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+h+h+h+<+%+U.R.L.D.w.r.0.x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+5.8 4 3 > , , & ~ ! ! ! ! ! ! ! ! ! ! ! ] v w q+y A C y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+G M M L S T U [ < w+o r %.,.v+>+[+7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+d+<+%+U.R.M.E.y.v.r.q.q.n.k.k.k.e.e.e.e.e.e.e.e.e.e.e.e.d.8 5 5 > , , & & ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ { { v x x z z B M F F F F F F F F F F F F G G G C y+y+y+G F M N L S T U [ 1 l ` =.;.).].'+f+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+6+<+`.U.S.N.M.K.D.B.C.z.z.s.s.s.0 h.h.h.h.h.h.h.h.h.h.9 5 5 a a , , ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ L L L L L L L L L L L L L L L L N M M M F F G y+y+y+G M M N L L S T U Z ...;.^.(.|+f+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+d+<+<+;+`. +S.S.R.N.J.G.G.A.A.g g d d d d d d d d d d d a a c ) ) ) / / / / / / / / / / / / / / / / / T T T T T T T T T T T T T T S L L N M M F G y+y+G F F M M M N L L W . ...>.(.!+g+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+h+h+d+6+<+<+<+;+;+Z.W.P.*.u n m m f f f f f f f f f f e e i i i ) ) : : : : : : : : : : : : : : : : : : [ [ [ [ [ [ [ [ [ [ [ [ [ U T S L N M M G y+y+y+C G G F F F M M W Y +.@.$._.[.2+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+7+[+>+v+,.%.r o w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+< 1 [ T V L N M F y+y+y+y+y+y+y+y+y+y+J P X Y +.#.>.:.2+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+[+[+>+v+,.,.r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r ` ` Z . .W W X X R R R P P O O J y+y+P R X Y +.@.$._.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.[.~+2+2+2+g+l+l+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+7+[+[+>+].v+,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.;.=.;.......@.@.+.+.Y X X R R P O y+y+O P R X Y +.+.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.$.>._.:.[.~+2+g+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+7+7+[+[+[+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+>+].].(.^.(.^._.>.>.$.@.+.+.Y X R P J y+J O P R R X X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y +.@.@.>._.:.~+g+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+k+k+k+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+f+f+f+|+|+2+2+2+2+[._.$.@.+.Y X P J y+y+J J J O O P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P X Y +.@.$._.[.2+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+~+:.>.@.+.Y X P O O J J J J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+P R Y +.@.$._.!+f+k+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+[._.>.@.@.+.Y X X R R P P O J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+P R X Y ...;.^.,+[+[+[+7+7+k+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+2+[.:._.>.#.@.@.+.+.Y X R R P J y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+H Q W W . ...=.).v+].>+>+[+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+g+2+2+~+[.:.:._.$.@.+.+.X X P O y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+H N N W V Z Z ` r %.,.,.v+>+[+[+7+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+l+l+g+2+[._.$.@.+.X R P y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+y+G M N L V U ( 1 | o r %.,.v+>+[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+2+:._.$.@.+.Y X P P P P P P P H F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F M N L S T U [ < < o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+2+~+:._.>.@.@.+.Y Y Y X W W W N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N L S T T U [ [ < < o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+g+2+~+[.:._.>.$.#.@.@. . . . .V V V T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T U [ [ [ < < < o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+l+l+g+2+2+2+~+[.[._.^.;.....` Z Z [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ < < < < < < o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+", "D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+k+[+>+].,.%.r o w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+w+o o r ,.v+].[+7+k+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+"}; gambit-0.2010.09.01/src/gui/bitmaps/gambitrc.rc0000644000076500007650000000021311350032206015554 00000000000000 #include gambit_icn ICON "gambit.ico" efg_icn ICON "efg.ico" nfg_icn ICON "nfg.ico" gambit BITMAP "gambit.bmp" gambit-0.2010.09.01/src/gui/bitmaps/label.xpm0000644000076500007650000000311111350032206015243 00000000000000/* XPM */ static char * label_xpm[] = { "24 24 59 1", " c None", ". c #FAFAFA", "+ c #646464", "@ c #CFCFCF", "# c #BEBEBE", "$ c #000000", "% c #999999", "& c #F3F3F3", "* c #272727", "= c #292929", "- c #ECECEC", "; c #252525", "> c #8A8A8A", ", c #171717", "' c #0C0C0C", ") c #878787", "! c #7B7B7B", "~ c #4B4B4B", "{ c #949494", "] c #2E2E2E", "^ c #F5F5F5", "/ c #848484", "( c #EBEBEB", "_ c #BDBDBD", ": c #0D0D0D", "< c #D0D0D0", "[ c #0F0F0F", "} c #DADADA", "| c #BCBCBC", "1 c #020202", "2 c #EFEFEF", "3 c #1E1E1E", "4 c #F0F0F0", "5 c #090909", "6 c #F9F9F9", "7 c #393939", "8 c #828282", "9 c #E5E5E5", "0 c #A1A1A1", "a c #414141", "b c #C6C6C6", "c c #282828", "d c #939393", "e c #737373", "f c #656565", "g c #969696", "h c #494949", "i c #E0E0E0", "j c #A0A0A0", "k c #353535", "l c #515151", "m c #444444", "n c #6A6A6A", "o c #4E4E4E", "p c #5D5D5D", "q c #1A1A1A", "r c #161616", "s c #ADADAD", "t c #8C8C8C", " ", " ", "........................", "........................", "........................", "........................", "........................", ".........+@.............", "........#$%.............", ".......&*=+..-;>,').....", ".......!~{]..^$/(_:.....", "......<[}|12.<3..45.....", ".....678.9$_.0a..bc.....", ".....d$$$$$).ef..gh.....", "....i:j...kl.m>..fn.....", "....ok6...pq.rs..kt.....", "........................", "........................", "........................", "........................", "........................", "........................", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/layout.xpm0000644000076500007650000000700611350032206015510 00000000000000/* XPM */ static char * layout_xpm[] = { "24 24 143 2", " c None", ". c #000000", "+ c #D3D3D3", "@ c #F6F6F6", "# c #FFFFFF", "$ c #F9F9F9", "% c #DADADA", "& c #585858", "* c #C7C7C7", "= c #D1D1D1", "- c #D6D6D6", "; c #D1940C", "> c #FEFEFE", ", c #FDFDFD", "' c #C0C0C0", ") c #E1E1E1", "! c #F0F0F0", "~ c #9B9B9B", "{ c #EED680", "] c #FCFCFB", "^ c #FBFBFB", "/ c #AFAFAE", "( c #E9E9E9", "_ c #DFDFDF", ": c #8F8F8F", "< c #FAFAF9", "[ c #F9F9F8", "} c #A4A4A3", "| c #F4F4F4", "1 c #CFCFCF", "2 c #A2A2A2", "3 c #414141", "4 c #1A1A1A", "5 c #7F7F7F", "6 c #C8C8C7", "7 c #F8F8F7", "8 c #F8F7F6", "9 c #9E9E9E", "0 c #C7C7C6", "a c #7E7E7D", "b c #F7F6F5", "c c #F6F6F4", "d c #F4F3F2", "e c #DEDDDC", "f c #D3D2D0", "g c #B7B7B5", "h c #9F9E9D", "i c #706F6F", "j c #65625A", "k c #50504F", "l c #F5F4F3", "m c #F2F2F0", "n c #E4E4E2", "o c #DAD9D7", "p c #D8D8D6", "q c #CDCCCA", "r c #AFAEAC", "s c #88847B", "t c #4F4F4F", "u c #F3F3F1", "v c #EFEFED", "w c #EEEDEB", "x c #EDECEA", "y c #E9E8E6", "z c #D5D4D3", "A c #C4C3C2", "B c #8F8A81", "C c #F6F5F4", "D c #F5F5F3", "E c #7C7B7B", "F c #282827", "G c #323232", "H c #323231", "I c #9A9A98", "J c #F1F1EF", "K c #F1F0EE", "L c #EAE9E7", "M c #E5E4E2", "N c #E4E3E0", "O c #D2D1CE", "P c #8D887E", "Q c #F3F2F1", "R c #7A7A79", "S c #191919", "T c #F0EFED", "U c #EFEEEC", "V c #787776", "W c #747472", "X c #E2E1DE", "Y c #E1DFDC", "Z c #979288", "` c #F0F0EE", " . c #272727", ".. c #616160", "+. c #5C5C5B", "@. c #A49E93", "#. c #ECEBE9", "$. c #E8E7E4", "%. c #E3E2DF", "&. c #E2E0DD", "*. c #E1E0DC", "=. c #E0DFDB", "-. c #A19C90", ";. c #314E6C", ">. c #E9E8E5", ",. c #E5E4E1", "'. c #E3E2DE", "). c #DFDEDA", "!. c #DEDDD9", "~. c #DDDCD8", "{. c #A19B90", "]. c #7590AE", "^. c #E7E6E3", "/. c #E7E5E2", "(. c #B6B5B2", "_. c #DCDBD7", ":. c #2F2F2E", "<. c #72716F", "[. c #DBD9D5", "}. c #D9D7D3", "|. c #9F998D", "1. c #DDDBD7", "2. c #DCDAD6", "3. c #D8D6D2", "4. c #9E988D", "5. c #E0DEDA", "6. c #D8D6D1", "7. c #D7D5D1", "8. c #9D978B", "9. c #E1DFDB", "0. c #DEDCD8", "a. c #D7D6D1", "b. c #D5D3CE", "c. c #9B958A", "d. c #999891", "e. c #A39E92", "f. c #A39D92", "g. c #A39D91", "h. c #A29C90", "i. c #A19B8F", "j. c #9D978C", "k. c #9B968A", "l. c #676359", " ", " . . . . . . . . . . . . . ", " . + @ # # # # # # # # $ % & . ", " . @ # # # # # # # # # # * = - . ", "; ; ; ; ; # # # # # > # > , ' ) ! ~ . ", "; { { { ; # # # > , ] , ] ^ / ( # _ : . ", "; { { { ; # > , ] ^ < ^ < [ } ! # | 1 2 . ", "; { { { ; 3 4 5 6 [ 7 [ 7 8 9 . . . . . . . ", "; { { { ; ^ < 0 a 8 b 8 b c d e f g h i j . ", "; { { { ; [ 7 8 k c l c l d m n o p q r s . ", "; ; ; ; ; 8 b c t d u d u m v w x y z A B . ", " . # C D E F G H I m J K w . L M N O P . ", " . # d Q m R S R T K T U V . W N X Y Z . ", " . # d Q m ` .K T K T ... . . +.X Y @.. ", " . # ` v v U w x x x x #.$.. %.&.*.=.-.. ", ";.;.;.;.;.;.;.;.;.;.;.;.>.>.,.. '.).!.~.{.. ", ";.].].].].].].].].].].;.^./.(.. =.!.~._.{.. ", ";.].].].].].].].].].].;.:.. . <.!._.[.}.|.. ", ";.].].].].].].].].].].;.'.*.*.!.1.2.}.3.4.. ", ";.;.;.;.;.;.;.;.;.;.;.;.*.).5.1.2.}.6.7.8.. ", " . = 9.5.).!.=.!.5.!.5.0.0.2.2.3.a.b.c.. ", " . d.e.@.f.g.f.-.h.-.h.i.{.|.|.j.j.k.l.. ", " . . . . . . . . . . . . . . . . . . ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/move.xpm0000644000076500007650000000137711350032206015146 00000000000000/* XPM */ static char * move_xpm[] = { "24 24 3 1", " c None", ". c #1F1F1F", "+ c #202020", " ", " ", " ", " .+++. ", " +++++ ", " +++++ ", " .+++. ", " ++++++. ", " +++++++++ ", " +++++++++ ", " +++++++++ ", " .+++++++. ", " .+++++. ", " .+++++. ", " +++++++++ ", " +++++++++++ ", " .+++++++++++. ", " ++++++++++++. ", " +++++++++++++ ", " +++++++++++++ ", " +++++++++++++ ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/new.xpm0000644000076500007650000000640311350032206014764 00000000000000/* XPM */ static char * new_xpm[] = { "24 24 127 2", " c None", ". c #000000", "+ c #0E0E0E", "@ c #282828", "# c #616161", "$ c #D3D3D3", "% c #F6F6F6", "& c #FFFFFF", "* c #F9F9F9", "= c #F9F9F8", "- c #E7E7E7", "; c #E4E4E4", "> c #CDCDCD", ", c #1F1F1F", "' c #EFEFEE", ") c #AFAFAE", "! c #E9E9E9", "~ c #B3B3B3", "{ c #383838", "] c #FEFEFE", "^ c #FDFDFD", "/ c #EEEEEE", "( c #A4A4A3", "_ c #F0F0F0", ": c #F4F4F4", "< c #ABABAB", "[ c #050505", "} c #FCFCFB", "| c #FBFBFB", "1 c #F2F2F2", "2 c #9E9E9E", "3 c #FAFAF9", "4 c #D4D4D3", "5 c #B9B7B6", "6 c #838381", "7 c #848381", "8 c #6A6763", "9 c #F8F8F7", "0 c #F8F7F6", "a c #F3F2F1", "b c #E0E0DF", "c c #DCDAD8", "d c #CACAC8", "e c #B6B6B4", "f c #72706C", "g c #F7F6F5", "h c #F6F6F4", "i c #F4F3F2", "j c #F1F0EF", "k c #F0EFED", "l c #E5E4E2", "m c #C4C3C0", "n c #817D74", "o c #F5F4F3", "p c #EBEAE8", "q c #E1DFDC", "r c #8B867D", "s c #F3F3F1", "t c #F2F2F0", "u c #EFEFED", "v c #EEEDEB", "w c #EDEDEB", "x c #E5E5E2", "y c #A49E93", "z c #F6F5F4", "A c #F5F5F3", "B c #F1F1EF", "C c #F1F0EE", "D c #ECEBE9", "E c #E7E6E3", "F c #E2E1DF", "G c #E4E3E0", "H c #F0F0EE", "I c #EFEEEC", "J c #E8E7E5", "K c #E5E4E1", "L c #E2E1DE", "M c #EDECEA", "N c #E8E7E4", "O c #E3E2DF", "P c #E2E0DD", "Q c #E1E0DC", "R c #E0DFDB", "S c #A19C90", "T c #E9E8E5", "U c #E6E4E1", "V c #E3E2DE", "W c #DFDEDA", "X c #DEDDD9", "Y c #DDDCD8", "Z c #A19B90", "` c #E9E8E6", " . c #E7E5E2", ".. c #E4E3DF", "+. c #DCDBD7", "@. c #E6E5E2", "#. c #E5E4E0", "$. c #E2E1DD", "%. c #DBD9D5", "&. c #D9D7D3", "*. c #9F998D", "=. c #E4E2DF", "-. c #DDDBD7", ";. c #DCDAD6", ">. c #D8D6D2", ",. c #9E988D", "'. c #EDEDED", "). c #E1E0DD", "!. c #E0DEDA", "~. c #D8D6D1", "{. c #D7D5D1", "]. c #9D978B", "^. c #D1D1D1", "/. c #E1DFDB", "(. c #DEDCD8", "_. c #D7D6D1", ":. c #D5D3CE", "<. c #9B958A", "[. c #999891", "}. c #A39E92", "|. c #A39D92", "1. c #A39D91", "2. c #A29C90", "3. c #A19B8F", "4. c #9D978C", "5. c #9B968A", "6. c #676359", " ", " . . . . . . . . . . . . . + @ # ", " . $ % & & & & & & & & * = = - ; > , ", " . % & & & & & & & & & & = ' ) ! & ~ { ", " . & & & & & & & ] & ] ^ = / ( _ & : < [ ", " . & & & & & ] ^ } ^ } | = 1 2 . . . . . ", " . & & & ] ^ } | 3 | 3 = = : 4 5 6 7 8 . ", " . & ] ^ } | 3 = 9 = 9 0 = a b c d e f . ", " . & } | 3 = 9 0 g 0 g h i j k k l m n . ", " . & 3 = 9 0 g h o h o i i i i p q q r . ", " . & 9 0 g h o i s i s t u v w x q q y . ", " . & z A i i s t B t B C v D E F G q y . ", " . & i a t H u C k C k I D J K G L q y . ", " . & i a t H u C k C k I D J K G L q y . ", " . & H u u I v M M M M D N E O P Q R S . ", " . & w M D D D p T p T T K U V W X Y Z . ", " . & p ` ` J N N E N E ...V R X Y +.Z . ", " . & E @.@.@.K U #.U #...$.R X +.%.&.*.. ", " . * G O V =...$.V $.V Q Q X -.;.&.>.,.. ", " . '.).q Q R $.R Q R Q W !.-.;.&.~.{.].. ", " . ^./.!.W X R X !.X !.(.(.;.;.>._.:.<.. ", " . [.}.y |.1.|.S 2.S 2.3.Z *.*.4.4.5.6.. ", " . . . . . . . . . . . . . . . . . . ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/newcol.xpm0000644000076500007650000000270311350032206015461 00000000000000/* XPM */ static char * newcol_xpm[] = { "24 24 50 1", " c None", ". c #000000", "+ c #FFFFFF", "@ c #ABABAB", "# c #DEDEDE", "$ c #E0E0E0", "% c #969696", "& c #E1E1E1", "* c #E2E2E2", "= c #E3E3E3", "- c #E4E4E4", "; c #E5E5E5", "> c #E6E6E6", ", c #E7E7E7", "' c #E8E8E8", ") c #D4D4D4", "! c #E9E9E9", "~ c #EAEAEA", "{ c #D6D6D6", "] c #989898", "^ c #999999", "/ c #9A9A9A", "( c #9B9B9B", "_ c #9C9C9C", ": c #9D9D9D", "< c #909090", "[ c #EED680", "} c #D2D2D2", "| c #BFBFBF", "1 c #979797", "2 c #9E9E9E", "3 c #9F9F9F", "4 c #A0A0A0", "5 c #939393", "6 c #B1B1B1", "7 c #A1A1A1", "8 c #A2A2A2", "9 c #A3A3A3", "0 c #A4A4A4", "a c #A5A5A5", "b c #EBEBEB", "c c #EDEDED", "d c #A6A6A6", "e c #A7A7A7", "f c #A8A8A8", "g c #D8D8D8", "h c #D9D9D9", "i c #929292", "j c #C9B56B", "k c #898989", " ", " ", "...................... ", ".+++@+++++++++++++++#. ", ".+$$%$$$$$$&*==-;>,'). ", ".+$$%$$.....=--;>'!~{. ", ".@%%%%%%...]^///(__:<. ", ".+$$%[[[[.[[[[/}}}}}|. ", ".+$$%[[[[[[[[[(}}}}}|. ", ".+$$%[[[[[[[[[_}}}}}|. ", ".+$&1]]^//(__::223445. ", ".+&*][[[[[[[[[2}}}}}6. ", ".+-;/[[[[[[[[[4}}}}}6. ", ".+;>/[[[[[[[[[4}}}}}6. ", ".+>,(__:22447888900a1. ", ".+'!_[[[[[[[[[8}}}}}|. ", ".+!~:[[[[[[[[[9}}}}}|. ", ".+~b2[[[[[[[[[0}}}}}|. ", ".+bc344788900aaddeff/. ", ".!ghijjjjjjjjjk||||||. ", "...................... ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/newplayer.xpm0000644000076500007650000001073111350032206016200 00000000000000/* XPM */ static char * newplayer_xpm[] = { "24 24 204 2", " c None", ". c #E5D087", "+ c #000000", "@ c #8E7F4F", "# c #DBCB9A", "$ c #F2EACC", "% c #DCCD9A", "& c #111110", "* c #4B4844", "= c #0A0500", "- c #CEC394", "; c #F0E9CE", "> c #FBFAF6", ", c #EFE7CA", "' c #DCC986", ") c #1D1D1D", "! c #060606", "~ c #444444", "{ c #252525", "] c #AFA87E", "^ c #F0E8CD", "/ c #F0E8CB", "( c #D7C482", "_ c #181817", ": c #130A00", "< c #4C3A29", "[ c #150B01", "} c #0E0700", "| c #1D1003", "1 c #261504", "2 c #361F05", "3 c #8C8468", "4 c #F1E4B1", "5 c #F7EFD1", "6 c #DCCE9A", "7 c #1B0F01", "8 c #412405", "9 c #C5751C", "0 c #C5741D", "a c #C1731D", "b c #C2731C", "c c #C8741A", "d c #7C450C", "e c #080400", "f c #EFE1B0", "g c #EADCA4", "h c #E4D69E", "i c #8E804F", "j c #2C1804", "k c #5B3107", "l c #D17A1D", "m c #D17B1E", "n c #D37D1F", "o c #D07A1D", "p c #CD761A", "q c #79430C", "r c #2D1905", "s c #311A04", "t c #A95F13", "u c #CC7519", "v c #CC761A", "w c #CC751A", "x c #CB7519", "y c #CA7218", "z c #B66614", "A c #2F1904", "B c #3A1F05", "C c #9B580F", "D c #BE6A15", "E c #83490F", "F c #261402", "G c #2E1803", "H c #8A4C0E", "I c #B56413", "J c #422305", "K c #472605", "L c #934F0D", "M c #321B03", "N c #AC6011", "O c #A55C10", "P c #653607", "Q c #351C02", "R c #0D1112", "S c #292626", "T c #593615", "U c #341B04", "V c #351D04", "W c #341C04", "X c #291704", "Y c #452F1A", "Z c #181E25", "` c #090B0D", " . c #25282C", ".. c #91999F", "+. c #899DB0", "@. c #6F7A84", "#. c #241E1A", "$. c #180E04", "%. c #1A120C", "&. c #222223", "*. c #646F7A", "=. c #455666", "-. c #3D4D5E", ";. c #090D0F", ">. c #282C31", ",. c #A0ABB7", "'. c #738EAA", "). c #7591AC", "!. c #506375", "~. c #899097", "{. c #CCCCCC", "]. c #C5C6C8", "^. c #8D99A5", "/. c #6F7F91", "(. c #556C83", "_. c #586E84", ":. c #45586B", "<. c #0A0D10", "[. c #121415", "}. c #90989E", "|. c #7C95AD", "1. c #6D89A5", "2. c #6F8BA6", "3. c #5C748B", "4. c #7C8A99", "5. c #F2F3F4", "6. c #E7EAED", "7. c #A7B8C7", "8. c #7E95AC", "9. c #66809B", "0. c #5D7995", "a. c #4E667D", "b. c #374656", "c. c #0A0C10", "d. c #131516", "e. c #96A1AD", "f. c #66829E", "g. c #67839E", "h. c #6884A0", "i. c #597088", "j. c #607285", "k. c #E6E8EB", "l. c #C9D3DB", "m. c #9AACBD", "n. c #7990A8", "o. c #BBC6D2", "p. c #6C859E", "q. c #526E8B", "r. c #4E6883", "s. c #0C1015", "t. c #191D20", "u. c #8A9EB0", "v. c #5C7895", "w. c #5E7A97", "x. c #607C98", "y. c #617D99", "z. c #52677C", "A. c #CFD5DB", "B. c #B8C3D0", "C. c #68829C", "D. c #BBC7D1", "E. c #D5DBE1", "F. c #CAD3DB", "G. c #4D6A87", "H. c #45617E", "I. c #0C1016", "J. c #1D2227", "K. c #8296AA", "L. c #56728F", "M. c #587491", "N. c #597692", "O. c #5A7692", "P. c #405267", "Q. c #B8C3CC", "R. c #A9B8C6", "S. c #587490", "T. c #4E6A87", "U. c #4A6684", "V. c #44617E", "W. c #3F5A78", "X. c #0D131A", "Y. c #171E27", "Z. c #748A9E", "`. c #4F6B88", " + c #536F8C", ".+ c #53708C", "++ c #3A4E63", "@+ c #6F8498", "#+ c #8FA0B2", "$+ c #4E6B88", "%+ c #4C6886", "&+ c #486482", "*+ c #3C5774", "=+ c #354F69", "-+ c #040608", ";+ c #182330", ">+ c #3E5773", ",+ c #3D5671", "'+ c #3E5672", ")+ c #3F5874", "!+ c #405A74", "~+ c #3C5670", "{+ c #3B526C", "]+ c #293B50", " ", " . . ", " + + + + + @ # $ $ % ", " & + * * = + + - ; > > , ' ", " ) ! * ~ { + + + ] ^ > > / ( ", " _ : < [ } | 1 2 3 4 5 5 6 ", " 7 8 9 0 a b c d e f g h i ", " j k l m n o p q r ", " s t u v w x y z A ", " B C D E F G H I J ", " K L M N O K P Q ", " R S T U V W X Y Z ` ", " ...+.@.#.$.%.&.*.=.-.;. ", " >.,.'.).!.~.{.].^./.(._.:.<. ", " [.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c. ", " d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s. ", " t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I. ", " J.K.L.M.N.O.P.Q.R.S.q.T.U.V.W.X. ", " Y.Z.`.q. +.+++@+#+$+%+&+H.*+=+-+ ", " + ;+>+,+'+)+)+!+>+>+>+~+{+{+]++ ", " + + + + + + + + + + + + + + ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/newrow.xpm0000644000076500007650000000266411350032206015521 00000000000000/* XPM */ static char * newrow_xpm[] = { "24 24 49 1", " c None", ". c #000000", "+ c #FFFFFF", "@ c #ABABAB", "# c #DEDEDE", "$ c #E0E0E0", "% c #969696", "& c #E1E1E1", "* c #E2E2E2", "= c #E3E3E3", "- c #E4E4E4", "; c #E5E5E5", "> c #E6E6E6", ", c #E7E7E7", "' c #E8E8E8", ") c #D4D4D4", "! c #E9E9E9", "~ c #EAEAEA", "{ c #D6D6D6", "] c #979797", "^ c #989898", "/ c #999999", "( c #9A9A9A", "_ c #9B9B9B", ": c #9C9C9C", "< c #9D9D9D", "[ c #909090", "} c #D2D2D2", "| c #BFBFBF", "1 c #9E9E9E", "2 c #9F9F9F", "3 c #A0A0A0", "4 c #939393", "5 c #EED680", "6 c #D9C374", "7 c #A1A1A1", "8 c #A2A2A2", "9 c #A3A3A3", "0 c #A4A4A4", "a c #A5A5A5", "b c #EBEBEB", "c c #EDEDED", "d c #A6A6A6", "e c #A7A7A7", "f c #A8A8A8", "g c #D8D8D8", "h c #D9D9D9", "i c #929292", "j c #898989", " ", " ", "...................... ", ".+++@+++++++++++++++#. ", ".+$$%$$$$$$&*==-;>,'). ", ".+$$%$$$$$&*=--;>'!~{. ", ".@%%%%%%%]^^/(((_::<[. ", ".+$$%}}}}}}}}}(}}}}}|. ", ".+$$%}}}}}}}}}_}}}}}|. ", ".+$$%}}}}}}}}}:}}}}}|. ", ".+$.]^^/((_::<<112334. ", ".+&..5555555551555556. ", ".+-...555555553555556. ", ".+;..5555555553555556. ", ".+>._::<11337888900a]. ", ".+'!:}}}}}}}}}8}}}}}|. ", ".+!~<}}}}}}}}}9}}}}}|. ", ".+~b1}}}}}}}}}0}}}}}|. ", ".+bc233788900aaddeff(. ", ".!ghi|||||||||j||||||. ", "...................... ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/newtable.xpm0000644000076500007650000000272411350032206015776 00000000000000/* XPM */ static char * newtable_xpm[] = { "24 24 51 1", " c None", ". c #000000", "+ c #D3D3D3", "@ c #ABABAB", "# c #A6A6A6", "$ c #C8C8C8", "% c #A2A2A2", "& c #E5D087", "* c #E4CF88", "= c #8F8051", "- c #DACA9B", "; c #F2EACC", "> c #DCCD9A", ", c #CDC399", "' c #F0E9CE", ") c #FBFAF6", "! c #EFE7CA", "~ c #DCC986", "{ c #ADA782", "] c #F0E8CD", "^ c #F0E8CB", "/ c #D2C084", "( c #868686", "_ c #F2F2F2", ": c #C4C4C4", "< c #EEEDED", "[ c #928A70", "} c #F1E4B1", "| c #F7EFD1", "1 c #DFD4A9", "2 c #C9C9C9", "3 c #E9E9E9", "4 c #EFE1B0", "5 c #EADCA4", "6 c #E4D69E", "7 c #9C9067", "8 c #A3A3A3", "9 c #C7C7C7", "0 c #A1A1A1", "a c #F1F1F1", "b c #C3C3C3", "c c #C5C5C5", "d c #ACACAC", "e c #ADADAD", "f c #AAAAAA", "g c #8C8C8C", "h c #CCCCCC", "i c #D1D1D1", "j c #D2D2D2", "k c #CECECE", "l c #B4B4B4", " ", " ..................... ", " .++++@++++@++++@+++#. ", " .+$$$%$$$$%$$$$&*$$#. ", " .+$$$%$$$$%$$=-;;>$#. ", " .+$$$%$$$$%$$,'))!~#. ", " .@%%%%%%%%%%%{]))^/(. ", " .+$$$%____:_<[}||1_2. ", " .+$$$%____:__34567_2. ", " .+$$$%____:________2. ", " .+$$$%____:________2. ", " .@%%%%:::::::::::::8. ", " .+$$$%_________:___2. ", " .+$$$%_________:___2. ", " .+$$$%_________:___2. ", " .+$$$%_________:___2. ", " .@%%%%:::::::::::::8. ", " .+9990aaaabaaaabaaa9. ", " .+9990aaaabaaaabaaa9. ", " .+9990aaaabaaaabaaa2. ", " .cdefghijkfhijkfhhhl. ", " ..................... ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/newtree.xpm0000644000076500007650000000536611350032206015653 00000000000000/* XPM */ static char * newtree_xpm[] = { "24 24 94 2", " c None", ". c #E5D087", "+ c #E5CB83", "@ c #FF0000", "# c #8E7F4F", "$ c #DBCB9A", "% c #F2EACC", "& c #DCCD9A", "* c #EA4040", "= c #CAA0A0", "- c #CEC394", "; c #F0E9CE", "> c #FBFAF6", ", c #EFE7CA", "' c #DCC986", ") c #C0C0C0", "! c #00FF00", "~ c #20BF00", "{ c #A9926E", "] c #F0E8CD", "^ c #F0E8CB", "/ c #D7C482", "( c #20F420", "_ c #80D580", ": c #7E9D5E", "< c #8B7C61", "[ c #F1E4B1", "} c #F7EFD1", "| c #DCCE9A", "1 c #A0CAA0", "2 c #7B4E4E", "3 c #EEE0AF", "4 c #EADCA4", "5 c #E4D69E", "6 c #9E6C43", "7 c #800808", "8 c #D18C8C", "9 c #80470E", "0 c #008E1C", "a c #60E060", "b c #800000", "c c #806060", "d c #F42020", "e c #F12B2B", "f c #789595", "g c #00FFFF", "h c #15EA15", "i c #4BE64B", "j c #4DE6E6", "k c #699769", "l c #801A1A", "m c #806B6B", "n c #E06060", "o c #F81515", "p c #D28B8B", "q c #808080", "r c #803131", "s c #E35555", "t c #C9A5A5", "u c #D58080", "v c #00B871", "w c #309F00", "x c #CF0000", "y c #F61B1B", "z c #CE9595", "A c #00D5AA", "B c #DF0000", "C c #EF3030", "D c #D09090", "E c #7AD77A", "F c #95CE95", "G c #9CC095", "H c #B29595", "I c #C79595", "J c #FC0B0B", "K c #C7ABAB", "L c #FA1010", "M c #00F1E3", "N c #13F913", "O c #009C39", "P c #2BF12B", "Q c #75D875", "R c #40BFBF", "S c #4DB34D", "T c #30EF30", "U c #90D090", "V c #DC6B6B", "W c #6EB5B5", "X c #6BDC6B", "Y c #35EE35", "Z c #40EA40", "` c #54E354", " . c #ABC7AB", ".. c #B5C4B5", " ", " . + @ @ @ ", " # $ % % & * * = ", " - ; > > , ' ) ) ", " ! ! ! ~ { ] > > ^ / ", " ! ( _ _ : < [ } } | ", " ! 1 ) 2 3 4 5 6 @ @ ", " ! _ ) 7 @ @ @ @ 8 ", " @ @ 9 0 ! a ) b c ) ) ) ) ", " @ d e f g h i b c ", " @ d = ) j g k ! ! l m @ @ @ @ n ", " o p ) g g q ! r m @ e s s s t ", " @ u ) v v ! ! ! w b x y z ) ", "@ @ n ) A A q ! ! ! ~ b B C ) ", "@ @ D g g q E F G H I J e ", "K s L g g q @ @ @ @ ", " @ @ M M q ! ! ! ! N L o o z ", " @ @ O O ! P P P P Q ) ) ) ) ", " @ @ R g S ! T ) ) ) ) ) ", " @ @ q g ! ! U ", " V W g X Y Z ", " ! ! ! ! ! ", " ! ! ! ! ` ", " . . ... "}; gambit-0.2010.09.01/src/gui/bitmaps/next.xpm0000644000076500007650000000226311350032206015151 00000000000000/* XPM */ static char * next_xpm[] = { "24 24 32 1", " c None", ". c #000000", "+ c #6C95BB", "@ c #A4BDD5", "# c #5B88B2", "$ c #A7BFD6", "% c #9EB8D1", "& c #5080AD", "* c #B5C9DC", "= c #AFC5DA", "- c #B2C7DB", "; c #B6CADD", "> c #A2BBD3", ", c #9CB7D1", "' c #080D11", ") c #9BB6D0", "! c #A0BAD3", "~ c #9AB5CF", "{ c #97B3CE", "] c #5F8BB4", "^ c #91B0CC", "/ c #98B4CF", "( c #95B2CE", "_ c #4C79A3", ": c #507FAB", "< c #4A77A1", "[ c #4C7AA5", "} c #2A435B", "| c #49749C", "1 c #3F6588", "2 c #456F96", "3 c #375978", " ", " ", " ", " . ", " .. ", " .+. ", " .@#. ", " ........$%&. ", " .*=-;;;;>@,&' ", " .)!,,,)~,!,{]. ", " .^%~/~),%,,!(_. ", " .:<[[[[[[[[[[<}. ", " .|11111111111}. ", " .|1111111111}. ", " .2333333111}. ", " ........31}. ", " .3}. ", " .}. ", " .. ", " . ", " ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/nfg.ico0000644000076500007650000000137611350032206014717 00000000000000 è( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøˆˆÿÿÿÿÿÿÿÿÿÿÿÿªªªÿÿÿÿÿÿÿÿÿÿÿúªªªÿÿÿÿÿÿÿÿÿˆˆˆªÿÿÿÿÿÿÿÿÿÿÿù™"ª¨ÿÿÿÿÿÿÿÿÿÿÿ™™"ª¨ÿÿÿÿÿÿÿÿÿùŸÿ"ªˆˆˆÿÿÿÿÿÿ™ÿÿ"ÿúªªªÿøˆˆÿùŸÿÿ÷ÿªªªÿÿ™™˜ˆ™ÿÿÿ"ÿÿÿÿÿù™™Ÿ™˜ÿÿÿ"ÿÿˆˆˆ™ÿÿÿ™˜ÿÿ"ÿúª¡˜ÿÿÿÿ™ˆÿÿ"ÿÿªª¡˜ÿÿÿù˜ÿ÷ú¯ÿñ™ˆˆˆÿÿ™ˆÿ"ªÿÿÿwù™™˜ÿÿù˜ˆ"z¯ÿÿñÿ™™Ÿÿÿÿ™™"ªÿÿñÿÿÿÿÿÿÿù™"ªˆÿÿñÿøˆˆÿÿÿÿÿÿú¨ÿñÿ™™˜ÿÿÿÿÿÿÿªˆÿÿwù™™Ÿÿÿÿÿÿÿÿú¨ˆ™ÿÿÿÿÿÿÿÿÿÿÿªª¡˜ÿÿÿÿÿÿÿÿÿÿÿúª¡˜ÿÿøøÿøÿÿÿøˆˆ™ˆˆˆÿñÿÿù™™˜ÿññÿÿÿÿ™™Ÿÿÿñˆˆÿÿÿÿÿÿÿñÿñÿÿÿÿÿÿñÿÿÿÿÿÿÿÿÿÿÿñˆˆˆˆÿÿÿÿÿÿÿñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgambit-0.2010.09.01/src/gui/bitmaps/open.xpm0000644000076500007650000000774411350032206015145 00000000000000/* XPM */ static char * open_xpm[] = { "24 24 173 2", " c None", ". c #000000", "+ c #010100", "@ c #B5B8A5", "# c #E4E7D2", "$ c #878A76", "% c #33342B", "& c #0B0B0B", "* c #E2E5CF", "= c #CFD4AF", "- c #CED3AE", "; c #B2B696", "> c #2D2D25", ", c #23241D", "' c #9D9F90", ") c #C6CAA6", "! c #C4C9A5", "~ c #C6CBA7", "{ c #C7CCA8", "] c #C9CEA9", "^ c #555847", "/ c #1A1B15", "( c #20201A", "_ c #D4D6C2", ": c #BEC2A0", "< c #B3B896", "[ c #B0B595", "} c #B3B797", "| c #B6BB99", "1 c #BBC09E", "2 c #BCC19F", "3 c #81856C", "4 c #3E3F32", "5 c #010101", "6 c #DADDC8", "7 c #AFB494", "8 c #AAAF8F", "9 c #A3A789", "0 c #A6AA8B", "a c #A9AD8E", "b c #A7AB8D", "c c #A4A88A", "d c #A1A588", "e c #AAAD96", "f c #B3B5A5", "g c #B8BBAA", "h c #BABCAB", "i c #C1C3B2", "j c #C7CAB7", "k c #CACDBB", "l c #BABDA8", "m c #0C0C09", "n c #DDDFCB", "o c #969B7E", "p c #9DA286", "q c #95987C", "r c #96997E", "s c #9A9D81", "t c #999D80", "u c #9DA184", "v c #A5AA8B", "w c #A4A98A", "x c #A3A889", "y c #A2A588", "z c #A2A587", "A c #9FA386", "B c #9B9E83", "C c #898D74", "D c #D8DBC9", "E c #84866E", "F c #7D8169", "G c #151612", "H c #D7DAC9", "I c #797D67", "J c #3D3F34", "K c #E0E0D9", "L c #EBEDDD", "M c #E8EBD9", "N c #E7EAD8", "O c #E3E6D4", "P c #DEE1D0", "Q c #DADCCC", "R c #DADCD1", "S c #2B2C28", "T c #D7DAC6", "U c #6F735E", "V c #0D0D0D", "W c #F4F4EC", "X c #CACFAB", "Y c #C6CBA8", "Z c #C2C6A4", "` c #ABB091", " . c #23251E", ".. c #494B3D", "+. c #DCDCD4", "@. c #EAECDD", "#. c #CDD2AD", "$. c #CCD1AC", "%. c #CACFAA", "&. c #BABF9D", "*. c #B5B999", "=. c #81836C", "-. c #070806", ";. c #D5D8C4", ">. c #161616", ",. c #F2F2EA", "'. c #C9CEAA", "). c #C8CDA9", "!. c #C4C9A6", "~. c #C1C5A3", "{. c #BCC09F", "]. c #B6BB9A", "^. c #B0B494", "/. c #9DA185", "(. c #535445", "_. c #B6B8A7", ":. c #747470", "<. c #ECECE2", "[. c #C3C8A5", "}. c #C2C7A4", "|. c #C0C5A2", "1. c #BFC4A1", "2. c #BDC2A0", "3. c #B9BD9C", "4. c #B9BE9D", "5. c #A9AD8F", "6. c #A3A78A", "7. c #80836D", "8. c #020201", "9. c #A6A998", "0. c #B8BC9B", "a. c #AFB394", "b. c #ACB091", "c. c #A8AC8E", "d. c #A6AA8C", "e. c #9FA286", "f. c #9B9F83", "g. c #9A9D82", "h. c #8A8D75", "i. c #4F5243", "j. c #070705", "k. c #9E9F91", "l. c #E5E6DA", "m. c #ADB192", "n. c #A5A98C", "o. c #9FA387", "p. c #999D81", "q. c #95987E", "r. c #92957B", "s. c #8C8F76", "t. c #8A8D74", "u. c #71735F", "v. c #080908", "w. c #E3E5D9", "x. c #C0C3AF", "y. c #94987C", "z. c #8F9379", "A. c #8B8F75", "B. c #8A8E74", "C. c #888C73", "D. c #858970", "E. c #868971", "F. c #82866E", "G. c #80836C", "H. c #7D8069", "I. c #797C66", "J. c #727560", "K. c #717460", "L. c #71745F", "M. c #6A6D59", "N. c #434538", "O. c #080907", "P. c #050504", " ", " ", " ", " . . . . . . . ", " + @ # # # # # $ % ", " & * = = = - - ; > ", ", ' * ) ! ~ { ] ] ^ / ", "( _ : < [ } | 1 2 3 4 5 . . . . . . . ", ", 6 7 8 9 0 8 a b c d e f g h i j k l . ", "m n o p q r s t r u v w x y 9 z A B C . ", ". D E F G . . . . . . . . . . . . . . . 5 5 ", ". H I J K L M M M M M M M M M M M N O P Q R S ", ". T U V W = = = = = = = = = - - - X Y Z 1 ` . ", ". T ..+.@.#.- - #.- #.#.#.#.#.$.%.Y Z &.*.=.-. ", ". ;.>.,.X %.X %.'.%.'.{ ).).Y !.~.{.].^./.(.m ", ". _.:.<.[.}.}.Z |.Z 1.2.|.2.3.4.} [ 5.6.7.8. ", ". 9.+.0.0.*.} } [ [ a.a.a.b.c.d.e.f.g.h.i.j. ", ". k.l.m.5.d.n.6.6.d o.e.f.p.q.r.s.t.t.u.v. ", ". w.x.y.z.A.B.C.C.D.E.F.G.H.I.J.K.L.M.N.O. ", " . . . . . . . . . . . . . . . . . . P. ", " ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/person.xpm0000644000076500007650000001016611350032206015502 00000000000000/* XPM */ static char * person_xpm[] = { "24 24 182 2", " c None", ". c #000000", "+ c #111110", "@ c #4B4844", "# c #0A0500", "$ c #1D1D1D", "% c #060606", "& c #444444", "* c #252525", "= c #181817", "- c #130A00", "; c #4C3A29", "> c #150B01", ", c #0E0700", "' c #1D1003", ") c #261504", "! c #361F05", "~ c #1B0F01", "{ c #412405", "] c #C5751C", "^ c #C5741D", "/ c #C1731D", "( c #C2731C", "_ c #C8741A", ": c #7C450C", "< c #080400", "[ c #2C1804", "} c #5B3107", "| c #D17A1D", "1 c #D17B1E", "2 c #D37D1F", "3 c #D07A1D", "4 c #CD761A", "5 c #79430C", "6 c #2D1905", "7 c #311A04", "8 c #A95F13", "9 c #CC7519", "0 c #CC761A", "a c #CC751A", "b c #CB7519", "c c #CA7218", "d c #B66614", "e c #2F1904", "f c #3A1F05", "g c #9B580F", "h c #BE6A15", "i c #83490F", "j c #261402", "k c #2E1803", "l c #8A4C0E", "m c #B56413", "n c #422305", "o c #472605", "p c #934F0D", "q c #321B03", "r c #AC6011", "s c #A55C10", "t c #653607", "u c #351C02", "v c #0D1112", "w c #292626", "x c #593615", "y c #341B04", "z c #351D04", "A c #341C04", "B c #291704", "C c #452F1A", "D c #181E25", "E c #090B0D", "F c #25282C", "G c #91999F", "H c #899DB0", "I c #6F7A84", "J c #241E1A", "K c #180E04", "L c #1A120C", "M c #222223", "N c #646F7A", "O c #455666", "P c #3D4D5E", "Q c #090D0F", "R c #282C31", "S c #A0ABB7", "T c #738EAA", "U c #7591AC", "V c #506375", "W c #899097", "X c #CCCCCC", "Y c #C5C6C8", "Z c #8D99A5", "` c #6F7F91", " . c #556C83", ".. c #586E84", "+. c #45586B", "@. c #0A0D10", "#. c #121415", "$. c #90989E", "%. c #7C95AD", "&. c #6D89A5", "*. c #6F8BA6", "=. c #5C748B", "-. c #7C8A99", ";. c #F2F3F4", ">. c #E7EAED", ",. c #A7B8C7", "'. c #7E95AC", "). c #66809B", "!. c #5D7995", "~. c #4E667D", "{. c #374656", "]. c #0A0C10", "^. c #131516", "/. c #96A1AD", "(. c #66829E", "_. c #67839E", ":. c #6884A0", "<. c #597088", "[. c #607285", "}. c #E6E8EB", "|. c #C9D3DB", "1. c #9AACBD", "2. c #7990A8", "3. c #BBC6D2", "4. c #6C859E", "5. c #526E8B", "6. c #4E6883", "7. c #0C1015", "8. c #191D20", "9. c #8A9EB0", "0. c #5C7895", "a. c #5E7A97", "b. c #607C98", "c. c #617D99", "d. c #52677C", "e. c #CFD5DB", "f. c #B8C3D0", "g. c #68829C", "h. c #BBC7D1", "i. c #D5DBE1", "j. c #CAD3DB", "k. c #4D6A87", "l. c #45617E", "m. c #0C1016", "n. c #1D2227", "o. c #8296AA", "p. c #56728F", "q. c #587491", "r. c #597692", "s. c #5A7692", "t. c #405267", "u. c #B8C3CC", "v. c #A9B8C6", "w. c #587490", "x. c #4E6A87", "y. c #4A6684", "z. c #44617E", "A. c #3F5A78", "B. c #0D131A", "C. c #171E27", "D. c #748A9E", "E. c #4F6B88", "F. c #536F8C", "G. c #53708C", "H. c #3A4E63", "I. c #6F8498", "J. c #8FA0B2", "K. c #4E6B88", "L. c #4C6886", "M. c #486482", "N. c #3C5774", "O. c #354F69", "P. c #040608", "Q. c #182330", "R. c #3E5773", "S. c #3D5671", "T. c #3E5672", "U. c #3F5874", "V. c #405A74", "W. c #3C5670", "X. c #3B526C", "Y. c #293B50", " ", " ", " . . . . . ", " + . @ @ # . . ", " $ % @ & * . . . + ", " = - ; > , ' ) ! % ", " ~ { ] ^ / ( _ : < ", " [ } | 1 2 3 4 5 6 ", " 7 8 9 0 a b c d e ", " f g h i j k l m n ", " o p q r s o t u ", " v w x y z A B C D E ", " F G H I J K L M N O P Q ", " R S T U V W X Y Z ` ...+.@. ", " #.$.%.&.*.=.-.;.>.,.'.).!.~.{.]. ", " ^./.(._.:.<.[.}.|.1.2.3.4.5.6.7. ", " 8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m. ", " n.o.p.q.r.s.t.u.v.w.5.x.y.z.A.B. ", " C.D.E.5.F.G.H.I.J.K.L.M.l.N.O.P. ", " . Q.R.S.T.U.U.V.R.R.R.W.X.X.Y.. ", " . . . . . . . . . . . . . . ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/prev.xpm0000644000076500007650000000232111350032206015142 00000000000000/* XPM */ static char * prev_xpm[] = { "24 24 34 1", " c None", ". c #000000", "+ c #AEC4D9", "@ c #C4D4E3", "# c #A6BED5", "$ c #A3BCD4", "% c #A2BBD3", "& c #AAC1D7", "* c #A9C0D6", "= c #ABC2D8", "- c #AFC5DA", "; c #6892B9", "> c #9CB7D1", ", c #A4BDD5", "' c #9FB9D2", ") c #9BB6D0", "! c #9AB5CF", "~ c #49759E", "{ c #1C2D3D", "] c #C5D5E4", "^ c #A0BAD3", "/ c #9EB8D1", "( c #4B78A2", "_ c #81A4C4", ": c #7198BC", "< c #739ABE", "[ c #759BBE", "} c #7299BD", "| c #3C6183", "1 c #2A435B", "2 c #3F6588", "3 c #34536F", "4 c #29425A", "5 c #2D4760", " ", " ", " ", " . ", " .. ", " .+. ", " .@#. ", " .@$%........ ", " .@#&*=-=++$;. ", " .@>,$%')))'!~. ", " {]'^//'>''^''(. ", " ._:<<<<<<<<<[}|. ", " .1222222222223. ", " .122222222223. ", " .12234444445. ", " .123........ ", " .13. ", " .3. ", " .. ", " . ", " ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/preview.xpm0000644000076500007650000001052711350032206015656 00000000000000/* XPM */ static char * preview_xpm[] = { "24 24 196 2", " c None", ". c #000000", "+ c #BABABA", "@ c #FFFFFF", "# c #F6F6F6", "$ c #8D8D8D", "% c #A6A6A6", "& c #B5B5B5", "* c #DADADA", "= c #828282", "- c #797979", "; c #A4A4A4", "> c #FDFDFD", ", c #787878", "' c #9E9E9E", ") c #5C5C5C", "! c #FEFEFE", "~ c #FAFAFA", "{ c #F2F2F2", "] c #AFAFAF", "^ c #47473F", "/ c #0A0A09", "( c #4B4B43", "_ c #BBBBBB", ": c #F8F8F8", "< c #7C7C7C", "[ c #484848", "} c #34342E", "| c #9D9D8D", "1 c #CFCFB9", "2 c #C4C4AF", "3 c #8D8D7F", "4 c #353530", "5 c #9F9F9F", "6 c #E2E2E2", "7 c #CFCFCF", "8 c #46463F", "9 c #9C9C8C", "0 c #E2E2D0", "a c #EDEDE7", "b c #C0C0AC", "c c #B2B29F", "d c #828274", "e c #4C4C44", "f c #EDEDED", "g c #C8C8C8", "h c #747474", "i c #090908", "j c #D5D5BF", "k c #FBFBFA", "l c #C3C3AE", "m c #B5B5A2", "n c #A6A695", "o c #9C9C8F", "p c #080807", "q c #E4E4E4", "r c #E1E1E1", "s c #9D9D9D", "t c #090909", "u c #CACAB5", "v c #DDDDD0", "w c #B7B7A4", "x c #AAAA98", "y c #9B9B8B", "z c #AEAEA3", "A c #C2C2C2", "B c #87847C", "C c #EAE8E3", "D c #848079", "E c #45443F", "F c #474740", "G c #929283", "H c #BABAA7", "I c #ADAD9B", "J c #9F9F8E", "K c #ACACA1", "L c #CFCFCB", "M c #4C4C45", "N c #807D74", "O c #AAA9A5", "P c #BAB5AB", "Q c #F3F3F3", "R c #DBDBDB", "S c #C9C9C9", "T c #838383", "U c #34342F", "V c #878779", "W c #A0A090", "X c #AEAEA2", "Y c #C3C3BE", "Z c #010101", "` c #C3C1BD", " . c #8B8B89", ".. c #E6E5E1", "+. c #F4F4F3", "@. c #E6E6E5", "#. c #D1D1D1", "$. c #C4C4C2", "%. c #8B8B8A", "&. c #414141", "*. c #A09F9D", "=. c #404040", "-. c #B5B5B4", ";. c #DFDED9", ">. c #A4A3A1", ",. c #6C6B6A", "'. c #F5F4F3", "). c #BDBDBD", "!. c #A7A7A7", "~. c #979797", "{. c #B0B0AF", "]. c #9B9B9B", "^. c #B6B6B6", "/. c #8C8C8C", "(. c #B3B3B3", "_. c #171717", ":. c #AEACA7", "<. c #6A6A69", "[. c #999896", "}. c #918F87", "|. c #999895", "1. c #6B6B6A", "2. c #E6E4E1", "3. c #F0EEEC", "4. c #F6F5F4", "5. c #EAE9E9", "6. c #E9E9E8", "7. c #EBEAE9", "8. c #E6E5E4", "9. c #D4D4D4", "0. c #CACAC9", "a. c #979696", "b. c #9C9C9C", "c. c #545454", "d. c #50504F", "e. c #858482", "f. c #9C9B99", "g. c #6B6A68", "h. c #585858", "i. c #5E5C57", "j. c #524F4B", "k. c #494744", "l. c #4A4945", "m. c #4A4845", "n. c #484642", "o. c #43413D", "p. c #3D3B38", "q. c #393834", "r. c #393836", "s. c #757575", "t. c #4C4C4C", "u. c #7B7A77", "v. c #797771", "w. c #949391", "x. c #989694", "y. c #868480", "z. c #6E6C66", "A. c #706D67", "B. c #5C5955", "C. c #67645F", "D. c #5B5954", "E. c #585651", "F. c #5C5A55", "G. c #56534F", "H. c #4C4945", "I. c #4A4744", "J. c #484743", "K. c #4B4A48", "L. c #848484", "M. c #7D7D7D", "N. c #696861", "O. c #77756F", "P. c #7E7B77", "Q. c #979690", "R. c #96938D", "S. c #807E77", "T. c #7D7A74", "U. c #787770", "V. c #716F6A", "W. c #6D6B66", "X. c #565450", "Y. c #5A5954", "Z. c #585752", "`. c #605F5A", " + c #676660", ".+ c #72716B", "++ c #76746F", "@+ c #6A6963", "#+ c #8B8880", "$+ c #B2AFA8", "%+ c #B6B3AD", "&+ c #BFBDB6", "*+ c #BDBBB4", "=+ c #B0AEA6", "-+ c #ABA8A2", ";+ c #9C9991", " ", " . . . . . . . . . . . . ", " . + @ @ @ @ @ @ @ @ @ @ + . ", " . @ @ @ @ @ @ @ @ @ @ @ # . ", " . @ $ % & @ * @ @ @ @ @ # . ", " . @ @ @ @ @ @ @ @ @ @ @ # . ", " . @ = - ; > , ' * + ) @ # . ", " . ! ~ { ] ^ / / ( _ @ @ # . ", " . : < [ } | 1 2 3 4 5 @ # . ", " . 6 7 8 9 0 a b c d e # f . ", " . . g h i j k l m n o p q r . . ", " . @ . % s t u v w x y z / g A . B . ", " . @ C D E . F G H I J K L M . N B O P . ", " . @ @ Q { R S T U V W X Y Z Z @ @ @ @ @ C . ", " . ` ...+.@.#.$.%.( / / &.*.=.Z -.C 5 ;.P . ", " . >.,.'.).7 !.& ~.{.].^./.(.' =._.:.<.[.}.. ", " . |.1.2.3.4.+.f 5.6.7.8.9.0.a.b.c.Z d.e.}.. ", " . f.g.h.i.j.k.l.m.m.m.n.o.p.q.r.s.t.t.u.v.. ", " . w.x.y.z.A.B.C.D.E.D.F.G.H.I.J.K.L.M.N.O.. ", " . P.Q.R.}.S.T.U.O.V.O.V.W.X.Y.Z.`. +.+++@+. ", " . . . . . . . . . . . . . . . . . . . . ", " . #+$+%+&+&+&+&+&+*+=+$+-+=+;+;+;+N N . ", " . . . . . . . . . . . . . . . . . . ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/print.xpm0000644000076500007650000001000511350032206015320 00000000000000/* XPM */ static char * print_xpm[] = { "24 24 175 2", " c None", ". c #000000", "+ c #C7C7C7", "@ c #FAFAFA", "# c #FCFCFC", "$ c #FBFBFB", "% c #F8F8F8", "& c #AFAFAF", "* c #F9F9F9", "= c #E5E5E5", "- c #E3E3E3", "; c #E2E2E2", "> c #E0E0E0", ", c #DFDFDF", "' c #DCDCDC", ") c #DBDBDB", "! c #B6B6B6", "~ c #6B6B6B", "{ c #676767", "] c #818181", "^ c #E7E7E7", "/ c #606060", "( c #A0A0A0", "_ c #DADADA", ": c #E1E1E1", "< c #B7B7B7", "[ c #FDFDFD", "} c #EFEFEF", "| c #EEEEEE", "1 c #EDEDED", "2 c #ECECEC", "3 c #EBEBEB", "4 c #E9E9E9", "5 c #E8E8E8", "6 c #BFBFBF", "7 c #8A8A8A", "8 c #6A6A6A", "9 c #9E9E9E", "0 c #F6F6F6", "a c #909090", "b c #A2A2A2", "c c #AAAAAA", "d c #F4F4F4", "e c #CECECE", "f c #ADADAD", "g c #AEAEAE", "h c #BEBEBE", "i c #A6A6A6", "j c #CDCDCD", "k c #F5F5F5", "l c #DEDEDE", "m c #DDDDDD", "n c #C9C9C9", "o c #878787", "p c #888888", "q c #D0D0D0", "r c #6E6E6E", "s c #797979", "t c #D1D1D1", "u c #A1A1A1", "v c #B3B3B3", "w c #FFFFFF", "x c #CACACA", "y c #A7A7A7", "z c #A5A5A5", "A c #A4A4A4", "B c #A3A3A3", "C c #87847C", "D c #EAE8E3", "E c #8D8982", "F c #53524C", "G c #807D74", "H c #AAA9A5", "I c #BAB5AB", "J c #F3F3F3", "K c #C3C1BD", "L c #8B8B89", "M c #E6E5E1", "N c #F9F9F8", "O c #FAFAF9", "P c #F9F9F7", "Q c #F7F6F5", "R c #F7F7F4", "S c #F6F5F4", "T c #F2F1EE", "U c #F0EFEC", "V c #E5E5E4", "W c #9F9F9F", "X c #DFDED9", "Y c #A4A3A1", "Z c #6C6B6A", "` c #F5F4F3", " . c #D5D5D5", ".. c #D3D3D3", "+. c #D4D4D3", "@. c #D4D4D4", "#. c #A9A9A9", "$. c #B5B5B5", "%. c #CDCDCB", "&. c #B5B5B4", "*. c #DCDAD3", "=. c #6B6B6A", "-. c #999896", ";. c #918F87", ">. c #999895", ",. c #E6E4E1", "'. c #F0EEEC", "). c #FAF9F9", "!. c #F9F8F7", "~. c #F8F7F6", "{. c #F8F8F7", "]. c #F4F3F1", "^. c #F2F1EF", "/. c #565655", "(. c #858482", "_. c #9C9B99", ":. c #6B6A68", "<. c #585858", "[. c #5E5C57", "}. c #524F4B", "|. c #4A4845", "1. c #4B4A46", "2. c #4B4946", "3. c #4A4844", "4. c #494743", "5. c #484642", "6. c #474541", "7. c #464440", "8. c #514F4B", "9. c #53514E", "0. c #7B7A77", "a. c #797771", "b. c #949391", "c. c #989694", "d. c #868480", "e. c #6E6C66", "f. c #706D67", "g. c #5C5955", "h. c #67645F", "i. c #5B5954", "j. c #585651", "k. c #5D5B56", "l. c #595652", "m. c #53504C", "n. c #575450", "o. c #595752", "p. c #5C5956", "q. c #5B5956", "r. c #61615E", "s. c #696861", "t. c #77756F", "u. c #7E7B77", "v. c #979690", "w. c #96938D", "x. c #807E77", "y. c #7D7A74", "z. c #787770", "A. c #716F6A", "B. c #6E6C67", "C. c #595753", "D. c #63615C", "E. c #686661", "F. c #6F6E68", "G. c #6D6C66", "H. c #72716B", "I. c #76746F", "J. c #6A6963", "K. c #8B8880", "L. c #B2AFA8", "M. c #B6B3AD", "N. c #BFBDB6", "O. c #BDBBB4", "P. c #B0AEA6", "Q. c #ABA8A2", "R. c #9C9991", " ", " . . . . . . . . . . . . ", " . + @ # # # # # # # $ % & . ", " . * = - - - ; > , , ' ) ! . ", " . # ~ { ] ^ / ( _ : > > < . ", " . [ } | 1 1 | 2 2 3 4 5 6 . ", " . [ 7 8 9 0 a b 4 c a d + . ", " . [ # # # # $ $ # # $ $ e . ", " . [ f g = h % h i j 3 # j . ", " . k l l l m l l , l 5 : n . ", " . . @ o ~ p q r s t p u q v . . ", " . w . x y z A z z i B b u u 9 . C . ", " . w D E F . . . . . . . . . . G C H I . ", " . w w J w w w w w w w w w w w w w w w w D . ", " . K L M N O N P Q R O O S T T U V D W X I . ", " . Y Z ` h .! ..! +.< @.#...$.%.&.*.=.-.;.. ", " . >.=.,.'.Q N @ ).N !.~.{.{.].].].^./.(.;.. ", " . _.:.<.[.}.|.1.2.2.2.3.4.5.6.4.7.8.9.0.a.. ", " . b.c.d.e.f.g.h.i.j.i.k.l.m.n.o.p.q.r.s.t.. ", " . u.v.w.;.x.y.z.t.A.t.A.B.C.D.E.F.G.H.I.J.. ", " . . . . . . . . . . . . . . . . . . . . ", " . K.L.M.N.N.N.N.N.O.P.L.Q.P.R.R.R.G G . ", " . . . . . . . . . . . . . . . . . . ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/profiles.xpm0000644000076500007650000000202211350032206016007 00000000000000/* XPM */ static char * profiles_xpm[] = { "24 24 21 1", " c None", ". c #889088", "+ c #BFBFBF", "@ c #586058", "# c #505050", "$ c #707070", "% c #FFFFFF", "& c #808080", "* c #606060", "= c #EFEFEF", "- c #CFCFCF", "; c #9F9F9F", "> c #000000", ", c #303030", "' c #101010", ") c #DFDFDF", "! c #202020", "~ c #AFAFAF", "{ c #404040", "] c #8F8F8F", "^ c #586858", " .++++++++++++++++@ ", " +#$%%%%%%%%%%%%%%& ", " +#*%%+%%%%%=-%%%%& ", " +;&%;>*%%%=,'-%%%& ", " +=%)>>>;%%*>>!%%%& ", " ~,*){*#~%%&*##%%%& ", " ;,#%%+=%%%%)-%%%%& ", " +)=%%+%%%%%=-%%%%& ", " +%%%;>*%%%=,'-%%%& ", " +%%)>>>;=%*>>!%%%& ", " +%%){*#;,*&*##%%%& ", " +%%%%+={>>&)-%%%%& ", " +%%%%%%',,#%%%%%%& ", " +%%=&*&-~-~&*]%%%& ", " +%%->>>]%%#>>'%%%& ", " +%%%*>,=%%-'>;%%%& ", " +%%%%&=%%%%-;%%)=& ", " +%%%%+=%%%%)-%),#& ", " +%%){*#~%%&*##=,*& ", " +%%)>>>;%%*>>!%=%& ", " +%%%;>*%%%=,'-%*+& ", " +%%%%+%%%%%=-%%{$& ", " +%%%%%%%%%%%%%%#$& ", " .++++++++++++++++^ "}; gambit-0.2010.09.01/src/gui/bitmaps/redo.xpm0000644000076500007650000000251111350032206015120 00000000000000/* XPM */ static char * redo_xpm[] = { "24 24 42 1", " c None", ". c #000000", "+ c #939A8D", "@ c #BAD09D", "# c #92998C", "$ c #818F71", "% c #ADBDA0", "& c #C2D5AA", "* c #D1DFBE", "= c #BED2A3", "- c #99A28F", "; c #A8BCA6", "> c #D5E1C6", ", c #CDDCBC", "' c #D2E0BF", ") c #C5D7AE", "! c #919889", "~ c #8C9A7F", "{ c #D4E0C5", "] c #D3E0C1", "^ c #BFD3A6", "/ c #9BAA87", "( c #B5C3A9", "_ c #92AD62", ": c #7C9B40", "< c #59702D", "[ c #7F8E6B", "} c #C8D9B2", "| c #85A24D", "1 c #53692A", "2 c #A4B690", "3 c #9BB572", "4 c #6D8839", "5 c #95A77E", "6 c #8BA859", "7 c #657255", "8 c #98AF74", "9 c #AFC394", "0 c #6D7A5B", "a c #9CAF84", "b c #748261", "c c #879772", " ", " ", " ", " . ", " .. ", " .+. ", " ....@#. ", " .$%&*=@-. ", " .;>,')@@@!. ", " .~{]*^@@@@@/. ", " .(>_::::::<. ", " .[}|::::::1. ", " .23:<...:1. ", " .@:4. .<. ", " .@:.. .. ", " .56. . ", " .78. ", " .9. ", " .0a. ", " .bc. ", " ... ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/save.xpm0000644000076500007650000001132411350032206015127 00000000000000/* XPM */ static char * save_xpm[] = { "24 24 220 2", " c None", ". c #000000", "+ c #C3D7F4", "@ c #A9CDE5", "# c #75757A", "$ c #EFC5BB", "% c #F1C8BE", "& c #F0C6BC", "* c #EEBCB2", "= c #EEBEB5", "- c #EEC1B8", "; c #EDBFB6", "> c #E9B7AD", ", c #E9B8AF", "' c #E9B9B1", ") c #E5BFBA", "! c #737277", "~ c #B3CDE3", "{ c #A1BED6", "] c #BBD6E8", "^ c #8AAAC5", "/ c #605F68", "( c #E08D7E", "_ c #E0826E", ": c #E0806E", "< c #DC7A68", "[ c #DC8171", "} c #DA7868", "| c #D48173", "1 c #D47D6E", "2 c #CE7265", "3 c #CF7264", "4 c #CE7567", "5 c #C4675B", "6 c #C36558", "7 c #626169", "8 c #87A3B7", "9 c #567187", "0 c #BAD5E9", "a c #88A7C3", "b c #686670", "c c #C8817B", "d c #CB7C74", "e c #CB7A73", "f c #CB7B73", "g c #CC7C72", "h c #CB7D73", "i c #BF6B64", "j c #CC7A70", "k c #C16A62", "l c #CC7C73", "m c #C2655B", "n c #C36459", "o c #BA6C6A", "p c #819EB6", "q c #547086", "r c #B6D3E7", "s c #87ABC1", "t c #737373", "u c #FFFFFF", "v c #83A0B8", "w c #526C80", "x c #B9D3E7", "y c #85A4BF", "z c #4F697C", "A c #B9D3E6", "B c #84A3BF", "C c #CECECE", "D c #CDCDCD", "E c #BFBFBF", "F c #88A4BB", "G c #486276", "H c #B7D2E7", "I c #82A0BB", "J c #636363", "K c #465E70", "L c #B5CAE5", "M c #7FA2B9", "N c #87A3BA", "O c #455C6D", "P c #AECCE5", "Q c #7DA0B6", "R c #C5C5C5", "S c #546069", "T c #B0D1E4", "U c #83A1B6", "V c #735B5B", "W c #515C64", "X c #AACEE3", "Y c #7B9BB2", "Z c #7A8E9A", "` c #7A7A7A", " . c #6B6F72", ".. c #6F6F6F", "+. c #696969", "@. c #6F777E", "#. c #86A2B9", "$. c #3A515D", "%. c #A9C9E2", "&. c #7494AF", "*. c #829FB7", "=. c #7F9DB6", "-. c #7E9CB5", ";. c #7998B2", ">. c #85A1B8", ",. c #8CA7BD", "'. c #8AA5BB", "). c #364A59", "!. c #ABC4E2", "~. c #7294AD", "{. c #6F90AC", "]. c #7192AE", "^. c #414A4E", "/. c #424A51", "(. c #525B63", "_. c #626F79", ":. c #5F6C76", "<. c #5C6971", "[. c #5A666F", "}. c #58636B", "|. c #57636A", "1. c #3B5360", "2. c #39424B", "3. c #7897B3", "4. c #A4B9CB", "5. c #364853", "6. c #AAC9E2", "7. c #7091AA", "8. c #6F8FA7", "9. c #4A5359", "0. c #97938C", "a. c #DFDDDA", "b. c #E3E1DE", "c. c #EBEAE8", "d. c #EAE9E7", "e. c #CFCEC9", "f. c #C9C6C0", "g. c #9B968E", "h. c #566168", "i. c #4B657A", "j. c #54738C", "k. c #AAC6DD", "l. c #34464E", "m. c #AAC9E1", "n. c #6C8EA6", "o. c #6C8CA4", "p. c #40474D", "q. c #DAD8D3", "r. c #E7E6E2", "s. c #67655E", "t. c #524F47", "u. c #D9D7D4", "v. c #C7C5BF", "w. c #C0BCB5", "x. c #B8B3AB", "y. c #434C54", "z. c #4D697F", "A. c #4F6F84", "B. c #B3CADC", "C. c #313E49", "D. c #A8C8E1", "E. c #6B8DA6", "F. c #728FA4", "G. c #E2E1DD", "H. c #F0EFEC", "I. c #CDCAC6", "J. c #C2BFB9", "K. c #CAC6C0", "L. c #DCDAD7", "M. c #4B555D", "N. c #4E697F", "O. c #BACCDC", "P. c #A4C4DE", "Q. c #698BA3", "R. c #708AA1", "S. c #383E43", "T. c #E0DEDA", "U. c #514E46", "V. c #4F4C44", "W. c #C7C4BE", "X. c #CBC8C2", "Y. c #E1E0DC", "Z. c #E9E8E6", "`. c #475158", " + c #4E6879", ".+ c #4D6C80", "++ c #A3C3DB", "@+ c #383F43", "#+ c #778999", "$+ c #6E899E", "%+ c #65859C", "&+ c #33383C", "*+ c #D7D4D0", "=+ c #D6D4D0", "-+ c #4E4A43", ";+ c #4D4942", ">+ c #D1CEC9", ",+ c #E6E5E2", "'+ c #EDECEA", ")+ c #454F55", "!+ c #486173", "~+ c #4D6678", "{+ c #A1C1DA", "]+ c #373C40", "^+ c #0C0D0F", "/+ c #4E5E6A", "(+ c #5B6E7C", "_+ c #4F5B62", ":+ c #A4A099", "<+ c #CCC9C3", "[+ c #D7D5D1", "}+ c #E4E2E0", "|+ c #DDDBD7", "1+ c #B8B5B0", "2+ c #3E474D", "3+ c #4A6176", "4+ c #4A6070", "5+ c #9BC3D8", "6+ c #363C41", "7+ c #28323E", " ", " . . . . . . . . . . . . . . . . . . . ", " . + @ # $ % & * = - ; > , > , ' ) ! ~ { . ", " . ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 . ", " . 0 a b c d e f g h i j k l m n o b p q . ", " . r s t u u u u u u u u u u u u u t v w . ", " . x y t u u u u u u u u u u u u u t v z . ", " . A B t C D D D D D D D D D D D E t F G . ", " . H I J u u u u u u u u u u u u u t F K . ", " . L M t u u u u u u u u u u u u u t N O . ", " . P Q t C D D D D D D D D D D D R t N S . ", " . T U V u u u u u u u u u u u u u t v W . ", " . X Y Z ` t t t t t ...t t t t +.@.#.$.. ", " . %.&.p v #.*.=.-.*.;.#.>.>.N *.,.v '.).. ", " . !.~.{.].^./.(._.:.<.[.}.|.(.1.2.3.4.5.. ", " . 6.7.8.9.0.a.b.c.c.d.a.e.f.g.h.i.j.k.l.. ", " . m.n.o.p.q.r.s.t.t.u.v.w.x.e.y.z.A.B.C.. ", " . D.E.F.p.G.H.s.t.t.I.J.w.K.L.M.N.A.O.C.. ", " . P.Q.R.S.T.c.U.V.V.W.w.X.Y.Z.`. +.+++@+. ", " . #+$+%+&+*+=+-+;+;+w.>+,+'+,+)+!+~+{+]+. ", " ^+/+(+_+:+w.x.<+<+[+}+d.|+1+2+3+4+5+6+. ", " . . . . . . . . . . . . . . . . 7+. ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/saveas.xpm0000644000076500007650000001256611350032206015464 00000000000000/* XPM */ static char * saveas_xpm[] = { "24 24 262 2", " c None", ". c #000000", "+ c #FBE73B", "@ c #F2B64D", "# c #FCEB3D", "$ c #F7B544", "% c #5D502C", "& c #C3D7F4", "* c #A9CDE5", "= c #75757A", "- c #EFC5BB", "; c #F1C8BE", "> c #F0C6BC", ", c #EEBCB2", "' c #EEBEB5", ") c #EEC1B8", "! c #EDBFB6", "~ c #E8B6AC", "{ c #FCE93B", "] c #F7B545", "^ c #6C5F34", "/ c #434345", "( c #92A7B9", "_ c #96B1C7", ": c #BBD6E8", "< c #8AAAC5", "[ c #605F68", "} c #E08D7E", "| c #E0826E", "1 c #E0806E", "2 c #DC7A68", "3 c #DC8171", "4 c #DA7868", "5 c #D38072", "6 c #FAE43A", "7 c #F4B244", "8 c #615030", "9 c #783E35", "0 c #4D4C52", "a c #7790A2", "b c #526D82", "c c #BAD5E9", "d c #88A7C3", "e c #686670", "f c #C8817B", "g c #CB7C74", "h c #CB7A73", "i c #CB7B73", "j c #CC7C72", "k c #CA7C72", "l c #F9DF39", "m c #F3AF42", "n c #614F2F", "o c #8F4941", "p c #945554", "q c #5B5A62", "r c #7B97AE", "s c #536F84", "t c #B6D3E7", "u c #87ABC1", "v c #737373", "w c #FFFFFF", "x c #FEFEFE", "y c #F9DC38", "z c #EFB44D", "A c #665A32", "B c #BBBBBB", "C c #CDCDCD", "D c #E4E4E4", "E c #6E6E6E", "F c #819EB6", "G c #526C80", "H c #B9D3E7", "I c #85A4BF", "J c #F8D837", "K c #F0A93F", "L c #655930", "M c #BABABA", "N c #CCCCCC", "O c #E5E5E5", "P c #F7F7F7", "Q c #727272", "R c #83A0B8", "S c #4F697C", "T c #B9D3E6", "U c #84A3BF", "V c #CECECE", "W c #F6D236", "X c #EDA43E", "Y c #5C5130", "Z c #949494", "` c #A3A3A3", " . c #B7B7B7", ".. c #C6C6C6", "+. c #BDBDBD", "@. c #88A4BB", "#. c #486276", "$. c #B7D2E7", "%. c #82A0BB", "&. c #636363", "*. c #FDFDFD", "=. c #D7AE74", "-. c #61562F", ";. c #465E70", ">. c #B5CAE5", ",. c #7FA2B9", "'. c #4F4115", "). c #87A3BA", "!. c #455C6D", "~. c #AECCE5", "{. c #7DA0B6", "]. c #CBCBCB", "^. c #9B9B9B", "/. c #9C9C9C", "(. c #A7A7A7", "_. c #B8B8B8", ":. c #C5C5C5", "<. c #546069", "[. c #B0D1E4", "}. c #83A1B6", "|. c #735B5B", "1. c #F0F0F0", "2. c #D9D9D9", "3. c #D3D3D3", "4. c #E1E1E1", "5. c #EDEDED", "6. c #F8F8F8", "7. c #515C64", "8. c #AACEE3", "9. c #7B9BB2", "0. c #7A8E9A", "a. c #7A7A7A", "b. c #707070", "c. c #6C6C6C", "d. c #6F6F6F", "e. c #6A6E71", "f. c #696969", "g. c #6F777E", "h. c #86A2B9", "i. c #3A515D", "j. c #A9C9E2", "k. c #7494AF", "l. c #7E9BB4", "m. c #7D9AB3", "n. c #7998B2", "o. c #85A1B8", "p. c #829FB7", "q. c #8CA7BD", "r. c #8AA5BB", "s. c #364A59", "t. c #ABC4E2", "u. c #7294AD", "v. c #6F90AC", "w. c #7192AE", "x. c #414A4E", "y. c #424A51", "z. c #525B63", "A. c #626F79", "B. c #5F6C76", "C. c #5C6971", "D. c #5A666F", "E. c #58636B", "F. c #57636A", "G. c #3B5360", "H. c #39424B", "I. c #7897B3", "J. c #A4B9CB", "K. c #364853", "L. c #AAC9E2", "M. c #7091AA", "N. c #6F8FA7", "O. c #4A5359", "P. c #97938C", "Q. c #DFDDDA", "R. c #E3E1DE", "S. c #EBEAE8", "T. c #EAE9E7", "U. c #CFCEC9", "V. c #C9C6C0", "W. c #9B968E", "X. c #566168", "Y. c #4B657A", "Z. c #54738C", "`. c #AAC6DD", " + c #34464E", ".+ c #AAC9E1", "++ c #6C8EA6", "@+ c #6C8CA4", "#+ c #40474D", "$+ c #DAD8D3", "%+ c #E7E6E2", "&+ c #67655E", "*+ c #524F47", "=+ c #D9D7D4", "-+ c #C7C5BF", ";+ c #C0BCB5", ">+ c #B8B3AB", ",+ c #434C54", "'+ c #4D697F", ")+ c #4F6F84", "!+ c #B3CADC", "~+ c #313E49", "{+ c #A8C8E1", "]+ c #6B8DA6", "^+ c #728FA4", "/+ c #E2E1DD", "(+ c #F0EFEC", "_+ c #CDCAC6", ":+ c #C2BFB9", "<+ c #CAC6C0", "[+ c #DCDAD7", "}+ c #4B555D", "|+ c #4E697F", "1+ c #BACCDC", "2+ c #A4C4DE", "3+ c #698BA3", "4+ c #708AA1", "5+ c #383E43", "6+ c #E0DEDA", "7+ c #514E46", "8+ c #4F4C44", "9+ c #C7C4BE", "0+ c #CBC8C2", "a+ c #E1E0DC", "b+ c #E9E8E6", "c+ c #475158", "d+ c #4E6879", "e+ c #4D6C80", "f+ c #A3C3DB", "g+ c #383F43", "h+ c #778999", "i+ c #6E899E", "j+ c #65859C", "k+ c #33383C", "l+ c #D7D4D0", "m+ c #D6D4D0", "n+ c #4E4A43", "o+ c #4D4942", "p+ c #D1CEC9", "q+ c #E6E5E2", "r+ c #EDECEA", "s+ c #454F55", "t+ c #486173", "u+ c #4D6678", "v+ c #A1C1DA", "w+ c #373C40", "x+ c #0C0D0F", "y+ c #4E5E6A", "z+ c #5B6E7C", "A+ c #4F5B62", "B+ c #A4A099", "C+ c #CCC9C3", "D+ c #D7D5D1", "E+ c #E4E2E0", "F+ c #DDDBD7", "G+ c #B8B5B0", "H+ c #3E474D", "I+ c #4A6176", "J+ c #4A6070", "K+ c #9BC3D8", "L+ c #363C41", "M+ c #28323E", " . . ", " . + @ . ", " . . . . . . . . . . . . . # $ % . . . ", " . & * = - ; > , ' ) ! ~ . { ] ^ . / ( _ . ", " . : < [ } | 1 2 3 4 5 . 6 7 8 . 9 0 a b . ", " . c d e f g h i j k . l m n . o p q r s . ", " . t u v w w w w x . y z A . B C D E F G . ", " . H I v w w w x . J K L . M N O P Q R S . ", " . T U v V C N . W X Y . Z ` ...+.v @.#.. ", " . $.%.&.w w *.. =.-.. M N D P *.w v @.;.. ", " . >.,.v w x . '.. . M N D P *.w w v ).!.. ", " . ~.{.v V ].. . ^./.(._...].C C :.v ).<.. ", " . [.}.|.w *.1.2.3.4.5.6.x w w w w v R 7.. ", " . 8.9.0.a.Q b.c.c.d.e.E v v v v f.g.h.i.. ", " . j.k.F R h.F l.m.F n.h.o.o.).p.q.R r.s.. ", " . t.u.v.w.x.y.z.A.B.C.D.E.F.z.G.H.I.J.K.. ", " . L.M.N.O.P.Q.R.S.S.T.Q.U.V.W.X.Y.Z.`. +. ", " . .+++@+#+$+%+&+*+*+=+-+;+>+U.,+'+)+!+~+. ", " . {+]+^+#+/+(+&+*+*+_+:+;+<+[+}+|+)+1+~+. ", " . 2+3+4+5+6+S.7+8+8+9+;+0+a+b+c+d+e+f+g+. ", " . h+i+j+k+l+m+n+o+o+;+p+q+r+q+s+t+u+v+w+. ", " x+y+z+A+B+;+>+C+C+D+E+T.F+G+H+I+J+K+L+. ", " . . . . . . . . . . . . . . . . M+. ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/savedata.xpm0000644000076500007650000001111011350032206015752 00000000000000/* XPM */ static char * savedata_xpm[] = { "24 24 211 2", " c None", ". c #000000", "+ c #C3D7F4", "@ c #A9CDE5", "# c #75757A", "$ c #EFC5BB", "% c #F1C8BE", "& c #F0C6BC", "* c #EEBCB2", "= c #EEBEB5", "- c #EEC1B8", "; c #EDBFB6", "> c #E9B7AD", ", c #E9B8AF", "' c #E9B9B1", ") c #E5BFBA", "! c #737277", "~ c #B3CDE3", "{ c #A1BED6", "] c #BBD6E8", "^ c #8AAAC5", "/ c #605F68", "( c #E08D7E", "_ c #E0826E", ": c #E0806E", "< c #DC7A68", "[ c #DC8171", "} c #DA7868", "| c #D48173", "1 c #D47D6E", "2 c #CE7265", "3 c #CF7264", "4 c #CE7567", "5 c #C4675B", "6 c #C36558", "7 c #626169", "8 c #87A3B7", "9 c #567187", "0 c #BAD5E9", "a c #88A7C3", "b c #686670", "c c #C8817B", "d c #CB7C74", "e c #CB7A73", "f c #CB7B73", "g c #CC7C72", "h c #CB7D73", "i c #BF6B64", "j c #CC7A70", "k c #C16A62", "l c #CC7C73", "m c #C2655B", "n c #C36459", "o c #BA6C6A", "p c #819EB6", "q c #547086", "r c #B6D3E7", "s c #87ABC1", "t c #737373", "u c #FFFFFF", "v c #83A0B8", "w c #526C80", "x c #B9D3E7", "y c #585858", "z c #4F697C", "A c #B9D3E6", "B c #9E9E9E", "C c #CDCDCD", "D c #BFBFBF", "E c #88A4BB", "F c #486276", "G c #B7D2E7", "H c #C4C4C4", "I c #465E70", "J c #B5CAE5", "K c #87A3BA", "L c #455C6D", "M c #AECCE5", "N c #ACACAC", "O c #C5C5C5", "P c #546069", "Q c #B0D1E4", "R c #515C64", "S c #AACEE3", "T c #6B6F72", "U c #6F6F6F", "V c #696969", "W c #6F777E", "X c #86A2B9", "Y c #3A515D", "Z c #A9C9E2", "` c #647A8D", " . c #829FB7", ".. c #7F9DB6", "+. c #7E9CB5", "@. c #7998B2", "#. c #85A1B8", "$. c #8CA7BD", "%. c #8AA5BB", "&. c #364A59", "*. c #ABC4E2", "=. c #556E84", "-. c #7192AE", ";. c #414A4E", ">. c #424A51", ",. c #525B63", "'. c #626F79", "). c #5F6C76", "!. c #5C6971", "~. c #5A666F", "{. c #58636B", "]. c #57636A", "^. c #3B5360", "/. c #39424B", "(. c #7897B3", "_. c #A4B9CB", ":. c #364853", "<. c #AAC9E2", "[. c #7091AA", "}. c #6F8FA7", "|. c #4A5359", "1. c #97938C", "2. c #DFDDDA", "3. c #E3E1DE", "4. c #EBEAE8", "5. c #EAE9E7", "6. c #CFCEC9", "7. c #C9C6C0", "8. c #9B968E", "9. c #566168", "0. c #4B657A", "a. c #54738C", "b. c #AAC6DD", "c. c #34464E", "d. c #AAC9E1", "e. c #6C8EA6", "f. c #6C8CA4", "g. c #40474D", "h. c #DAD8D3", "i. c #E7E6E2", "j. c #67655E", "k. c #524F47", "l. c #D9D7D4", "m. c #C7C5BF", "n. c #C0BCB5", "o. c #B8B3AB", "p. c #434C54", "q. c #4D697F", "r. c #4F6F84", "s. c #B3CADC", "t. c #313E49", "u. c #A8C8E1", "v. c #6B8DA6", "w. c #728FA4", "x. c #E2E1DD", "y. c #F0EFEC", "z. c #CDCAC6", "A. c #C2BFB9", "B. c #CAC6C0", "C. c #DCDAD7", "D. c #4B555D", "E. c #4E697F", "F. c #BACCDC", "G. c #A4C4DE", "H. c #698BA3", "I. c #708AA1", "J. c #383E43", "K. c #E0DEDA", "L. c #514E46", "M. c #4F4C44", "N. c #C7C4BE", "O. c #CBC8C2", "P. c #E1E0DC", "Q. c #E9E8E6", "R. c #475158", "S. c #4E6879", "T. c #4D6C80", "U. c #A3C3DB", "V. c #383F43", "W. c #778999", "X. c #6E899E", "Y. c #65859C", "Z. c #33383C", "`. c #D7D4D0", " + c #D6D4D0", ".+ c #4E4A43", "++ c #4D4942", "@+ c #D1CEC9", "#+ c #E6E5E2", "$+ c #EDECEA", "%+ c #454F55", "&+ c #486173", "*+ c #4D6678", "=+ c #A1C1DA", "-+ c #373C40", ";+ c #0C0D0F", ">+ c #4E5E6A", ",+ c #5B6E7C", "'+ c #4F5B62", ")+ c #A4A099", "!+ c #CCC9C3", "~+ c #D7D5D1", "{+ c #E4E2E0", "]+ c #DDDBD7", "^+ c #B8B5B0", "/+ c #3E474D", "(+ c #4A6176", "_+ c #4A6070", ":+ c #9BC3D8", "<+ c #363C41", "[+ c #28323E", " ", " . . . . . . . . . . . . . . . . . . . ", " . + @ # $ % & * = - ; > , > , ' ) ! ~ { . ", " . ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 . ", " . 0 a b c d e f g h i j k l m n o b p q . ", " . r s t u u u u u u u u u u u u u t v w . ", " . x . y u u u u u u u u u u u u u t v z . ", " . A . . B C C C C C C C C C C C D t E F . ", " . G . . . H u u u u u u u u u u u t E I . ", " . J . . . . H u u u u u u u u u u t K L . ", " . M . . . . . N C C C C C C C C O t K P . ", " . Q . . . . H u u u u u u u u u u t v R . ", " . S . . . y t t t t T U t t t t V W X Y . ", " . Z . . ` X ...+. .@.X #.#.K .$.v %.&.. ", " . *.. =.-.;.>.,.'.).!.~.{.].,.^./.(._.:.. ", " . <.[.}.|.1.2.3.4.4.5.2.6.7.8.9.0.a.b.c.. ", " . d.e.f.g.h.i.j.k.k.l.m.n.o.6.p.q.r.s.t.. ", " . u.v.w.g.x.y.j.k.k.z.A.n.B.C.D.E.r.F.t.. ", " . G.H.I.J.K.4.L.M.M.N.n.O.P.Q.R.S.T.U.V.. ", " . W.X.Y.Z.`. +.+++++n.@+#+$+#+%+&+*+=+-+. ", " ;+>+,+'+)+n.o.!+!+~+{+5.]+^+/+(+_+:+<+. ", " . . . . . . . . . . . . . . . . [+. ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/stop.xpm0000644000076500007650000001246411350032206015164 00000000000000/* XPM */ static char * stop_xpm[] = { "24 24 258 2", " c None", ". c #010000", "+ c #180801", "@ c #2D1103", "# c #2C1003", "$ c #280F02", "% c #84320B", "& c #C75621", "* c #DC794A", "= c #DA7546", "- c #D77445", "; c #D37245", "> c #B74918", ", c #772B09", "' c #250D02", ") c #0B0400", "! c #88360E", "~ c #DF723D", "{ c #E47F4E", "] c #E1733D", "^ c #DA5A1C", "/ c #D65112", "( c #D14E11", "_ c #CC4C0F", ": c #C7490F", "< c #C2460F", "[ c #BB430F", "} c #742909", "| c #0A0300", "1 c #150701", "2 c #B5450F", "3 c #E47B46", "4 c #E5733A", "5 c #E25813", "6 c #DF5613", "7 c #DB5412", "8 c #D04E10", "9 c #CA4B0F", "0 c #C5480F", "a c #BF450F", "b c #B9420E", "c c #97350B", "d c #130600", "e c #B3440F", "f c #E57944", "g c #E67034", "h c #E75A13", "i c #E95B13", "j c #E85B13", "k c #E45913", "l c #E05713", "m c #DA5312", "n c #D44F12", "o c #CD4D0F", "p c #C1460F", "q c #BB430E", "r c #B53F0D", "s c #93330B", "t c #090300", "u c #82340F", "v c #E17641", "w c #E46C2F", "x c #ED5D13", "y c #C94F10", "z c #C14B0F", "A c #E35813", "B c #DC5512", "C c #C6490F", "D c #AC3F0C", "E c #C3460F", "F c #BC430F", "G c #B6400E", "H c #B03D0D", "I c #6A2408", "J c #230C02", "K c #D7632C", "L c #E37A47", "M c #E95C13", "N c #A24919", "O c #9C7663", "P c #8C634D", "Q c #AA4410", "R c #DA5512", "S c #DE5612", "T c #C14B12", "U c #A0735D", "V c #B38C7A", "W c #A64F27", "X c #BC440F", "Y c #A93A0D", "Z c #1F0A01", "` c #7F3715", " . c #DE7A4A", ".. c #AB8069", "+. c #FFFFFF", "@. c #DEB39D", "#. c #B14712", "$. c #C34D13", "%. c #A38272", "&. c #DBDBDB", "*. c #E6B49E", "=. c #C66035", "-. c #AA3A0D", ";. c #642107", ">. c #000000", ",. c #C3683D", "'. c #D7602A", "). c #D95312", "!. c #DF5713", "~. c #E55913", "{. c #AB7255", "]. c #D8AF9B", "^. c #AC8978", "/. c #DADADA", "(. c #DC997B", "_. c #CA6D44", ":. c #B5400E", "<. c #AF3D0D", "[. c #7F2B09", "}. c #100500", "|. c #D57548", "1. c #BC4A11", "2. c #B18771", "3. c #E7B39C", "4. c #CE724A", "5. c #C7663C", "6. c #B43F0D", "7. c #AE3C0D", "8. c #A8390C", "9. c #8E2F0A", "0. c #220C03", "a. c #D24E11", "b. c #D75112", "c. c #DD5512", "d. c #DE5714", "e. c #AF8673", "f. c #E8B49D", "g. c #D3774E", "h. c #C3592A", "i. c #B7410E", "j. c #B23E0D", "k. c #AC3B0D", "l. c #A6380C", "m. c #852C08", "n. c #1F0A02", "o. c #210C03", "p. c #D17045", "q. c #C8490F", "r. c #D45012", "s. c #D85415", "t. c #B28F7D", "u. c #EBC1AF", "v. c #C55625", "w. c #BA420E", "x. c #A4370C", "y. c #742606", "z. c #1A0801", "A. c #0D0400", "B. c #CC6E45", "C. c #C4470F", "D. c #CB4B0F", "E. c #CE4D0F", "F. c #A8410E", "G. c #B18D7D", "H. c #ECECEC", "I. c #EBC8B9", "J. c #BD5123", "K. c #AD3B0D", "L. c #A7380C", "M. c #A2360B", "N. c #672005", "O. c #0E0400", "P. c #AD5129", "Q. c #BE450F", "R. c #AA3E0C", "S. c #A7745D", "T. c #E6B39C", "U. c #DCA892", "V. c #B64F25", "W. c #8E2F09", "X. c #5F1E05", "Y. c #804A32", "Z. c #BD440F", "`. c #97360B", " + c #A87D6B", ".+ c #E5B29C", "++ c #C96335", "@+ c #C45729", "#+ c #E2B19B", "$+ c #DBA995", "%+ c #B4512A", "&+ c #9A330A", "*+ c #7C2807", "=+ c #441504", "-+ c #190801", ";+ c #BC5B32", ">+ c #9A3E17", ",+ c #C08E78", "'+ c #D89375", ")+ c #C66034", "!+ c #BF5426", "~+ c #BC5427", "{+ c #D28E72", "]+ c #D9A38D", "^+ c #B4542D", "/+ c #AF4C24", "(+ c #872C08", "_+ c #712506", ":+ c #160600", "<+ c #672B11", "[+ c #BB582E", "}+ c #B64717", "|+ c #C05A2F", "1+ c #B85025", "2+ c #B8552E", "3+ c #B3512A", "4+ c #B05029", "5+ c #973109", "6+ c #6F2307", "7+ c #471604", "8+ c #050100", "9+ c #872E0A", "0+ c #B7532A", "a+ c #B44B1F", "b+ c #A1360B", "c+ c #963109", "d+ c #6C2106", "e+ c #5D1D05", "f+ c #0C0300", "g+ c #832C0A", "h+ c #B4552E", "i+ c #B0481F", "j+ c #A5370C", "k+ c #A2360C", "l+ c #9F350B", "m+ c #7B2707", "n+ c #641F06", "o+ c #652006", "p+ c #0B0300", "q+ c #040100", "r+ c #5A1E06", "s+ c #A1360C", "t+ c #A2370C", "u+ c #822A08", "v+ c #661F05", "w+ c #702406", "x+ c #511905", "y+ c #140600", "z+ c #561D06", "A+ c #752707", "B+ c #892C08", "C+ c #7F2907", "D+ c #642005", "E+ c #5E1D05", "F+ c #4D1804", "G+ c #150600", "H+ c #080200", "I+ c #160701", " ", " . + @ # + . ", " $ % & * = - ; > , ' ", " ) ! ~ { ] ^ / ( _ : < [ } | ", " 1 2 3 4 5 5 6 7 / 8 9 0 a b c d ", " | e f g h i j k l m n o : p q r s t ", " u v w h x y z i A B / C D E F G H I ", " J K L A M N O P Q R S T U V W X G H Y Z ", " ` .7 5 j ..+.+.@.#.$.%.&.+.*.=.G H -.;. ", " >.,.'.).!.~.{.+.+.+.].^./.+.+.(._.:.<.Y [.>. ", " }.|.8 / 7 l 1.2.+.+.+.+.+.+.3.4.5.6.7.8.9.}. ", " 0.; _ a.b.m c.d.e.+.+.+.+.f.g.h.i.j.k.l.m.n. ", " o.p.q._ ( r.b.s.t.+.+.+.+.u.v.w.r H -.x.y.z. ", " A.B.C.: D.E.F.G.H.+.+.+.+.+.I.J.j.K.L.M.N.O. ", " >.P.Q.< 0 R.S.+.+.+.3.T.+.+.+.U.V.Y x.W.X.>. ", " Y.b Z.a `. ++.+..+++@+#++.+.$+%+l.&+*+=+ ", " -+;+i.b q >+,+'+)+w.!+~+{+]+^+/+M.(+_+:+ ", " <+[+}+:.G |+|+:.6.j.1+2+3+4+M.5+6+7+ ", " 8+9+0+a+H H H H 7.k.-.L.x.b+c+d+e+8+ ", " f+g+h+i+-.-.Y 8.l.j+k+l+m+n+o+p+ ", " q+r+s+x.x.x.t+b+l+u+v+w+x+8+ ", " y+z+A+B+C+D+o+E+F+G+ ", " >.H+I+I+H+>. ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/table.xpm0000644000076500007650000000213211350032206015255 00000000000000/* XPM */ static char * table_xpm[] = { "24 24 26 1", " c None", ". c #000000", "+ c #D3D3D3", "@ c #ABABAB", "# c #A6A6A6", "$ c #C8C8C8", "% c #A2A2A2", "& c #868686", "* c #F2F2F2", "= c #C4C4C4", "- c #C9C9C9", "; c #A3A3A3", "> c #C7C7C7", ", c #A1A1A1", "' c #F1F1F1", ") c #C3C3C3", "! c #C5C5C5", "~ c #ACACAC", "{ c #ADADAD", "] c #AAAAAA", "^ c #8C8C8C", "/ c #CCCCCC", "( c #D1D1D1", "_ c #D2D2D2", ": c #CECECE", "< c #B4B4B4", " ", " ..................... ", " .++++@++++@++++@+++#. ", " .+$$$%$$$$%$$$$%$$$#. ", " .+$$$%$$$$%$$$$%$$$#. ", " .+$$$%$$$$%$$$$%$$$#. ", " .@%%%%%%%%%%%%%%%%%&. ", " .+$$$%****=********-. ", " .+$$$%****=********-. ", " .+$$$%****=********-. ", " .+$$$%****=********-. ", " .@%%%%=============;. ", " .+$$$%*********=***-. ", " .+$$$%*********=***-. ", " .+$$$%*********=***-. ", " .+$$$%*********=***-. ", " .@%%%%=============;. ", " .+>>>,'''')'''')'''>. ", " .+>>>,'''')'''')'''>. ", " .+>>>,'''')'''')'''-. ", " .!~{]^/(_:]/(_:]///<. ", " ..................... ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/tobegin.xpm0000644000076500007650000000272311350032206015623 00000000000000/* XPM */ static char * tobegin_xpm[] = { "24 24 51 1", " c None", ". c #000000", "+ c #F4F7F9", "@ c #BED0E1", "# c #E3EBF2", "$ c #9EB8D1", "% c #C1D2E2", "& c #E0E9F1", "* c #B1C6DA", "= c #E2EAF1", "- c #AEC4D9", "; c #A2BBD3", "> c #ABC2D8", ", c #AAC1D7", "' c #A9C0D6", ") c #B5C9DC", "! c #BCCEDF", "~ c #D4E0EB", "{ c #D3DFEA", "] c #C0D1E1", "^ c #6892B9", "/ c #AFC5DA", "( c #A4BDD5", "_ c #A3BCD4", ": c #9FB9D2", "< c #9BB6D0", "[ c #9AB5CF", "} c #49759E", "| c #DEE7EF", "1 c #1C2D3D", "2 c #DAE4ED", "3 c #A6BED5", "4 c #A0BAD3", "5 c #9CB7D1", "6 c #4B78A2", "7 c #89AAC8", "8 c #4C7AA5", "9 c #B2C7DB", "0 c #7BA0C2", "a c #739ABE", "b c #759BBE", "c c #7299BD", "d c #3C6183", "e c #769CBF", "f c #3F6588", "g c #2A435B", "h c #34536F", "i c #29425A", "j c #2D4760", "k c #648FB7", "l c #314F6A", " ", " ", " ", " .... . ", " .+@. .. ", " .#$. .%. ", " .#$. .&*. ", " .#$. .=-;........ ", " .#$. .=>,'>)!~{]^. ", " .#$. .=/(_;:<<<:[}. ", " .|$. 1234$$:5::4::6. ", " .78..90aaaaaaaaabcd. ", " .ef. .gfffffffffffh. ", " .ef. .gffffffffffh. ", " .ef. .gffhiiiiiij. ", " .ef. .gfh........ ", " .ef. .gh. ", " .ef. .h. ", " .kl. .. ", " .... . ", " ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/toend.xpm0000644000076500007650000000253111350032206015302 00000000000000/* XPM */ static char * toend_xpm[] = { "24 24 43 1", " c None", ". c #000000", "+ c #F4F7F9", "@ c #BED0E1", "# c #AEC4D9", "$ c #E3EBF2", "% c #9EB8D1", "& c #E7EEF4", "* c #5B88B2", "= c #DCE6EF", "- c #5080AD", "; c #EDF2F6", "> c #DFE8F0", ", c #DBE5EE", "' c #D1DEEA", ") c #BACDDF", "! c #A4BDD5", "~ c #9CB7D1", "{ c #080D11", "] c #D4E0EB", "^ c #A0BAD3", "/ c #9BB6D0", "( c #9AB5CF", "_ c #97B3CE", ": c #5F8BB4", "< c #CCDAE7", "[ c #98B4CF", "} c #95B2CE", "| c #4C79A3", "1 c #DEE7EF", "2 c #8DADCA", "3 c #4A77A1", "4 c #4C7AA5", "5 c #2A435B", "6 c #89AAC8", "7 c #84A6C5", "8 c #3F6588", "9 c #769CBF", "0 c #82A5C5", "a c #5382AE", "b c #375978", "c c #648FB7", "d c #314F6A", " ", " ", " ", " . .... ", " .. .+@. ", " .#. .$%. ", " .&*. .$%. ", " ........=%-. .$%. ", " .+;&>,'))!~-{ .$%. ", " .]^~~~/(~^~_:. .$%. ", " .<%([(/~%~~^}|. .1%. ", " .23444444444435..64. ", " .7888888888885. .98. ", " .088888888885. .98. ", " .abbbbbb8885. .98. ", " ........b85. .98. ", " .b5. .98. ", " .5. .98. ", " .. .cd. ", " . .... ", " ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/tree.xpm0000644000076500007650000000343211350032206015131 00000000000000/* XPM */ static char * tree_xpm[] = { "24 24 73 1", " c None", ". c #FF0000", "+ c #F42020", "@ c #EA4040", "# c #CAA0A0", "$ c #F81515", "% c #D28B8B", "& c #C0C0C0", "* c #00FF00", "= c #20BF00", "- c #800000", "; c #DF0000", "> c #EF3030", ", c #20F420", "' c #80D580", ") c #80A060", "! c #A04040", "~ c #FA1010", "{ c #A0CAA0", "] c #805151", "^ c #807979", "/ c #800808", "( c #D18C8C", "_ c #80470E", ": c #008E1C", "< c #60E060", "[ c #806060", "} c #F12B2B", "| c #789595", "1 c #00FFFF", "2 c #15EA15", "3 c #4BE64B", "4 c #4DE6E6", "5 c #699769", "6 c #801A1A", "7 c #806B6B", "8 c #E06060", "9 c #808080", "0 c #803131", "a c #E35555", "b c #C9A5A5", "c c #D58080", "d c #00B871", "e c #309F00", "f c #CF0000", "g c #F61B1B", "h c #CE9595", "i c #00D5AA", "j c #D09090", "k c #7AD77A", "l c #95CE95", "m c #9CC095", "n c #B29595", "o c #C79595", "p c #FC0B0B", "q c #C7ABAB", "r c #00F1E3", "s c #13F913", "t c #009C39", "u c #2BF12B", "v c #75D875", "w c #40BFBF", "x c #4DB34D", "y c #30EF30", "z c #90D090", "A c #DC6B6B", "B c #6EB5B5", "C c #6BDC6B", "D c #35EE35", "E c #40EA40", "F c #54E354", "G c #ABC7AB", "H c #B5C4B5", " ", " .... ", " .+@@@#", " $%&&&&", " ***=-;>& ", " *,'')-!~@ ", " *{& ]^ .... ", " *'& / ....(", " .._:*<& -[ &&&&", " .+}|123 -[ ", " .+#&415** 67 ....8", " $%& 119 * 07.}aaab", " .c& dd ***e-fgh& ", "..8& ii9 ***=-;>& ", "..j 119 klmnop} ", "qa~ 119 .... ", " .. rr9 ****s ~$$h", " .. tt *uuuuv &&&&", " .. w1x*y&&&&& ", " ..91**z ", " AB1CDE ", " ***** ", " ****F ", " GGGH "}; gambit-0.2010.09.01/src/gui/bitmaps/undo.xpm0000644000076500007650000000224411350032206015137 00000000000000/* XPM */ static char * undo_xpm[] = { "24 24 31 1", " c None", ". c #000000", "+ c #EFE5BA", "@ c #EFE7C1", "# c #EED680", "$ c #EFE4B6", "% c #D5B75D", "& c #B29544", "* c #D1B051", "= c #C0AF73", "- c #C0A048", "; c #986B07", "> c #D1940C", ", c #E0B74C", "' c #D9C374", ") c #8F6406", "! c #D59D1C", "~ c #B1933F", "{ c #DFB74A", "] c #CCB76D", "^ c #B8820A", "/ c #D9A72E", "( c #D7A62C", "_ c #C7B26A", ": c #D4B150", "< c #A39256", "[ c #E2CB79", "} c #C9B46B", "| c #8D7E4A", "1 c #AE9C5C", "2 c #96864F", " ", " ", " ", " . ", " .. ", " .+. ", " .@#.... ", " .$####%&. ", " .+#######*. ", " .=#########-. ", " .;>>>>>>,#'.. ", " .)>>>>>>!#~. ", " .)>...;>{]. ", " .;. ..^/#. ", " .. ..>#. ", " . .(_. ", " .:<. ", " .[. ", " .}|. ", " .12. ", " .. ", " ", " ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/zoom1.xpm0000644000076500007650000000662511350032206015246 00000000000000/* XPM */ static char * zoom1_xpm[] = { "24 24 136 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #EFEFEF", "4 c #F3F3F3", "5 c #F1F1F1", "6 c #E5E5E5", "7 c #D2D2D2", "8 c #BCBCBC", "9 c #5E5E5E", "0 c #101010", "a c #212121", "b c #5B5B5B", "c c #CCCCCC", "d c #D7D7D7", "e c #F5F5F5", "f c #FAFAFA", "g c #FBFBFB", "h c #F8F8F8", "i c #F0F0F0", "j c #E1E1E1", "k c #C2C2C2", "l c #434343", "m c #0F0F0F", "n c #1F1F1F", "o c #B9B9B9", "p c #D6D6D6", "q c #4A4A4A", "r c #FDFDFD", "s c #FCFCFC", "t c #F2F2F2", "u c #464646", "v c #E4E4E4", "w c #ABABAB", "x c #0E0E0E", "y c #1B1B1B", "z c #6D6D6D", "A c #494949", "B c #FEFEFE", "C c #4B4B4B", "D c #F9F9F9", "E c #E6E6E6", "F c #575757", "G c #090909", "H c #141414", "I c #A8A8A8", "J c #D8D8D8", "K c #484848", "L c #DCDCDC", "M c #9B9B9B", "N c #060606", "O c #111111", "P c #C5C5C5", "Q c #DFDFDF", "R c #F7F7F7", "S c #BFBFBF", "T c #C6C6C6", "U c #E3E3E3", "V c #ECECEC", "W c #F4F4F4", "X c #474747", "Y c #454545", "Z c #E0E0E0", "` c #BABABA", " . c #050505", ".. c #0B0B0B", "+. c #A5A5A5", "@. c #F6F6F6", "#. c #D1D1D1", "$. c #939393", "%. c #020202", "&. c #0A0A0A", "*. c #5F5F5F", "=. c #D9D9D9", "-. c #444444", ";. c #EEEEEE", ">. c #EDEDED", ",. c #E9E9E9", "'. c #414141", "). c #D4D4D4", "!. c #000000", "~. c #404040", "{. c #3F3F3F", "]. c #CBCBCB", "^. c #3B3B3B", "/. c #DADADA", "(. c #D5D5D5", "_. c #C8C8C8", ":. c #BDBDBD", "<. c #515151", "[. c #C7C7C7", "}. c #CDCDCD", "|. c #B8B8B8", "1. c #030303", "2. c #313131", "3. c #999999", "4. c #BBBBBB", "5. c #B6B6B6", "6. c #909090", "7. c #2B2B2B", "8. c #010101", "9. c #7A7A7A", "0. c #9A9A9A", "a. c #777777", "b. c #3C3C3C", "c. c #686868", "d. c #797979", "e. c #3A3A3A", " ", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 4 5 6 7 8 9 0 ", " a b c d 6 e f g f h e i j k l m ", " n o p 2 q g r r s g h t u v w x ", " y z 7 j A q r B C C s D A u E 1 F G ", " H I J u A q s B C C g A K u E L M N ", " O P Q 3 A A g r r s f R K u 6 1 S N ", " x T U V K A h f f f R W X Y Z d ` . ", " ..+.j 2 u X W @.A A 4 3 u l 1 #.$.%. ", " &.*.=.j -.u ;.3 X u >.,.l '.).~ : !. ", " &.= J '.l 6 E E 2 U Q ~.{.].* %. ", " N ^.c 7 )./.1 /.1 J (.] _.:.$ !. ", " .<.k [.].c }.].]._.k |.Y !. ", " 1.2.3.4.:.8 8 8 5.6.7.!.!.!. ", " 8.1.'.9.0.0.a.b.!.!. !.!.!.!. ", " !.!.!.!.!.!. , , !.!. ", " !.c.. !.!. ", " !.d.e.!.!. ", " !.c.n !. ", " !.!. ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/zoomfit.xpm0000644000076500007650000000772711350032206015674 00000000000000/* XPM */ static char * zoomfit_xpm[] = { "24 24 172 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #EFEFEF", "4 c #F3F3F3", "5 c #F1F1F1", "6 c #E5E5E5", "7 c #D2D2D2", "8 c #BCBCBC", "9 c #5E5E5E", "0 c #101010", "a c #212121", "b c #5B5B5B", "c c #CCCCCC", "d c #D7D7D7", "e c #F5F5F5", "f c #FAFAFA", "g c #FBFBFB", "h c #F8F8F8", "i c #F0F0F0", "j c #E1E1E1", "k c #C2C2C2", "l c #434343", "m c #0F0F0F", "n c #1F1F1F", "o c #B9B9B9", "p c #D6D6D6", "q c #F9F9F9", "r c #FDFDFD", "s c #FCFCFC", "t c #F2F2F2", "u c #ECECEC", "v c #E4E4E4", "w c #ABABAB", "x c #0E0E0E", "y c #171717", "z c #5D5D5D", "A c #EBEBEB", "B c #FEFEFE", "C c #EEEEEE", "D c #E6E6E6", "E c #575757", "F c #090909", "G c #111111", "H c #A8A8A8", "I c #D8D8D8", "J c #91A0AF", "K c #47607B", "L c #E3E3E3", "M c #49637D", "N c #92A0AF", "O c #DCDCDC", "P c #9B9B9B", "Q c #060606", "R c #000000", "S c #141414", "T c #C5C5C5", "U c #DFDFDF", "V c #C7CDD3", "W c #314E6C", "X c #6E8296", "Y c #F7F7F7", "Z c #D9D9D9", "` c #93A2B1", " . c #BFC5CB", ".. c #BFBFBF", "+. c #5C7289", "@. c #65788D", "#. c #BABABA", "$. c #050505", "%. c #2B2B2B", "&. c #A4A4A4", "*. c #E0E0E0", "=. c #C0C6CC", "-. c #7D8EA0", ";. c #F6F6F6", ">. c #8F9DAC", ",. c #B7BDC3", "'. c #D1D1D1", "). c #939393", "!. c #020202", "~. c #9EA8B4", "{. c #48617C", "]. c #EDEDED", "^. c #405A76", "/. c #77899B", "(. c #D4D4D4", "_. c #0A0A0A", ":. c #B3B3B3", "<. c #DBDBDA", "[. c #D5D5D5", "}. c #C4C4C4", "|. c #C6C6C6", "1. c #CBCBCB", "2. c #DEDEDD", "3. c #3E3E3E", "4. c #3A3A3A", "5. c #CBCBCA", "6. c #D1D1D0", "7. c #D6D5D5", "8. c #C2C2C1", "9. c #BDBDBD", "0. c #BEBEBE", "a. c #080808", "b. c #505050", "c. c #C0C0C0", "d. c #C8C8C7", "e. c #C7C7C7", "f. c #C8C8C8", "g. c #BABAB9", "h. c #A6A6A6", "i. c #B5B5B5", "j. c #454545", "k. c #A3A2A2", "l. c #979797", "m. c #B9B9B8", "n. c #BBBBBA", "o. c #B7B7B7", "p. c #AAAAA9", "q. c #7B7B7B", "r. c #2A2A2A", "s. c #FBFBFA", "t. c #E9E9E8", "u. c #B8B8B8", "v. c #393939", "w. c #030303", "x. c #404040", "y. c #787878", "z. c #747473", "A. c #383837", "B. c #FBFAFA", "C. c #E8E7E7", "D. c #E8E8E7", "E. c #E7E6E6", "F. c #CACAC9", "G. c #9F9F9F", "H. c #525151", "I. c #1D1D1D", "J. c #181818", "K. c #E8E8E8", "L. c #686868", "M. c #797979", "N. c #BBBBBB", "O. c #A0A0A0", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 4 5 6 7 8 9 0 ", " a b c d 6 e f g f h e i j k l m ", " n o p 2 q g r r s g h t u v w x ", " y z = ( 7 p A B B r s q e C D 1 E F ", " G H I C e J K L r r g M N C D O P Q ", "R S T U V W W X Y Z g f ` W W .1 ..Q ", "R G T +.W W W W W W W W W W W W @.#.$. ", "R %.&.*.=.W W -.;.5 6 ] >.W W ,.'.).!. ", "R ! 9 I *.6 ~.{.3 ].2 *.^./.1 (.~ : R ", "R - _.:.d <.[.}.T T |.k ..~ | 1.* !. ", "R 2.3.4.5.6.7 7.[.'.{ |.8.- |.9.$ R ", "R g 0.a.b.c.T d.e.f.T ( g.h.i.j.R ", "R g ^ k.Q % l.m.n.o o.i.p.q.r.R R R ", "R s.t./ u.v.w.x.y.l.l.z.A.R R R R R R ", "R B.C.D.E.F.G.H.I.w.w.J.R , , R R ", "R r K.D D D D ~ ~ ~ / h.R R L.. R R ", "R r 2 2 D D D 6 6 v v 9.R R M.4.R R ", "R r D 6 6 6 v v L L L N.R R L.n R ", "R k 9.9.9.8 8 N.N.N.N.O.R R R ", " R R R R R R R R R R R ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/zoomin.xpm0000644000076500007650000000652611350032206015514 00000000000000/* XPM */ static char * zoomin_xpm[] = { "24 24 132 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #EFEFEF", "4 c #F3F3F3", "5 c #F1F1F1", "6 c #E5E5E5", "7 c #D2D2D2", "8 c #BCBCBC", "9 c #5E5E5E", "0 c #101010", "a c #212121", "b c #5B5B5B", "c c #CCCCCC", "d c #D7D7D7", "e c #F5F5F5", "f c #FAFAFA", "g c #FBFBFB", "h c #F8F8F8", "i c #F0F0F0", "j c #E1E1E1", "k c #C2C2C2", "l c #434343", "m c #0F0F0F", "n c #1F1F1F", "o c #B9B9B9", "p c #D6D6D6", "q c #F9F9F9", "r c #FDFDFD", "s c #454545", "t c #F2F2F2", "u c #ECECEC", "v c #E4E4E4", "w c #ABABAB", "x c #0E0E0E", "y c #1B1B1B", "z c #6D6D6D", "A c #FEFEFE", "B c #FCFCFC", "C c #EEEEEE", "D c #E6E6E6", "E c #575757", "F c #090909", "G c #141414", "H c #A8A8A8", "I c #D8D8D8", "J c #F6F6F6", "K c #F4F4F4", "L c #DCDCDC", "M c #9B9B9B", "N c #060606", "O c #111111", "P c #C5C5C5", "Q c #DFDFDF", "R c #444444", "S c #424242", "T c #EDEDED", "U c #BFBFBF", "V c #C6C6C6", "W c #E3E3E3", "X c #414141", "Y c #EAEAEA", "Z c #E0E0E0", "` c #BABABA", " . c #050505", ".. c #0B0B0B", "+. c #A5A5A5", "@. c #D1D1D1", "#. c #939393", "$. c #020202", "%. c #0A0A0A", "&. c #5F5F5F", "*. c #D9D9D9", "=. c #EBEBEB", "-. c #E9E9E9", ";. c #D4D4D4", ">. c #000000", ",. c #E2E2E2", "'. c #3F3F3F", "). c #DADADA", "!. c #CBCBCB", "~. c #3B3B3B", "{. c #D5D5D5", "]. c #C8C8C8", "^. c #BDBDBD", "/. c #515151", "(. c #C7C7C7", "_. c #CDCDCD", ":. c #B8B8B8", "<. c #030303", "[. c #313131", "}. c #999999", "|. c #BBBBBB", "1. c #B6B6B6", "2. c #909090", "3. c #2B2B2B", "4. c #010101", "5. c #7A7A7A", "6. c #9A9A9A", "7. c #777777", "8. c #3C3C3C", "9. c #686868", "0. c #797979", "a. c #3A3A3A", " ", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 4 5 6 7 8 9 0 ", " a b c d 6 e f g f h e i j k l m ", " n o p 2 q g r s s g h t u v w x ", " y z 7 j e f r A s s B q e C D 1 E F ", " G H I C J q B A s s g h K C D L M N ", " O P Q 3 e R R s s s R l S T 6 1 U N ", " x V W u t l R R R R l S X Y Z d ` . ", " ..+.j 2 T 5 K J l l 4 3 u v 1 @.#.$. ", " %.&.*.j D =.C 3 X X T -.v 1 ;.~ : >. ", " %.= I L ,.6 D '.'.W Q ).;.!.* $. ", " N ~.c 7 ;.).1 ).1 I {.] ].^.$ >. ", " ./.k (.!.c _.!.!.].k :.s >. ", " <.[.}.|.^.8 8 8 1.2.3.>.>.>. ", " 4.<.X 5.6.6.7.8.>.>. >.>.>.>. ", " >.>.>.>.>.>. , , >.>. ", " >.9.. >.>. ", " >.0.a.>.>. ", " >.9.n >. ", " >.>. ", " "}; gambit-0.2010.09.01/src/gui/bitmaps/zoomout.xpm0000644000076500007650000000650711350032206015714 00000000000000/* XPM */ static char * zoomout_xpm[] = { "24 24 131 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #EFEFEF", "4 c #F3F3F3", "5 c #F1F1F1", "6 c #E5E5E5", "7 c #D2D2D2", "8 c #BCBCBC", "9 c #5E5E5E", "0 c #101010", "a c #212121", "b c #5B5B5B", "c c #CCCCCC", "d c #D7D7D7", "e c #F5F5F5", "f c #FAFAFA", "g c #FBFBFB", "h c #F8F8F8", "i c #F0F0F0", "j c #E1E1E1", "k c #C2C2C2", "l c #434343", "m c #0F0F0F", "n c #1F1F1F", "o c #B9B9B9", "p c #D6D6D6", "q c #F9F9F9", "r c #FDFDFD", "s c #FCFCFC", "t c #F2F2F2", "u c #ECECEC", "v c #E4E4E4", "w c #ABABAB", "x c #0E0E0E", "y c #1B1B1B", "z c #6D6D6D", "A c #FEFEFE", "B c #EEEEEE", "C c #E6E6E6", "D c #575757", "E c #090909", "F c #141414", "G c #A8A8A8", "H c #D8D8D8", "I c #F6F6F6", "J c #F4F4F4", "K c #DCDCDC", "L c #9B9B9B", "M c #060606", "N c #111111", "O c #C5C5C5", "P c #DFDFDF", "Q c #444444", "R c #454545", "S c #424242", "T c #EDEDED", "U c #BFBFBF", "V c #C6C6C6", "W c #E3E3E3", "X c #414141", "Y c #EAEAEA", "Z c #E0E0E0", "` c #BABABA", " . c #050505", ".. c #0B0B0B", "+. c #A5A5A5", "@. c #D1D1D1", "#. c #939393", "$. c #020202", "%. c #0A0A0A", "&. c #5F5F5F", "*. c #D9D9D9", "=. c #EBEBEB", "-. c #E9E9E9", ";. c #D4D4D4", ">. c #000000", ",. c #E2E2E2", "'. c #DADADA", "). c #CBCBCB", "!. c #3B3B3B", "~. c #D5D5D5", "{. c #C8C8C8", "]. c #BDBDBD", "^. c #515151", "/. c #C7C7C7", "(. c #CDCDCD", "_. c #B8B8B8", ":. c #030303", "<. c #313131", "[. c #999999", "}. c #BBBBBB", "|. c #B6B6B6", "1. c #909090", "2. c #2B2B2B", "3. c #010101", "4. c #7A7A7A", "5. c #9A9A9A", "6. c #777777", "7. c #3C3C3C", "8. c #686868", "9. c #797979", "0. c #3A3A3A", " ", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 4 5 6 7 8 9 0 ", " a b c d 6 e f g f h e i j k l m ", " n o p 2 q g r r s g h t u v w x ", " y z 7 j e f r A A r s q e B C 1 D E ", " F G H B I q s A A r g h J B C K L M ", " N O P 3 e Q Q R R R Q l S T 6 1 U M ", " x V W u t l Q Q Q Q l S X Y Z d ` . ", " ..+.j 2 T 5 J I I e 4 3 u v 1 @.#.$. ", " %.&.*.j C =.B 3 3 B T -.v 1 ;.~ : >. ", " %.= H K ,.6 C C 2 W P '.;.).* $. ", " M !.c 7 ;.'.1 '.1 H ~.] {.].$ >. ", " .^.k /.).c (.).).{.k _.R >. ", " :.<.[.}.].8 8 8 |.1.2.>.>.>. ", " 3.:.X 4.5.5.6.7.>.>. >.>.>.>. ", " >.>.>.>.>.>. , , >.>. ", " >.8.. >.>. ", " >.9.0.>.>. ", " >.8.n >. ", " >.>. ", " "}; gambit-0.2010.09.01/src/gui/dcsvg.cc0000644000076500007650000005635411350032206013435 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: svg.cpp // Purpose: SVG sample // Author: Chris Elliott // Modified by: // RCS-ID: $Id$ // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "dcsvg.h" #include "wx/image.h" #define wxSVG_DEBUG FALSE // or TRUE to see the calls being executed #define newline wxString(wxT("\n")) #define space wxString(wxT(" ")) #define semicolon wxString(wxT(";")) #define wx_round(a) (int)((a)+.5) #ifdef __BORLANDC__ #pragma warn -rch #pragma warn -ccc #endif static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } ; wxString wxColStr ( wxColour c ) { unsigned char r, g, b ; r = c.Red (); g = c.Green (); b = c. Blue (); // possible Unicode bug here wxString s = wxDecToHex(r) + wxDecToHex(g) + wxDecToHex(b) ; return s ; } wxString wxBrushString ( wxColour c, int style ) { wxString s = wxT("fill:#") + wxColStr (c) + semicolon + space ; switch ( style ) { case wxSOLID : s = s + wxT("fill-opacity:1.0; "); break ; case wxTRANSPARENT: s = s + wxT("fill-opacity:0.0; "); break ; default : wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::Requested Brush Style not available")) ; } s = s + newline ; return s ; } void wxSVGFileDC::Init (wxString f, int Width, int Height, float dpi) { //set up things first wxDCBase does all this? m_width = Width ; m_height = Height ; m_clipping = FALSE; m_OK = TRUE; m_mm_to_pix_x = dpi/25.4; m_mm_to_pix_y = dpi/25.4; m_signX = m_signY = 1; m_userScaleX = m_userScaleY = m_deviceOriginX = m_deviceOriginY = 0; m_OriginX = m_OriginY = 0; m_logicalOriginX = m_logicalOriginY = 0; m_logicalScaleX = m_logicalScaleY = 0 ; m_scaleX = m_scaleY = 1.0 ; m_logicalFunction = wxCOPY; m_backgroundMode = wxTRANSPARENT; m_mappingMode = wxMM_TEXT; m_backgroundBrush = *wxTRANSPARENT_BRUSH; m_textForegroundColour = *wxBLACK; m_textBackgroundColour = *wxWHITE; m_colour = wxColourDisplay(); m_pen = *wxBLACK_PEN; m_font = *wxNORMAL_FONT; m_brush = *wxWHITE_BRUSH; m_graphics_changed = TRUE ; ////////////////////code here m_outfile = new wxFileOutputStream(f) ; m_OK = m_outfile->Ok (); if (m_OK) { m_filename = f ; m_sub_images = 0 ; wxString s ; s = wxT("") ; s = s + newline ; write(s); s = wxT(" ")+ newline ; write(s); s.Printf ( wxT(" \n"), float(Width)/dpi*2.54, float(Height)/dpi*2.54, Width, Height ); write(s); s = wxT("SVG Picture created as ") + wxFileNameFromPath(f) + wxT(" ") + newline ; write(s); s = wxString (wxT("Picture generated by wxSVG ")) + wxSVGVersion + wxT(" ")+ newline ; write(s); s = wxT("") + newline ; write(s); } } // constructors wxSVGFileDC::wxSVGFileDC (wxString f) { // quarter 640x480 screen display at 72 dpi Init (f,320,240,72.0); }; wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height) { Init (f,Width,Height,72.0); }; wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height, float dpi) { Init (f,Width,Height,dpi); }; wxSVGFileDC::~wxSVGFileDC() { wxString s = wxT(" \n \n") ; write(s); delete m_outfile ; } ////////////////////////////////////////////////////////////////////////////////////////// void wxSVGFileDC::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) { if (m_graphics_changed) NewGraphics (); wxString s ; s.Printf ( wxT(" \n"), x1,y1,x2,y2 ); if (m_OK) { write(s); } wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawLine Call executed")) ; CalcBoundingBox(x1, y1) ; CalcBoundingBox(x2, y2) ; return; }; void wxSVGFileDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset ) { for ( int i = 1; i < n ; i++ ) { DoDrawLine ( points [i-1].x + xoffset, points [i-1].y + yoffset, points [ i ].x + xoffset, points [ i ].y + yoffset ) ; } } void wxSVGFileDC::DoDrawPoint (wxCoord x1, wxCoord y1) { wxString s; if (m_graphics_changed) NewGraphics (); s = wxT(" ") + newline ; write(s); DrawLine ( x1,y1,x1,y1 ); s = wxT(""); write(s); } void wxSVGFileDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height) { wxDCBase::DoDrawCheckMark (x1,y1,width,height) ; } void wxSVGFileDC::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1) { DoDrawRotatedText(text, x1,y1,0.0); wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawText Call executed")) ; } void wxSVGFileDC::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle) { //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW if (m_graphics_changed) NewGraphics (); wxString s, sTmp; // calculate bounding box wxCoord w, h, desc ; DoGetTextExtent(sText, &w, &h, &desc); double rad = DegToRad(angle); // wxT("upper left") and wxT("upper right") CalcBoundingBox(x, y); CalcBoundingBox((wxCoord)(x + w*cos(rad)), (wxCoord)(y - h*sin(rad))); // wxT("bottom left") and wxT("bottom right") x += (wxCoord)(h*sin(rad)); y += (wxCoord)(h*cos(rad)); CalcBoundingBox(x, y); CalcBoundingBox((wxCoord)(x + h*sin(rad)), (wxCoord)(y + h*cos(rad))); if (m_backgroundMode == wxSOLID) { // draw background first // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ; sTmp.Printf ( wxT(" "), -angle, x,y ) ; s = s + sTmp + newline ; write(s); } //now do the text itself s.Printf (wxT(" 0) s = s + wxT("style=\"font-family:") + sTmp + wxT("; "); else s = s + wxT("style=\" ") ; wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") }; s = s + wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + semicolon + space; wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") }; s = s + wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + semicolon + space; sTmp.Printf (wxT("font-size:%dpt; fill:#"), m_font.GetPointSize () ); s = s + sTmp ; s = s + wxColStr (m_textForegroundColour) + wxT("; stroke:#") + wxColStr (m_textForegroundColour) + wxT("; ") ; sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle, x,y ) ; s = s + sTmp + sText + wxT(" ") + newline ; if (m_OK) { write(s); } wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ; } void wxSVGFileDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) { DoDrawRoundedRectangle(x, y, width, height, 0) ; } void wxSVGFileDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) { if (m_graphics_changed) NewGraphics (); wxString s ; s.Printf ( wxT(" ") + newline ; write(s); wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ; CalcBoundingBox(x, y) ; CalcBoundingBox(x + width, y + height) ; } void wxSVGFileDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle) { if (m_graphics_changed) NewGraphics (); wxString s, sTmp ; s = wxT(" ") ; s = s + newline ; write(s); wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ; } void wxSVGFileDC::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height) { if (m_graphics_changed) NewGraphics (); int rh = height /2 ; int rw = width /2 ; wxString s; s.Printf ( wxT(" ") + newline ; write(s); wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ; CalcBoundingBox(x, y) ; CalcBoundingBox(x + width, y + height) ; } void wxSVGFileDC::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc) { /* Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) and ending at (x2, y2). The current pen is used for the outline and the current brush for filling the shape. The arc is drawn in an anticlockwise direction from the start point to the end point. Might be better described as Pie drawing */ if (m_graphics_changed) NewGraphics (); wxString s ; // we need the radius of the circle which has two estimates double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) ); double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) ); wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ; if ( fabs ( r2-r1 ) > 3 ) //pixels { s = wxT(" \n") ; write(s); } double theta1 = atan2((double)(yc-y1),(double)(x1-xc)); if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2; double theta2 = atan2((double)(yc-y2), (double)(x2-xc)); if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2; if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2 ; int fArc ; // flag for large or small arc 0 means less than 180 degrees if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0 ; int fSweep = 0 ; // flag for sweep always 0 s.Printf ( wxT(" ") + newline ; if (m_OK) { write(s); } wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed")) ; } void wxSVGFileDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea) { /* Draws an arc of an ellipse. The current pen is used for drawing the arc and the current brush is used for drawing the pie. This function is currently only available for X window and PostScript device contexts. x and y specify the x and y coordinates of the upper-left corner of the rectangle that contains the ellipse. width and height specify the width and height of the rectangle that contains the ellipse. start and end specify the start and end of the arc relative to the three-o'clock position from the center of the rectangle. Angles are specified in degrees (360 is a complete circle). Positive values mean counter-clockwise motion. If start is equal to end, a complete ellipse will be drawn. */ //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW if (m_graphics_changed) NewGraphics (); wxString s ; //radius double rx = w / 2 ; double ry = h / 2 ; // center double xc = x + rx ; double yc = y + ry ; double xs, ys, xe, ye ; xs = xc + rx * cos (DegToRad(sa)) ; xe = xc + rx * cos (DegToRad(ea)) ; ys = yc - ry * sin (DegToRad(sa)) ; ye = yc - ry * sin (DegToRad(ea)) ; ///now same as circle arc... double theta1 = atan2(ys-yc, xs-xc); double theta2 = atan2(ye-yc, xe-xc); int fArc ; // flag for large or small arc 0 means less than 180 degrees if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0 ; int fSweep ; if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0 ; s.Printf ( wxT(" ") + newline ; if (m_OK) { write(s); } wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ; } void wxSVGFileDC::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , wxFont *font) const { wxScreenDC sDC ; sDC.SetFont (m_font); if ( font != NULL ) sDC.SetFont ( *font ); sDC.GetTextExtent(string, w, h, descent, externalLeading ); wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed")) ; } wxCoord wxSVGFileDC::GetCharHeight() const { wxScreenDC sDC ; sDC.SetFont (m_font); wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing")) ; return ( sDC.GetCharHeight() ); } wxCoord wxSVGFileDC::GetCharWidth() const { wxScreenDC sDC ; sDC.SetFont (m_font); wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing")) ; return ( sDC.GetCharWidth() ) ; } /// Set Functions ///////////////////////////////////////////////////////////////// void wxSVGFileDC::SetBackground( const wxBrush &brush ) { m_backgroundBrush = brush; return; } void wxSVGFileDC::SetBackgroundMode( int mode ) { m_backgroundMode = mode; return; } void wxSVGFileDC::SetBrush(const wxBrush& brush) { m_brush = brush ; m_graphics_changed = TRUE ; wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed")) ; } void wxSVGFileDC::SetPen(const wxPen& pen) { // width, color, ends, joins : currently implemented // dashes, stipple : not implemented m_pen = pen ; m_graphics_changed = TRUE ; wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed")) ; } void wxSVGFileDC::NewGraphics () { int w = m_pen.GetWidth (); wxColour c = m_pen.GetColour () ; wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn; sBrush = wxT("\n \n") ; } sLast.Printf ( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"), w, m_OriginX, m_OriginY, m_scaleX, m_scaleY ); s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn; write(s); m_graphics_changed = FALSE ; wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed")) ; } void wxSVGFileDC::SetFont(const wxFont& font) { m_font = font ; wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed")) ; } void wxSVGFileDC::ComputeScaleAndOrigin() { m_scaleX = m_logicalScaleX * m_userScaleX; m_scaleY = m_logicalScaleY * m_userScaleY; m_OriginX = m_logicalOriginX * m_logicalScaleX + m_deviceOriginX ; m_OriginY = m_logicalOriginY * m_logicalScaleY + m_deviceOriginY ; m_graphics_changed = TRUE; } int wxSVGFileDC::GetMapMode() { return m_mappingMode ; } void wxSVGFileDC::SetMapMode( int mode ) { switch (mode) { case wxMM_TWIPS: SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y ); break; case wxMM_POINTS: SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y ); break; case wxMM_METRIC: SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y ); break; case wxMM_LOMETRIC: SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 ); break; default: case wxMM_TEXT: SetLogicalScale( 1.0, 1.0 ); break; } m_mappingMode = mode; /* we don't do this mega optimisation if (mode != wxMM_TEXT) { m_needComputeScaleX = TRUE; m_needComputeScaleY = TRUE; } */ } void wxSVGFileDC::GetUserScale(double *x, double *y) const { *x = m_userScaleX ; *y = m_userScaleY ; } void wxSVGFileDC::SetUserScale( double x, double y ) { // allow negative ? -> no m_userScaleX = x; m_userScaleY = y; ComputeScaleAndOrigin(); } void wxSVGFileDC::SetLogicalScale( double x, double y ) { // allow negative ? m_logicalScaleX = x; m_logicalScaleY = y; ComputeScaleAndOrigin(); } void wxSVGFileDC::SetLogicalOrigin( wxCoord x, wxCoord y ) { // is this still correct ? m_logicalOriginX = x * m_signX; m_logicalOriginY = y * m_signY; ComputeScaleAndOrigin(); } void wxSVGFileDC::SetDeviceOrigin( wxCoord x, wxCoord y ) { // only wxPostScripDC has m_signX = -1, m_deviceOriginX = x; m_deviceOriginY = y; ComputeScaleAndOrigin(); } void wxSVGFileDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) { // only wxPostScripDC has m_signX = -1, m_signX = (xLeftRight ? 1 : -1); m_signY = (yBottomUp ? -1 : 1); ComputeScaleAndOrigin(); } // export a bitmap as a raster image in png bool wxSVGFileDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, wxDC* source, wxCoord xsrc, wxCoord ysrc, int logicalFunc /*= wxCOPY*/, bool useMask /*= FALSE*/, wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/) { if (logicalFunc != wxCOPY) { wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ; return FALSE ; } if (useMask != FALSE) { wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ; return FALSE ; } wxBitmap myBitmap (width, height) ; wxMemoryDC memDC; memDC.SelectObject( myBitmap ); memDC.Blit(0, 0, width, height, source, xsrc, ysrc); memDC.SelectObject( wxNullBitmap ); DoDrawBitmap(myBitmap, xdest, ydest); wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed")) ; return FALSE ; } void wxSVGFileDC::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y) { wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() ) ; wxMemoryDC memDC; memDC.SelectObject( myBitmap ); memDC.DrawIcon(myIcon,0,0); memDC.SelectObject( wxNullBitmap ); DoDrawBitmap(myBitmap, x, y); wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ; return ; } void wxSVGFileDC::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ ) { if (m_graphics_changed) NewGraphics (); wxString sTmp, s, sPNG ; wxImage::AddHandler(new wxPNGHandler); // create suitable file name sTmp.Printf ( wxT("_image%d.png"), m_sub_images); sPNG = m_filename.BeforeLast(wxT('.')) + sTmp; while (wxFile::Exists(sPNG) ) { m_sub_images ++ ; sTmp.Printf ( wxT("_image%d.png"), m_sub_images); sPNG = m_filename.BeforeLast(wxT('.')) + sTmp; } //create copy of bitmap (wxGTK doesn't like saving a constant bitmap) wxBitmap myBitmap = bmp ; //save it bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG); // refrence the bitmap from the SVG doc int w = myBitmap.GetWidth(); int h = myBitmap.GetHeight(); sTmp.Printf ( wxT(" \n"), sPNG.c_str() ); s = s + sTmp + wxT("Image from wxSVG ") + newline; if (m_OK && bPNG_OK) { write(s); } m_OK = m_outfile->Ok () && bPNG_OK; wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ; return ; } // --------------------------------------------------------------------------- // coordinates transformations // --------------------------------------------------------------------------- wxCoord wxSVGFileDC::DeviceToLogicalX(wxCoord x) const { return XDEV2LOG(x); } wxCoord wxSVGFileDC::DeviceToLogicalY(wxCoord y) const { return YDEV2LOG(y); } wxCoord wxSVGFileDC::DeviceToLogicalXRel(wxCoord x) const { return XDEV2LOGREL(x); } wxCoord wxSVGFileDC::DeviceToLogicalYRel(wxCoord y) const { return YDEV2LOGREL(y); } wxCoord wxSVGFileDC::LogicalToDeviceX(wxCoord x) const { return XLOG2DEV(x); } wxCoord wxSVGFileDC::LogicalToDeviceY(wxCoord y) const { return YLOG2DEV(y); } wxCoord wxSVGFileDC::LogicalToDeviceXRel(wxCoord x) const { return XLOG2DEVREL(x); } wxCoord wxSVGFileDC::LogicalToDeviceYRel(wxCoord y) const { return YLOG2DEVREL(y); } void wxSVGFileDC::write(const wxString &s) { const wxWX2MBbuf buf = s.mb_str(wxConvUTF8); m_outfile->Write(buf, strlen((const char *)buf)); m_OK = m_outfile->Ok(); } #ifdef __BORLANDC__ #pragma warn .rch #pragma warn .ccc #endif gambit-0.2010.09.01/src/gui/dcsvg.h0000644000076500007650000002436011350032206013267 00000000000000#ifndef __DCSVG_H #define __DCSVG_H #include #include /* #ifdef WXMAKINGDLL_SVG #define WXDLLIMPEXP_SVG WXEXPORT #elif defined(WXUSINGDLL) #define WXDLLIMPEXP_SVG WXIMPORT #else // not making nor using DLL */ #define WXDLLIMPEXP_SVG /* #endif */ #define wxSVGVersion wxT("v0100") #ifdef __BORLANDC__ #pragma warn -rch #pragma warn -ccc #endif class WXDLLIMPEXP_SVG wxSVGFileDC : public wxDC { private: wxFileOutputStream * m_outfile ; wxString m_filename ; //holds number of png format images we have int m_sub_images ; bool m_OK, m_graphics_changed ; int m_width, m_height ; double m_logicalScaleX, m_logicalScaleY, m_userScaleX, m_userScaleY, m_scaleX, m_scaleY, m_OriginX, m_OriginY, m_mm_to_pix_x, m_mm_to_pix_y; bool m_needComputeScaleX, m_needComputeScaleY; // not yet used bool DoGetPixel(wxCoord, wxCoord, class wxColour *) const { wxASSERT_MSG (false, wxT("wxSVGFILEDC::DoGetPixel Call not implemented")); return true; }; virtual bool DoBlit(wxCoord, wxCoord, wxCoord, wxCoord, class wxDC *, wxCoord, wxCoord, int = wxCOPY, bool = 0, int = -1, int = -1) ; void DoCrossHair(wxCoord, wxCoord) { wxASSERT_MSG (false, wxT("wxSVGFILEDC::CrossHair Call not implemented")); return ; }; void DoDrawArc(wxCoord, wxCoord, wxCoord, wxCoord, wxCoord, wxCoord); void DoDrawBitmap(const class wxBitmap &, wxCoord, wxCoord, bool = 0) ; void DoDrawCheckMark(wxCoord x, wxCoord y, wxCoord width, wxCoord height) ; void DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height) ; void DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea) ; void DoDrawIcon(const class wxIcon &, wxCoord, wxCoord) ; void DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) ; void DoDrawPoint(wxCoord, wxCoord) ; void DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle) ; void DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) ; void DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle) ; void DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius = 20) ; void DoDrawText(const wxString& text, wxCoord x, wxCoord y); bool DoFloodFill(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxColour& WXUNUSED(col), int WXUNUSED(style) = wxFLOOD_SURFACE) { wxASSERT_MSG (false, wxT("wxSVGFILEDC::DoFloodFill Call not implemented")); return false ; }; void DoGetSize(int * x, int *y) const { *x = m_width; *y = m_height ; return ; } ; void DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent = NULL, wxCoord *externalLeading = NULL, wxFont *font = NULL) const ; void DoSetClippingRegionAsRegion(const class wxRegion &) { wxASSERT_MSG (false, wxT("wxSVGFILEDC::DoSetClippingRegionAsRegion Call not yet implemented")); return ; }; void Init (wxString f, int Width, int Height, float dpi); void NewGraphics () ; #ifdef XDEV2LOG #undef XDEV2LOG #endif wxCoord XDEV2LOG(wxCoord x) const { wxCoord new_x = x - m_deviceOriginX; if (new_x > 0) return (wxCoord)((double)(new_x) / m_scaleX + 0.5) * m_signX + m_logicalOriginX; else return (wxCoord)((double)(new_x) / m_scaleX - 0.5) * m_signX + m_logicalOriginX; } #ifdef XDEV2LOGREL #undef XDEV2LOGREL #endif wxCoord XDEV2LOGREL(wxCoord x) const { if (x > 0) return (wxCoord)((double)(x) / m_scaleX + 0.5); else return (wxCoord)((double)(x) / m_scaleX - 0.5); } #ifdef YDEV2LOG #undef YDEV2LOG #endif wxCoord YDEV2LOG(wxCoord y) const { wxCoord new_y = y - m_deviceOriginY; if (new_y > 0) return (wxCoord)((double)(new_y) / m_scaleY + 0.5) * m_signY + m_logicalOriginY; else return (wxCoord)((double)(new_y) / m_scaleY - 0.5) * m_signY + m_logicalOriginY; } #ifdef YDEV2LOGREL #undef YDEV2LOGREL #endif wxCoord YDEV2LOGREL(wxCoord y) const { if (y > 0) return (wxCoord)((double)(y) / m_scaleY + 0.5); else return (wxCoord)((double)(y) / m_scaleY - 0.5); } #ifdef XLOG2DEV #undef XLOG2DEV #endif wxCoord XLOG2DEV(wxCoord x) const { wxCoord new_x = x - m_logicalOriginX; if (new_x > 0) return (wxCoord)((double)(new_x) * m_scaleX + 0.5) * m_signX + m_deviceOriginX; else return (wxCoord)((double)(new_x) * m_scaleX - 0.5) * m_signX + m_deviceOriginX; } #ifdef XLOG2DEVREL #undef XLOG2DEVREL #endif wxCoord XLOG2DEVREL(wxCoord x) const { if (x > 0) return (wxCoord)((double)(x) * m_scaleX + 0.5); else return (wxCoord)((double)(x) * m_scaleX - 0.5); } #ifdef YLOG2DEV #undef YLOG2DEV #endif wxCoord YLOG2DEV(wxCoord y) const { wxCoord new_y = y - m_logicalOriginY; if (new_y > 0) return (wxCoord)((double)(new_y) * m_scaleY + 0.5) * m_signY + m_deviceOriginY; else return (wxCoord)((double)(new_y) * m_scaleY - 0.5) * m_signY + m_deviceOriginY; } #ifdef YLOG2DEVREL #undef YLOG2DEVREL #endif wxCoord YLOG2DEVREL(wxCoord y) const { if (y > 0) return (wxCoord)((double)(y) * m_scaleY + 0.5); else return (wxCoord)((double)(y) * m_scaleY - 0.5); } void write(const wxString &s); public: wxSVGFileDC (wxString f); wxSVGFileDC (wxString f, int Width, int Height); wxSVGFileDC (wxString f, int Width, int Height, float dpi); ~wxSVGFileDC(); bool CanDrawBitmap() const { return true; }; bool CanGetTextExtent() const { return true; }; int GetDepth() const { wxASSERT_MSG (false, wxT("wxSVGFILEDC::GetDepth Call not implemented")); return -1 ; }; void BeginDrawing() { return;}; bool Blit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, wxDC* source, wxCoord xsrc, wxCoord ysrc, int logicalFunc = wxCOPY, bool useMask = false) { return DoBlit(xdest, ydest, width, height, source, xsrc, ysrc, logicalFunc, useMask); }; void Clear() { wxASSERT_MSG (false, wxT("wxSVGFILEDC::Clear() Call not implemented \nNot sensible for an output file?")); return ; }; void CrossHair(wxCoord x, wxCoord y) { DoCrossHair (x,y); return; }; virtual void ComputeScaleAndOrigin(); void DestroyClippingRegion() { wxASSERT_MSG (false, wxT("wxSVGFILEDC::void Call not yet implemented")); return ; }; wxCoord DeviceToLogicalX(wxCoord x) const ; wxCoord DeviceToLogicalXRel(wxCoord x) const ; wxCoord DeviceToLogicalY(wxCoord y) const ; wxCoord DeviceToLogicalYRel(wxCoord y) const ; void DrawBitmap(const wxBitmap& bitmap, wxCoord x, wxCoord y, bool transparent) { DoDrawBitmap ( bitmap, x, y, transparent ) ; return ;}; void DrawIcon(const wxIcon& icon, wxCoord x, wxCoord y) {DoDrawIcon(icon, x, y) ; return ; }; void DoDrawLines(int n, wxPoint points[], wxCoord xoffset = 0, wxCoord yoffset = 0) ; void EndDoc() { return ; }; void EndDrawing() { return ; }; void EndPage() { return ; }; void FloodFill(wxCoord x, wxCoord y, wxColour *colour, int style=wxFLOOD_SURFACE) { DoFloodFill (x, y, *colour, style); return ;} ; wxCoord GetCharHeight() const; wxCoord GetCharWidth() const; void GetClippingBox(wxCoord *WXUNUSED(x), wxCoord *WXUNUSED(y), wxCoord * WXUNUSED(width), wxCoord * WXUNUSED(height)) { wxASSERT_MSG (false, wxT("wxSVGFILEDC::GetClippingBox Call not yet implemented")); return ; }; int GetLogicalFunction() { wxASSERT_MSG (false, wxT("wxSVGFILEDC::GetLogicalFunction() Call not implemented")); return wxCOPY ; }; int GetMapMode() ; bool GetPixel(wxCoord x, wxCoord y, wxColour *colour) { return DoGetPixel (x, y, colour) ; } ; void GetUserScale(double *x, double *y) const ; wxCoord LogicalToDeviceX(wxCoord x) const ; wxCoord LogicalToDeviceXRel(wxCoord x) const ; wxCoord LogicalToDeviceY(wxCoord y) const ; wxCoord LogicalToDeviceYRel(wxCoord y) const ; bool Ok() const {return m_OK;}; void SetAxisOrientation( bool xLeftRight, bool yBottomUp ) ; void SetClippingRegion(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxCoord WXUNUSED(width), wxCoord WXUNUSED(height)) { wxASSERT_MSG (false, wxT("wxSVGFILEDC::SetClippingRegion Call not yet implemented")); return ; }; void SetPalette(const wxPalette& WXUNUSED(palette)) { wxASSERT_MSG (false, wxT("wxSVGFILEDC::SetPalette Call not yet implemented")); return ; }; void SetBackground( const wxBrush &brush ) ; void SetBackgroundMode( int mode ) ; void SetBrush(const wxBrush& brush) ; void SetFont(const wxFont& font) ; void SetLogicalFunction(int WXUNUSED(function)) { wxASSERT_MSG (false, wxT("wxSVGFILEDC::SetLogicalFunction Call implemented")); return ; }; void SetLogicalScale( double x, double y ) ; void SetLogicalOrigin( wxCoord x, wxCoord y ) ; void SetDeviceOrigin( wxCoord x, wxCoord y ) ; void SetMapMode(int anint) ; void SetPen(const wxPen& pen) ; void SetUserScale(double xScale, double yScale) ; bool StartDoc(const wxString& WXUNUSED(message)) { return false; }; void StartPage() { return ; }; }; #ifdef __BORLANDC__ #pragma warn .rch #pragma warn .ccc #endif #endif gambit-0.2010.09.01/src/gui/dlabout.cc0000644000076500007650000000716411441446350013766 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlabout.cc // Implementation of "about" dialog // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "dlabout.h" #include "bitmaps/gambitbig.xpm" static wxStaticText *FormattedText(wxWindow *p_parent, const wxString &p_label, const wxFont &p_font) { wxStaticText *t = new wxStaticText(p_parent, wxID_STATIC, p_label); t->SetFont(p_font); return t; } gbtAboutDialog::gbtAboutDialog(wxWindow *p_parent) : wxDialog(p_parent, -1, _T("About Gambit..."), wxDefaultPosition, wxDefaultSize) { SetFont(wxFont(12, wxROMAN, wxNORMAL, wxBOLD)); wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); topSizer->Add(new wxStaticBitmap(this, wxID_STATIC, wxBitmap(gambitbig_xpm)), 0, wxALL | wxALIGN_CENTER, 20); topSizer->Add(new wxStaticText(this, wxID_STATIC, _T("Gambit: Software Tools for Game Theory")), 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_CENTER, 20); topSizer->Add(new wxStaticText(this, wxID_STATIC, _T("Graphical Interface")), 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, 5); topSizer->Add(new wxStaticText(this, wxID_STATIC, _T("Version " VERSION)), 0, wxALIGN_CENTER, 5); topSizer->Add(FormattedText(this, _T("http://www.gambit-project.org"), wxFont(12, wxMODERN, wxNORMAL, wxNORMAL)), 0, wxTOP | wxALIGN_CENTER, 10); topSizer->Add(FormattedText(this, _("Built with " wxVERSION_STRING), wxFont(12, wxROMAN, wxNORMAL, wxNORMAL)), 0, wxTOP | wxALIGN_CENTER, 20); topSizer->Add(FormattedText(this, _T("http://www.wxwidgets.org"), wxFont(12, wxMODERN, wxNORMAL, wxNORMAL)), 0, wxALIGN_CENTER, 5); topSizer->Add(FormattedText(this, _T("Copyright (C) 1994-2010, The Gambit Project"), wxFont(12, wxROMAN, wxNORMAL, wxNORMAL)), 0, wxTOP | wxALIGN_CENTER, 20); topSizer->Add(FormattedText(this, _("Theodore Turocy, Project Maintainer"), wxFont(12, wxROMAN, wxNORMAL, wxNORMAL)), 0, wxALIGN_CENTER, 5); topSizer->Add(FormattedText(this, _T("T.Turocy@uea.ac.uk"), wxFont(12, wxMODERN, wxNORMAL, wxNORMAL)), 0, wxALIGN_CENTER, 5); topSizer->Add(FormattedText(this, _("This program is free software,"), wxFont(12, wxROMAN, wxNORMAL, wxNORMAL)), 0, wxTOP | wxALIGN_CENTER, 20); topSizer->Add(FormattedText(this, _("distributed under the terms of"), wxFont(12, wxROMAN, wxNORMAL, wxNORMAL)), 0, wxALIGN_CENTER, 5); topSizer->Add(FormattedText(this, _("the GNU General Public License"), wxFont(12, wxROMAN, wxNORMAL, wxNORMAL)), 0, wxALIGN_CENTER, 5); wxButton *okButton = new wxButton(this, wxID_OK, _("OK")); okButton->SetDefault(); topSizer->Add(okButton, 0, wxALL | wxALIGN_RIGHT, 20); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); CenterOnParent(); } gambit-0.2010.09.01/src/gui/dlabout.h0000644000076500007650000000207011435216100013606 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlabout.h // Declaration of "about" dialog // // 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 DLABOUT_H #define DLABOUT_H class gbtAboutDialog : public wxDialog { public: gbtAboutDialog(wxWindow *p_parent); virtual ~gbtAboutDialog() { } }; #endif // DLABOUT_H gambit-0.2010.09.01/src/gui/dleditmove.cc0000644000076500007650000001455411435216100014460 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dleditmove.cc // Dialog for viewing and editing properties of a move // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "libgambit/libgambit.h" #include "dleditmove.h" #include "renratio.h" class gbtActionSheet : public wxSheet { private: Gambit::GameInfoset m_infoset; // Overriding wxSheet members wxSheetCellAttr GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const; public: gbtActionSheet(wxWindow *p_parent, Gambit::GameInfoset p_infoset) : wxSheet(p_parent, 1), m_infoset(p_infoset) { } }; wxSheetCellAttr gbtActionSheet::GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const { if (IsRowLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultRowLabelAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); return attr; } else if (IsColLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultColLabelAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); return attr; } else if (IsCornerLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultCornerLabelAttr); return attr; } wxSheetCellAttr attr(GetSheetRefData()->m_defaultGridCellAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(false); if (p_coords.GetCol() == 1) { attr.SetRenderer(wxSheetCellRenderer(new gbtRationalRendererRefData())); attr.SetEditor(wxSheetCellEditor(new gbtRationalEditorRefData())); } else { attr.SetEditor(wxSheetCellEditor(new wxSheetCellTextEditorRefData())); } return attr; } //====================================================================== // class gbtEditMoveDialog //====================================================================== gbtEditMoveDialog::gbtEditMoveDialog(wxWindow *p_parent, Gambit::GameInfoset p_infoset) : wxDialog(p_parent, -1, _("Move properties"), wxDefaultPosition), m_infoset(p_infoset) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *labelSizer = new wxBoxSizer(wxHORIZONTAL); labelSizer->Add(new wxStaticText(this, wxID_STATIC, _("Information set label")), 0, wxALL | wxALIGN_CENTER, 5); m_infosetName = new wxTextCtrl(this, -1, wxString(p_infoset->GetLabel().c_str(), *wxConvCurrent)); labelSizer->Add(m_infosetName, 1, wxALL | wxCENTER | wxEXPAND, 5); topSizer->Add(labelSizer, 0, wxALL | wxEXPAND, 0); topSizer->Add(new wxStaticText(this, wxID_STATIC, wxString::Format(_("Number of members: %d"), p_infoset->NumMembers())), 0, wxALL | wxALIGN_CENTER, 5); wxBoxSizer *playerSizer = new wxBoxSizer(wxHORIZONTAL); playerSizer->Add(new wxStaticText(this, wxID_STATIC, _("Belongs to player")), 0, wxALL | wxALIGN_CENTER, 5); m_player = new wxChoice(this, -1); if (p_infoset->IsChanceInfoset()) { m_player->Append(_("Chance")); m_player->SetSelection(0); } else { for (int pl = 1; pl <= p_infoset->GetGame()->NumPlayers(); pl++) { m_player->Append(wxString::Format(_T("%d: "), pl) + wxString(p_infoset->GetGame()->GetPlayer(pl)->GetLabel().c_str(), *wxConvCurrent)); } m_player->SetSelection(p_infoset->GetPlayer()->GetNumber() - 1); } playerSizer->Add(m_player, 1, wxALL | wxEXPAND, 5); topSizer->Add(playerSizer, 0, wxALL | wxEXPAND, 0); wxStaticBoxSizer *actionBoxSizer = new wxStaticBoxSizer(new wxStaticBox(this, -1, _("Actions")), wxHORIZONTAL); m_actionSheet = new gbtActionSheet(this, p_infoset); m_actionSheet->CreateGrid(p_infoset->NumActions(), (p_infoset->IsChanceInfoset()) ? 2 : 1); m_actionSheet->SetRowLabelWidth(40); m_actionSheet->SetColLabelHeight(25); m_actionSheet->SetColLabelValue(0, wxT("Label")); if (p_infoset->IsChanceInfoset()) { m_actionSheet->SetColLabelValue(1, wxT("Probability")); } for (int act = 1; act <= p_infoset->NumActions(); act++) { m_actionSheet->SetCellValue(wxSheetCoords(act-1, 0), wxString(p_infoset->GetAction(act)->GetLabel().c_str(), *wxConvCurrent)); if (p_infoset->IsChanceInfoset()) { m_actionSheet->SetCellValue(wxSheetCoords(act-1, 1), wxString(p_infoset->GetActionProb(act).c_str(), *wxConvCurrent)); } } m_actionSheet->SetDefaultColWidth(150); m_actionSheet->AutoSizeRows(); actionBoxSizer->Add(m_actionSheet, 1, wxALL | wxEXPAND, 5); topSizer->Add(actionBoxSizer, 0, wxALL | wxEXPAND, 5); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 5); wxButton *okButton = new wxButton(this, wxID_OK, _("OK")); okButton->SetDefault(); buttonSizer->Add(okButton, 0, wxALL, 5); topSizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); CenterOnParent(); } std::string gbtEditMoveDialog::GetActionName(int p_act) const { m_actionSheet->SaveEditControlValue(); return (const char *) m_actionSheet->GetCellValue(wxSheetCoords(p_act-1, 0)).mb_str(); } std::string gbtEditMoveDialog::GetActionProb(int p_act) const { m_actionSheet->SaveEditControlValue(); return (const char *) m_actionSheet->GetCellValue(wxSheetCoords(p_act-1, 1)).mb_str(); } gambit-0.2010.09.01/src/gui/dleditmove.h0000644000076500007650000000335211435216100014314 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dleditmove.h // Dialog for viewing and editing properties of a move // // 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 DLEDITMOVE_H #define DLEDITMOVE_H #include "wx/sheet/sheet.h" class gbtEditMoveDialog : public wxDialog { private: Gambit::GameInfoset m_infoset; wxChoice *m_player; wxTextCtrl *m_infosetName; wxSheet *m_actionSheet; public: // Lifecycle gbtEditMoveDialog(wxWindow *p_parent, Gambit::GameInfoset p_infoset); // Data access (only valid when ShowModal() returns with wxID_OK) wxString GetInfosetName(void) const { return m_infosetName->GetValue(); } int GetPlayer(void) const { return (m_player->GetSelection() + 1); } int NumActions(void) const { return m_actionSheet->GetNumberRows(); } // const Gambit::Array &GetActions(void) const // { return m_infoset->Actions(); } std::string GetActionName(int p_act) const; std::string GetActionProb(int p_act) const; }; #endif // DLEDITMOVE_H gambit-0.2010.09.01/src/gui/dleditnode.cc0000644000076500007650000001344311435216100014433 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dleditnode.cc // Dialog for viewing and editing properties of a node // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "libgambit/libgambit.h" #include "dleditnode.h" //====================================================================== // class dialogEditNode //====================================================================== dialogEditNode::dialogEditNode(wxWindow *p_parent, Gambit::GameNode p_node) : wxDialog(p_parent, -1, _("Node properties"), wxDefaultPosition), m_node(p_node) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *labelSizer = new wxBoxSizer(wxHORIZONTAL); labelSizer->Add(new wxStaticText(this, wxID_STATIC, _("Node label")), 0, wxALL | wxCENTER, 5); m_nodeName = new wxTextCtrl(this, -1, wxString(m_node->GetLabel().c_str(), *wxConvCurrent)); labelSizer->Add(m_nodeName, 1, wxALL | wxCENTER | wxEXPAND, 5); topSizer->Add(labelSizer, 0, wxALL | wxEXPAND, 5); wxBoxSizer *infosetSizer = new wxBoxSizer(wxHORIZONTAL); infosetSizer->Add(new wxStaticText(this, wxID_STATIC, _("Information set")), 0, wxALL | wxCENTER, 5); m_infoset = new wxChoice(this, -1); if (p_node->NumChildren() > 0) { m_infoset->Append(_("New information set")); if (p_node->GetInfoset()->IsChanceInfoset()) { int selection = 0; for (int iset = 1; iset <= p_node->GetGame()->GetChance()->NumInfosets(); iset++) { Gambit::GameInfoset infoset = p_node->GetGame()->GetChance()->GetInfoset(iset); if (infoset->NumActions() == p_node->NumChildren()) { m_infosetList.Append(infoset); m_infoset->Append(wxString::Format(_("Chance infoset %d"), infoset->GetNumber())); if (infoset == p_node->GetInfoset()) { selection = m_infosetList.Length(); } } } m_infoset->SetSelection(selection); } else { int selection = 0; for (int pl = 1; pl <= p_node->GetGame()->NumPlayers(); pl++) { Gambit::GamePlayer player = p_node->GetGame()->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { Gambit::GameInfoset infoset = player->GetInfoset(iset); if (infoset->NumActions() == p_node->NumChildren()) { m_infosetList.Append(infoset); m_infoset->Append(wxString::Format(_("Player %d, Infoset %d"), pl, iset)); if (infoset == p_node->GetInfoset()) { selection = m_infosetList.Length(); } } } } m_infoset->SetSelection(selection); } } else { m_infoset->Append(_("(none)")); m_infoset->SetSelection(0); m_infoset->Enable(false); } infosetSizer->Add(m_infoset, 1, wxALL | wxEXPAND, 5); topSizer->Add(infosetSizer, 0, wxALL | wxEXPAND, 5); wxBoxSizer *subgameSizer = new wxBoxSizer(wxVERTICAL); if (!p_node->GetParent()) { subgameSizer->Add(new wxStaticText(this, wxID_STATIC, _("This is the root node of the tree")), 0, wxALL | wxCENTER, 5); } else if (p_node->IsSubgameRoot()) { subgameSizer->Add(new wxStaticText(this, wxID_STATIC, _("This is the root of a proper subgame")), 0, wxALL | wxCENTER, 5); } topSizer->Add(subgameSizer, 0, wxALL | wxCENTER, 5); wxBoxSizer *outcomeSizer = new wxBoxSizer(wxHORIZONTAL); outcomeSizer->Add(new wxStaticText(this, wxID_STATIC, _("Outcome")), 0, wxALL | wxCENTER, 5); m_outcome = new wxChoice(this, -1); m_outcome->Append(_("(null)")); m_outcome->SetSelection(0); Gambit::Game efg = p_node->GetGame(); for (int outc = 1; outc <= efg->NumOutcomes(); outc++) { Gambit::GameOutcome outcome = efg->GetOutcome(outc); std::string item = Gambit::ToText(outc) + ": " + outcome->GetLabel(); if (item == "") { item = "Outcome" + Gambit::ToText(outc); } item += (" (" + Gambit::ToText(outcome->GetPayoff(1)) + ", " + Gambit::ToText(outcome->GetPayoff(2))); if (efg->NumPlayers() > 2) { item += ", " + Gambit::ToText(outcome->GetPayoff(3)); if (efg->NumPlayers() > 3) { item += ",...)"; } else { item += ")"; } } else { item += ")"; } m_outcome->Append(wxString(item.c_str(), *wxConvCurrent)); if (m_node->GetOutcome() == outcome) { m_outcome->SetSelection(outc); } } outcomeSizer->Add(m_outcome, 1, wxALL | wxEXPAND, 5); topSizer->Add(outcomeSizer, 0, wxALL | wxEXPAND, 5); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 5); wxButton *okButton = new wxButton(this, wxID_OK, _("OK")); okButton->SetDefault(); buttonSizer->Add(okButton, 0, wxALL, 5); topSizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); CenterOnParent(); } Gambit::GameInfoset dialogEditNode::GetInfoset(void) const { if (m_infoset->GetSelection() == 0) { return 0; } else { return m_infosetList[m_infoset->GetSelection()]; } } gambit-0.2010.09.01/src/gui/dleditnode.h0000644000076500007650000000276311435216100014300 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dleditnode.h // Dialog for viewing and editing properties of a node // // 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 DLEDITNODE_H #define DLEDITNODE_H class dialogEditNode : public wxDialog { private: Gambit::GameNode m_node; wxTextCtrl *m_nodeName; wxChoice *m_outcome, *m_infoset; Gambit::Array m_infosetList; public: // Lifecycle dialogEditNode(wxWindow *p_parent, Gambit::GameNode p_node); // Data access (only valid when ShowModal() returns with wxID_OK) wxString GetNodeName(void) const { return m_nodeName->GetValue(); } int GetOutcome(void) const { return m_outcome->GetSelection(); } Gambit::GameInfoset GetInfoset(void) const; }; #endif // DLEDITNODE_H gambit-0.2010.09.01/src/gui/dlefglayout.cc0000644000076500007650000003025711435216100014641 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlefglayout.cc // Declaration of dialog to set tree layout parameters // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include #include "dlefglayout.h" //========================================================================== // class gbtLayoutDialog: Implementation //========================================================================== class gbtLayoutNodesPanel : public wxPanel { private: wxChoice *m_chanceToken, *m_playerToken, *m_terminalToken; wxSpinCtrl *m_nodeSize, *m_terminalSpacing; public: gbtLayoutNodesPanel(wxWindow *p_parent, const gbtStyle &p_settings); int NodeSize(void) const { return m_nodeSize->GetValue(); } int TerminalSpacing(void) const { return m_terminalSpacing->GetValue(); } int ChanceToken(void) const { return m_chanceToken->GetSelection(); } int PlayerToken(void) const { return m_playerToken->GetSelection(); } int TerminalToken(void) const { return m_terminalToken->GetSelection(); } }; gbtLayoutNodesPanel::gbtLayoutNodesPanel(wxWindow *p_parent, const gbtStyle &p_settings) : wxPanel(p_parent, -1) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxStaticBoxSizer *nodeSizer = new wxStaticBoxSizer(wxVERTICAL, this, _T("Drawing nodes")); wxFlexGridSizer *tokenSizer = new wxFlexGridSizer(2); wxString tokenChoices[] = { _("a line"), _("a box"), _("an unfilled circle"), _("a diamond"), _("a filled circle") }; tokenSizer->Add(new wxStaticText(this, wxID_STATIC, _("Indicate chance nodes with")), 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); m_chanceToken = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 5, tokenChoices); m_chanceToken->SetSelection(p_settings.ChanceToken()); tokenSizer->Add(m_chanceToken, 1, wxALL | wxEXPAND | wxALIGN_CENTER, 5); tokenSizer->Add(new wxStaticText(this, wxID_STATIC, _("Indicate player nodes with")), 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); m_playerToken = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 5, tokenChoices); m_playerToken->SetSelection(p_settings.PlayerToken()); tokenSizer->Add(m_playerToken, 1, wxALL | wxEXPAND | wxALIGN_CENTER, 5); tokenSizer->Add(new wxStaticText(this, wxID_STATIC, _("Indicate terminal nodes with")), 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); m_terminalToken = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 5, tokenChoices); m_terminalToken->SetSelection(p_settings.TerminalToken()); tokenSizer->Add(m_terminalToken, 1, wxALL | wxEXPAND | wxALIGN_CENTER, 5); nodeSizer->Add(tokenSizer, 1, wxALL | wxEXPAND, 5); topSizer->Add(nodeSizer, 0, wxALL | wxALIGN_CENTER, 5); wxStaticBoxSizer *sizeSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Layout sizing")); wxFlexGridSizer *gridSizer = new wxFlexGridSizer(2); gridSizer->AddGrowableCol(1); gridSizer->Add(new wxStaticText(this, -1, _("Horizontal size of nodes")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); const int NODE_LENGTH_MIN = 5; const int NODE_LENGTH_MAX = 100; m_nodeSize = new wxSpinCtrl(this, -1, wxString::Format(_T("%d"), p_settings.NodeSize()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, NODE_LENGTH_MIN, NODE_LENGTH_MAX); gridSizer->Add(m_nodeSize, 1, wxEXPAND | wxALL, 5); gridSizer->Add(new wxStaticText(this, -1, _("Vertical spacing between terminal nodes")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); const int Y_SPACING_MIN = 15; const int Y_SPACING_MAX = 60; m_terminalSpacing = new wxSpinCtrl(this, -1, wxString::Format(_T("%d"), p_settings.TerminalSpacing()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, Y_SPACING_MIN, Y_SPACING_MAX); gridSizer->Add(m_terminalSpacing, 1, wxEXPAND | wxALL, 5); sizeSizer->Add(gridSizer, 1, wxALL | wxEXPAND, 5); topSizer->Add(sizeSizer, 0, wxALL | wxALIGN_CENTER, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); } class gbtLayoutBranchesPanel : public wxPanel { private: wxChoice *m_branchStyle, *m_branchLabels; wxSpinCtrl *m_branchLength, *m_tineLength; public: gbtLayoutBranchesPanel(wxWindow *p_parent, const gbtStyle &); int BranchLength(void) const { return m_branchLength->GetValue(); } int TineLength(void) const { return m_tineLength->GetValue(); } int BranchStyle(void) const { return m_branchStyle->GetSelection(); } int BranchLabels(void) const { return m_branchLabels->GetSelection(); } }; gbtLayoutBranchesPanel::gbtLayoutBranchesPanel(wxWindow *p_parent, const gbtStyle &p_settings) : wxPanel(p_parent, -1) { const int BRANCH_LENGTH_MIN = 0; const int BRANCH_LENGTH_MAX = 100; const int TINE_LENGTH_MIN = 20; const int TINE_LENGTH_MAX = 100; wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxStaticBoxSizer *styleBoxSizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Drawing branches")); wxFlexGridSizer *styleSizer = new wxFlexGridSizer(2); styleSizer->Add(new wxStaticText(this, wxID_STATIC, _("Draw branches")), 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); wxString styleChoices[] = { _("using straight lines between nodes"), _("with a tine for branch labels") }; m_branchStyle = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 2, styleChoices); m_branchStyle->SetSelection(p_settings.BranchStyle()); styleSizer->Add(m_branchStyle, 1, wxALL | wxEXPAND, 5); styleSizer->Add(new wxStaticText(this, wxID_STATIC, _("Draw labels")), 1, wxALL | wxALIGN_CENTER_VERTICAL, 5); wxString labelChoices[] = { _("horizontally"), _("rotated parallel to the branch") }; m_branchLabels = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 2, labelChoices); m_branchLabels->SetSelection(p_settings.BranchLabels()); styleSizer->Add(m_branchLabels, 1, wxALL | wxEXPAND, 5); styleBoxSizer->Add(styleSizer, 1, wxALL | wxEXPAND, 5); topSizer->Add(styleBoxSizer, 0, wxALL | wxALIGN_CENTER, 5); wxStaticBoxSizer *lengthSizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _T("Length of branches")); wxFlexGridSizer *gridSizer = new wxFlexGridSizer(2); gridSizer->AddGrowableCol(1); gridSizer->Add(new wxStaticText(this, -1, _("Length of branch fork")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); m_branchLength = new wxSpinCtrl(this, -1, wxString::Format(_T("%d"), p_settings.BranchLength()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, BRANCH_LENGTH_MIN, BRANCH_LENGTH_MAX); gridSizer->Add(m_branchLength, 1, wxALL | wxEXPAND, 5); gridSizer->Add(new wxStaticText(this, -1, _("Length of branch tine")), 1, wxALIGN_CENTER_VERTICAL | wxALL, 5); m_tineLength = new wxSpinCtrl(this, -1, wxString::Format(_T("%d"), p_settings.TineLength()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, TINE_LENGTH_MIN, TINE_LENGTH_MAX); gridSizer->Add(m_tineLength, 1, wxALL | wxEXPAND, 5); lengthSizer->Add(gridSizer, 1, wxALL | wxEXPAND, 5); topSizer->Add(lengthSizer, 0, wxALL | wxALIGN_CENTER, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); } class gbtLayoutInfosetsPanel : public wxPanel { private: wxChoice *m_infosetConnect, *m_infosetJoin; public: gbtLayoutInfosetsPanel(wxWindow *p_parent, const gbtStyle &); int InfosetConnect(void) const { return m_infosetConnect->GetSelection(); } int InfosetJoin(void) const { return m_infosetJoin->GetSelection(); } }; gbtLayoutInfosetsPanel::gbtLayoutInfosetsPanel(wxWindow *p_parent, const gbtStyle &p_settings) : wxPanel(p_parent, -1) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxStaticBoxSizer *infosetSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Drawing information sets")); wxFlexGridSizer *styleSizer = new wxFlexGridSizer(2); styleSizer->Add(new wxStaticText(this, wxID_STATIC, _("Connect members of information sets")), 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); wxString connectChoices[] = { _("invisibly (don't draw indicators)"), _("only when on the same level"), _("regardless of level") }; m_infosetConnect = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 3, connectChoices); m_infosetConnect->SetSelection(p_settings.InfosetConnect()); styleSizer->Add(m_infosetConnect, 0, wxALL, 5); styleSizer->Add(new wxStaticText(this, wxID_STATIC, _("Draw information set connections")), 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); wxString joinChoices[] = { _("using lines"), _("using bubbles") }; m_infosetJoin = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 2, joinChoices); m_infosetJoin->SetSelection(p_settings.InfosetJoin()); styleSizer->Add(m_infosetJoin, 0, wxALL | wxEXPAND, 5); infosetSizer->Add(styleSizer, 0, wxALL | wxALIGN_CENTER, 5); topSizer->Add(infosetSizer, 0, wxALL, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); } gbtLayoutDialog::gbtLayoutDialog(wxWindow *p_parent, const gbtStyle &p_settings) : wxDialog(p_parent, -1, _("Layout options"), wxDefaultPosition), m_toDefaults(false) { m_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize); m_notebook->AddPage(new gbtLayoutNodesPanel(m_notebook, p_settings), _("Nodes")); m_notebook->AddPage(new gbtLayoutBranchesPanel(m_notebook, p_settings), _("Branches")); m_notebook->AddPage(new gbtLayoutInfosetsPanel(m_notebook, p_settings), _("Information sets")); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); wxButton *defaultsButton = new wxButton(this, -1, _("Set to defaults")); Connect(defaultsButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtLayoutDialog::OnSetDefaults)); buttonSizer->Add(defaultsButton, 0, wxALL, 5); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 5); wxButton *okButton = new wxButton(this, wxID_OK, _("OK")); okButton->SetDefault(); buttonSizer->Add(okButton, 0, wxALL, 5); wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); topSizer->Add(m_notebook, 0, wxEXPAND | wxALL, 5); topSizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); CenterOnParent(); } void gbtLayoutDialog::GetSettings(gbtStyle &p_settings) { if (m_toDefaults) { p_settings.SetDefaults(); return; } gbtLayoutNodesPanel *nodes = (gbtLayoutNodesPanel *) m_notebook->GetPage(0); p_settings.SetNodeSize(nodes->NodeSize()); p_settings.SetTerminalSpacing(nodes->TerminalSpacing()); p_settings.SetChanceToken(nodes->ChanceToken()); p_settings.SetPlayerToken(nodes->PlayerToken()); p_settings.SetTerminalToken(nodes->TerminalToken()); gbtLayoutBranchesPanel *branches = (gbtLayoutBranchesPanel *) m_notebook->GetPage(1); p_settings.SetBranchLength(branches->BranchLength()); p_settings.SetTineLength(branches->TineLength()); p_settings.SetBranchStyle(branches->BranchStyle()); p_settings.SetBranchLabels(branches->BranchLabels()); gbtLayoutInfosetsPanel *infosets = (gbtLayoutInfosetsPanel *) m_notebook->GetPage(2); p_settings.SetInfosetConnect(infosets->InfosetConnect()); p_settings.SetInfosetJoin(infosets->InfosetJoin()); } void gbtLayoutDialog::OnSetDefaults(wxCommandEvent &) { m_toDefaults = true; EndModal(wxID_OK); } gambit-0.2010.09.01/src/gui/dlefglayout.h0000644000076500007650000000255011435216100014476 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlefglayout.h // Declaration of dialog to set tree layout parameters // // 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 DLEFGLAYOUT_H #define DLEFGLAYOUT_H #include #include "style.h" class gbtLayoutDialog : public wxDialog { private: bool m_toDefaults; wxNotebook *m_notebook; // Event handlers void OnSetDefaults(wxCommandEvent &); public: // Lifecycle gbtLayoutDialog(wxWindow *p_parent, const gbtStyle &); // Data access (only valid when ShowModal() returns with wxID_OK) void GetSettings(gbtStyle &); }; #endif // DLEFGLAYOUT_H gambit-0.2010.09.01/src/gui/dlefglegend.cc0000644000076500007650000001213011435216100014550 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlefglegend.cc // Declaration of dialog to set tree layout parameters // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "dlefglegend.h" //========================================================================== // class gbtLegendDialog: Implementation //========================================================================== gbtLegendDialog::gbtLegendDialog(wxWindow *p_parent, const gbtStyle &p_options) : wxDialog(p_parent, -1, _("Labels"), wxDefaultPosition) { wxStaticBoxSizer *nodeGroup = new wxStaticBoxSizer(new wxStaticBox(this, -1, _("Node labeling")), wxVERTICAL); wxString nodeLabelList[] = { _("no label"), _("the node's label"), _("the player's name"), _("the information set's label"), _("the information set's number"), _("the realization probability"), _("the belief probability"), _("the payoff of reaching the node") }; wxBoxSizer *nodeAboveSizer = new wxBoxSizer(wxHORIZONTAL); nodeAboveSizer->Add(new wxStaticText(this, wxID_STATIC, _("Display")), 0, wxALL | wxALIGN_CENTER, 5); m_nodeAbove = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 8, nodeLabelList); m_nodeAbove->SetSelection(p_options.NodeAboveLabel()); nodeAboveSizer->Add(m_nodeAbove, 1, wxALL | wxALIGN_CENTER, 5); nodeAboveSizer->Add(new wxStaticText(this, wxID_STATIC, _("above each node")), 0, wxALL | wxALIGN_CENTER, 5); nodeGroup->Add(nodeAboveSizer, 0, wxALL | wxEXPAND, 5); wxBoxSizer *nodeBelowSizer = new wxBoxSizer(wxHORIZONTAL); nodeBelowSizer->Add(new wxStaticText(this, wxID_STATIC, _("Display")), 0, wxALL | wxALIGN_CENTER, 5); m_nodeBelow = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 8, nodeLabelList); m_nodeBelow->SetSelection(p_options.NodeBelowLabel()); nodeBelowSizer->Add(m_nodeBelow, 1, wxALL | wxALIGN_CENTER, 5); nodeBelowSizer->Add(new wxStaticText(this, wxID_STATIC, _("below each node")), 0, wxALL | wxALIGN_CENTER, 5); nodeGroup->Add(nodeBelowSizer, 0, wxALL | wxEXPAND, 5); wxStaticBoxSizer *actionGroup = new wxStaticBoxSizer(new wxStaticBox(this, -1, _("Action labeling")), wxVERTICAL); wxString actionLabelList[] = { _("no label"), _("the name of the action"), _("the probability the action is played"), _("the value of the action") }; wxBoxSizer *actionAboveSizer = new wxBoxSizer(wxHORIZONTAL); actionAboveSizer->Add(new wxStaticText(this, wxID_STATIC, _("Display")), 0, wxALL | wxALIGN_CENTER, 5); m_actionAbove = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 4, actionLabelList); m_actionAbove->SetSelection(p_options.BranchAboveLabel()); actionAboveSizer->Add(m_actionAbove, 1, wxALL | wxALIGN_CENTER, 5); actionAboveSizer->Add(new wxStaticText(this, wxID_STATIC, _("above each action")), 0, wxALL | wxALIGN_CENTER, 5); actionGroup->Add(actionAboveSizer, 0, wxALL | wxEXPAND, 5); wxBoxSizer *actionBelowSizer = new wxBoxSizer(wxHORIZONTAL); actionBelowSizer->Add(new wxStaticText(this, wxID_STATIC, _("Display")), 0, wxALL | wxALIGN_CENTER, 5); m_actionBelow = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 4, actionLabelList); m_actionBelow->SetSelection(p_options.BranchBelowLabel()); actionBelowSizer->Add(m_actionBelow, 1, wxALL | wxALIGN_CENTER, 5); actionBelowSizer->Add(new wxStaticText(this, wxID_STATIC, _("below each action")), 0, wxALL | wxALIGN_CENTER, 5); actionGroup->Add(actionBelowSizer, 0, wxALL | wxEXPAND, 5); wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); topSizer->Add(nodeGroup, 0, wxEXPAND | wxALL, 5); topSizer->Add(actionGroup, 0, wxEXPAND | wxALL, 5); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 5); wxButton *okButton = new wxButton(this, wxID_OK, _("OK")); okButton->SetDefault(); buttonSizer->Add(okButton, 0, wxALL, 5); topSizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); CenterOnParent(); } gambit-0.2010.09.01/src/gui/dlefglegend.h0000644000076500007650000000304711435216100014421 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlefglegend.h // Dialog for setting legends for extensive form display // // 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 DLEFGLEGEND_H #define DLEFGLEGEND_H #include "style.h" class gbtLegendDialog : public wxDialog { private: wxChoice *m_nodeAbove, *m_nodeBelow, *m_actionAbove, *m_actionBelow; public: // Lifecycle gbtLegendDialog(wxWindow *, const gbtStyle &); // Data access (only valid when ShowModal() returns with wxID_OK) int GetNodeAbove(void) const { return m_nodeAbove->GetSelection(); } int GetNodeBelow(void) const { return m_nodeBelow->GetSelection(); } int GetBranchAbove(void) const { return m_actionAbove->GetSelection(); } int GetBranchBelow(void) const { return m_actionBelow->GetSelection(); } }; #endif // DLEFGLEGEND_H gambit-0.2010.09.01/src/gui/dlefglogit.cc0000644000076500007650000002716311435216100014444 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlefglogit.cc // Dialog for monitoring progress of logit equilibrium computation // // 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 #include #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include #include #include "wx/sheet/sheet.h" #include "dlefglogit.h" class gbtLogitBehavList : public wxSheet { private: gbtGameDocument *m_doc; Gambit::List m_lambdas; Gambit::List > m_profiles; // Overriding wxSheet members for data access wxString GetCellValue(const wxSheetCoords &); wxSheetCellAttr GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const; // Overriding wxSheet members to disable selection behavior bool SelectRow(int, bool = false, bool = false) { return false; } bool SelectRows(int, int, bool = false, bool = false) { return false; } bool SelectCol(int, bool = false, bool = false) { return false; } bool SelectCols(int, int, bool = false, bool = false) { return false; } bool SelectCell(const wxSheetCoords&, bool = false, bool = false) { return false; } bool SelectBlock(const wxSheetBlock&, bool = false, bool = false) { return false; } bool SelectAll(bool = false) { return false; } // Overriding wxSheet member to suppress drawing of cursor void DrawCursorCellHighlight(wxDC&, const wxSheetCellAttr &) { } public: gbtLogitBehavList(wxWindow *p_parent, gbtGameDocument *p_doc); virtual ~gbtLogitBehavList(); void AddProfile(const wxString &p_text, bool p_forceShow); }; gbtLogitBehavList::gbtLogitBehavList(wxWindow *p_parent, gbtGameDocument *p_doc) : wxSheet(p_parent, -1), m_doc(p_doc) { CreateGrid(0, 0); SetRowLabelWidth(40); SetColLabelHeight(25); } gbtLogitBehavList::~gbtLogitBehavList() { } wxString gbtLogitBehavList::GetCellValue(const wxSheetCoords &p_coords) { if (IsRowLabelCell(p_coords)) { return wxString::Format(wxT("%d"), p_coords.GetRow() + 1); } else if (IsColLabelCell(p_coords)) { if (p_coords.GetCol() == 0) { return wxT("Lambda"); } else { Gambit::GameAction action = m_doc->GetGame()->GetAction(p_coords.GetCol()); return (wxString::Format(wxT("%d: "), action->GetInfoset()->GetNumber())+ wxString(action->GetLabel().c_str(), *wxConvCurrent)); } } else if (IsCornerLabelCell(p_coords)) { return wxT("#"); } if (p_coords.GetCol() == 0) { return wxString(Gambit::ToText(m_lambdas[p_coords.GetRow()+1], m_doc->GetStyle().NumDecimals()).c_str(), *wxConvCurrent); } else { const Gambit::MixedBehavProfile &profile = m_profiles[p_coords.GetRow()+1]; return wxString(Gambit::ToText(profile[p_coords.GetCol()], m_doc->GetStyle().NumDecimals()).c_str(), *wxConvCurrent); } } static wxColour GetPlayerColor(gbtGameDocument *p_doc, int p_index) { if (p_index == 0) return *wxBLACK; Gambit::GameAction action = p_doc->GetGame()->GetAction(p_index); return p_doc->GetStyle().GetPlayerColor(action->GetInfoset()->GetPlayer()->GetNumber()); } wxSheetCellAttr gbtLogitBehavList::GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const { if (IsRowLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultRowLabelAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); return attr; } else if (IsColLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultColLabelAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); attr.SetForegroundColour(GetPlayerColor(m_doc, p_coords.GetCol())); return attr; } else if (IsCornerLabelCell(p_coords)) { return GetSheetRefData()->m_defaultCornerLabelAttr; } wxSheetCellAttr attr(GetSheetRefData()->m_defaultGridCellAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); attr.SetAlignment(wxALIGN_RIGHT, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); if (p_coords.GetCol() > 0) { Gambit::GameAction action = m_doc->GetGame()->GetAction(p_coords.GetCol()); attr.SetForegroundColour(m_doc->GetStyle().GetPlayerColor(action->GetInfoset()->GetPlayer()->GetNumber())); if (action->GetInfoset()->GetNumber() % 2 == 0) { attr.SetBackgroundColour(wxColour(250, 250, 250)); } else { attr.SetBackgroundColour(wxColour(225, 225, 225)); } } else { attr.SetForegroundColour(*wxBLACK); attr.SetBackgroundColour(wxColour(250, 250, 250)); } attr.SetReadOnly(true); return attr; } void gbtLogitBehavList::AddProfile(const wxString &p_text, bool p_forceShow) { if (GetNumberCols() == 0) { AppendCols(m_doc->GetGame()->BehavProfileLength() + 1); } Gambit::MixedBehavProfile profile(m_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); m_lambdas.Append((double) Gambit::ToNumber(std::string((const char *) tok.GetNextToken().mb_str()))); for (int i = 1; i <= profile.Length(); i++) { profile[i] = Gambit::ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } m_profiles.Append(profile); if (p_forceShow || m_profiles.Length() - GetNumberRows() > 20) { AppendRows(m_profiles.Length() - GetNumberRows()); MakeCellVisible(wxSheetCoords(GetNumberRows() - 1, 0)); } // Lambda tends to get large, so this column usually needs resized AutoSizeCol(0); } const int GBT_ID_TIMER = 1000; const int GBT_ID_PROCESS = 1001; BEGIN_EVENT_TABLE(gbtLogitBehavDialog, wxDialog) EVT_END_PROCESS(GBT_ID_PROCESS, gbtLogitBehavDialog::OnEndProcess) EVT_IDLE(gbtLogitBehavDialog::OnIdle) EVT_TIMER(GBT_ID_TIMER, gbtLogitBehavDialog::OnTimer) EVT_BUTTON(wxID_SAVE, gbtLogitBehavDialog::OnSave) END_EVENT_TABLE() #include "bitmaps/stop.xpm" gbtLogitBehavDialog::gbtLogitBehavDialog(wxWindow *p_parent, gbtGameDocument *p_doc) : wxDialog(p_parent, -1, wxT("Compute quantal response equilibria"), wxDefaultPosition), m_doc(p_doc), m_process(0), m_timer(this, GBT_ID_TIMER) { wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *startSizer = new wxBoxSizer(wxHORIZONTAL); m_statusText = new wxStaticText(this, wxID_STATIC, wxT("The computation is currently in progress.")); m_statusText->SetForegroundColour(*wxBLUE); startSizer->Add(m_statusText, 0, wxALL | wxALIGN_CENTER, 5); m_stopButton = new wxBitmapButton(this, wxID_CANCEL, wxBitmap(stop_xpm)); m_stopButton->SetToolTip(_("Stop the computation")); startSizer->Add(m_stopButton, 0, wxALL | wxALIGN_CENTER, 5); Connect(wxID_CANCEL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtLogitBehavDialog::OnStop)); sizer->Add(startSizer, 0, wxALL | wxALIGN_CENTER, 5); m_behavList = new gbtLogitBehavList(this, m_doc); m_behavList->SetSizeHints(wxSize(600, 400)); sizer->Add(m_behavList, 0, wxALL | wxALIGN_CENTER, 5); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); m_saveButton = new wxButton(this, wxID_SAVE, wxT("Save correspondence to .csv file")); m_saveButton->Enable(false); buttonSizer->Add(m_saveButton, 0, wxALL | wxALIGN_CENTER, 5); m_okButton = new wxButton(this, wxID_OK, wxT("OK")); buttonSizer->Add(m_okButton, 0, wxALL | wxALIGN_CENTER, 5); m_okButton->Enable(false); sizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(sizer); sizer->Fit(this); sizer->SetSizeHints(this); Layout(); CenterOnParent(); Start(); } void gbtLogitBehavDialog::Start(void) { m_process = new wxProcess(this, GBT_ID_PROCESS); m_process->Redirect(); #ifdef __WXMAC__ m_pid = wxExecute(wxT("/usr/local/bin/gambit-logit"), wxEXEC_ASYNC, m_process); #else m_pid = wxExecute(wxT("gambit-logit"), wxEXEC_ASYNC, m_process); #endif // __WXMAC__ std::ostringstream s; m_doc->GetGame()->WriteEfgFile(s); wxString str(wxString(s.str().c_str(), *wxConvCurrent)); // It is possible that the whole string won't write on one go, so // we should take this possibility into account. If the write doesn't // complete the whole way, we take a 100-millisecond siesta and try // again. (This seems to primarily be an issue with -- you guessed it -- // Windows!) while (str.length() > 0) { wxTextOutputStream os(*m_process->GetOutputStream()); // It appears that (at least with mingw) the string itself contains // only '\n' for newlines. If we don't SetMode here, these get // converted to '\r\n' sequences, and so the number of characters // LastWrite() returns does not match the number of characters in // our string. Setting this explicitly solves this problem. os.SetMode(wxEOL_UNIX); os.WriteString(str); str.Remove(0, m_process->GetOutputStream()->LastWrite()); wxMilliSleep(100); } m_process->CloseOutput(); m_timer.Start(1000, false); } void gbtLogitBehavDialog::OnIdle(wxIdleEvent &p_event) { if (!m_process) return; if (m_process->IsInputAvailable()) { wxTextInputStream tis(*m_process->GetInputStream()); wxString msg; msg << tis.ReadLine(); m_behavList->AddProfile(msg, false); m_output += msg; m_output += wxT("\n"); p_event.RequestMore(); } else { m_timer.Start(1000, false); } } void gbtLogitBehavDialog::OnTimer(wxTimerEvent &p_event) { wxWakeUpIdle(); } void gbtLogitBehavDialog::OnEndProcess(wxProcessEvent &p_event) { m_stopButton->Enable(false); m_timer.Stop(); while (m_process->IsInputAvailable()) { wxTextInputStream tis(*m_process->GetInputStream()); wxString msg; msg << tis.ReadLine(); if (msg != wxT("")) { m_behavList->AddProfile(msg, true); m_output += msg; m_output += wxT("\n"); } } if (p_event.GetExitCode() == 0) { m_statusText->SetLabel(wxT("The computation has completed.")); m_statusText->SetForegroundColour(wxColour(0, 192, 0)); } else { m_statusText->SetLabel(wxT("The computation ended abnormally.")); m_statusText->SetForegroundColour(*wxRED); } m_okButton->Enable(true); m_saveButton->Enable(true); } void gbtLogitBehavDialog::OnStop(wxCommandEvent &) { // Per the wxWidgets wiki, under Windows, programs that run // without a console window don't respond to the more polite // SIGTERM, so instead we must be rude and SIGKILL it. m_stopButton->Enable(false); #ifdef __WXMSW__ wxProcess::Kill(m_pid, wxSIGKILL); #else wxProcess::Kill(m_pid, wxSIGTERM); #endif // __WXMSW__ } void gbtLogitBehavDialog::OnSave(wxCommandEvent &) { wxFileDialog dialog(this, _("Choose file"), wxT(""), wxT(""), wxT("CSV files (*.csv)|*.csv|" "All files (*.*)|*.*"), wxSAVE | wxOVERWRITE_PROMPT); if (dialog.ShowModal() == wxID_OK) { std::ofstream file((const char *) dialog.GetPath().mb_str()); file << ((const char *) m_output.mb_str()); } } gambit-0.2010.09.01/src/gui/dlefglogit.h0000644000076500007650000000314011435216100014273 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlefglogit.h // Dialog for monitoring logit equilibrium computation // // 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 DLEFGLOGIT_H #define DLEFGLOGIT_H #include #include "gamedoc.h" class gbtLogitBehavList; class gbtLogitBehavDialog : public wxDialog { private: gbtGameDocument *m_doc; int m_pid; wxProcess *m_process; gbtLogitBehavList *m_behavList; wxStaticText *m_statusText; wxButton *m_stopButton, *m_okButton, *m_saveButton; wxTimer m_timer; wxString m_output; void OnStop(wxCommandEvent &); void OnTimer(wxTimerEvent &); void OnIdle(wxIdleEvent &); void OnEndProcess(wxProcessEvent &); void OnSave(wxCommandEvent &); void Start(void); public: gbtLogitBehavDialog(wxWindow *p_parent, gbtGameDocument *p_doc); DECLARE_EVENT_TABLE() }; #endif // DLLOGIT_H gambit-0.2010.09.01/src/gui/dlefgreveal.cc0000644000076500007650000000605411435216100014600 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlefgreveal.cc // Dialog for revealing actions to players // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "libgambit/libgambit.h" #include "dlefgreveal.h" //========================================================================= // gbtRevealMoveDialog: Member functions //========================================================================= gbtRevealMoveDialog::gbtRevealMoveDialog(wxWindow *p_parent, gbtGameDocument *p_doc) : wxDialog(p_parent, -1, _("Reveal this move to players"), wxDefaultPosition), m_doc(p_doc) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxStaticBoxSizer *playerBox = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Reveal the move to players")); wxBoxSizer *boxSizer = new wxBoxSizer(wxVERTICAL); for (int pl = 1; pl <= m_doc->NumPlayers(); pl++) { Gambit::GamePlayer player = m_doc->GetGame()->GetPlayer(pl); if (player->GetLabel() != "") { m_players.Append(new wxCheckBox(this, -1, wxString(player->GetLabel().c_str(), *wxConvCurrent))); } else { m_players.Append(new wxCheckBox(this, -1, wxString::Format(_T("Player %d"), pl))); } m_players[pl]->SetValue(1); m_players[pl]->SetForegroundColour(m_doc->GetStyle().GetPlayerColor(pl)); boxSizer->Add(m_players[pl], 1, wxALL | wxEXPAND, 0); } playerBox->Add(boxSizer, 1, wxALL | wxEXPAND, 5); topSizer->Add(playerBox, 1, wxALL | wxEXPAND, 5); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 5); wxButton *okButton = new wxButton(this, wxID_OK, _("OK")); okButton->SetDefault(); buttonSizer->Add(okButton, 0, wxALL, 5); topSizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); CenterOnParent(); } Gambit::Array gbtRevealMoveDialog::GetPlayers(void) const { Gambit::Array players; for (int pl = 1; pl <= m_doc->NumPlayers(); pl++) { if (m_players[pl]->GetValue()) { players.Append(m_doc->GetGame()->GetPlayer(pl)); } } return players; } gambit-0.2010.09.01/src/gui/dlefgreveal.h0000644000076500007650000000247011435216100014440 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlefgreveal.h // Dialog for revealing actions to players // // 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 DLEFGREVEAL_H #define DLEFGREVEAL_H #include "gamedoc.h" class gbtRevealMoveDialog : public wxDialog { private: gbtGameDocument *m_doc; Gambit::Array m_players; public: // Lifecycle gbtRevealMoveDialog(wxWindow *, gbtGameDocument *); // Data access (only valid when ShowModal() returns with wxID_OK) Gambit::Array GetPlayers(void) const; }; #endif // DLEFGREVEAL_H gambit-0.2010.09.01/src/gui/dlgameprop.cc0000644000076500007650000000756211435216100014457 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlgameprop.cc // Dialog for viewing and editing properties of a game // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "gamedoc.h" #include "dlgameprop.h" //======================================================================== // class gbtGamePropertiesDialog //======================================================================== gbtGamePropertiesDialog::gbtGamePropertiesDialog(wxWindow *p_parent, gbtGameDocument *p_doc) : wxDialog(p_parent, -1, _("Game properties"), wxDefaultPosition), m_doc(p_doc) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *titleSizer = new wxBoxSizer(wxHORIZONTAL); titleSizer->Add(new wxStaticText(this, wxID_STATIC, _("Title")), 0, wxALL | wxALIGN_CENTER, 5); m_title = new wxTextCtrl(this, -1, wxString(m_doc->GetGame()->GetTitle().c_str(), *wxConvCurrent), wxDefaultPosition, wxSize(400, -1)); titleSizer->Add(m_title, 1, wxALL | wxALIGN_CENTER, 5); topSizer->Add(titleSizer, 0, wxALL | wxEXPAND, 0); wxBoxSizer *commentSizer = new wxBoxSizer(wxHORIZONTAL); commentSizer->Add(new wxStaticText(this, wxID_STATIC, _("Comment")), 0, wxALL | wxALIGN_CENTER, 5); m_comment = new wxTextCtrl(this, -1, wxString(m_doc->GetGame()->GetComment().c_str(), *wxConvCurrent), wxDefaultPosition, wxSize(400, -1), wxTE_MULTILINE); commentSizer->Add(m_comment, 1, wxALL | wxALIGN_CENTER, 5); topSizer->Add(commentSizer, 1, wxALL | wxEXPAND, 0); wxStaticBoxSizer *boxSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Information about this game")); boxSizer->Add(new wxStaticText(this, wxID_STATIC, wxString(_("Filename: ")) + m_doc->GetFilename()), 0, wxALL, 5); Gambit::Game game = m_doc->GetGame(); boxSizer->Add(new wxStaticText(this, wxID_STATIC, wxString::Format(_("Number of players: %d"), game->NumPlayers())), 0, wxALL, 5); if (game->IsConstSum()) { boxSizer->Add(new wxStaticText(this, wxID_STATIC, _("This is a constant-sum game")), 0, wxALL, 5); } else { boxSizer->Add(new wxStaticText(this, wxID_STATIC, _("This is not a constant-sum game")), 0, wxALL, 5); } if (m_doc->IsTree()) { if (game->IsPerfectRecall()) { boxSizer->Add(new wxStaticText(this, wxID_STATIC, _("This is a game of perfect recall")), 0, wxALL, 5); } else { boxSizer->Add(new wxStaticText(this, wxID_STATIC, _("This is not a game of perfect recall")), 0, wxALL, 5); } } topSizer->Add(boxSizer, 0, wxALL | wxEXPAND, 5); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 5); wxButton *okButton = new wxButton(this, wxID_OK, _("OK")); okButton->SetDefault(); buttonSizer->Add(okButton, 0, wxALL, 5); topSizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); CenterOnParent(); } gambit-0.2010.09.01/src/gui/dlgameprop.h0000644000076500007650000000260311435216101014311 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlgameprop.h // Dialog for viewing and editing properties of a game // // 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 DLGAMEPROP_H #define DLGAMEPROP_H class gbtGamePropertiesDialog : public wxDialog { private: gbtGameDocument *m_doc; wxTextCtrl *m_title, *m_comment; public: // Lifecycle gbtGamePropertiesDialog(wxWindow *p_parent, gbtGameDocument *p_doc); // Data access (only valid when ShowModal() returns with wxID_OK) wxString GetTitle(void) const { return m_title->GetValue(); } wxString GetComment(void) const { return m_comment->GetValue(); } }; #endif // DLGAMEPROP_H gambit-0.2010.09.01/src/gui/dlinsertmove.cc0000644000076500007650000001572311435216101015037 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlinsertmove.cc // Implementation of dialog to insert a move into a tree // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "libgambit/libgambit.h" #include "dlinsertmove.h" //========================================================================= // gbtInsertMoveDialog: Member functions //========================================================================= gbtInsertMoveDialog::gbtInsertMoveDialog(wxWindow *p_parent, gbtGameDocument *p_doc) : wxDialog(p_parent, -1, _("Insert Move"), wxDefaultPosition), m_doc(p_doc) { m_playerItem = new wxChoice(this, -1); m_playerItem->Append(_("Insert move for the chance player")); for (int pl = 1; pl <= m_doc->NumPlayers(); pl++) { wxString s = _("Insert move for "); Gambit::GamePlayer player = m_doc->GetGame()->GetPlayer(pl); if (player->GetLabel() != "") { s += wxString(player->GetLabel().c_str(), *wxConvCurrent); } else { s += wxString::Format(_("player %d"), pl); } m_playerItem->Append(s); } m_playerItem->Append(_("Insert move for a new player")); m_playerItem->SetSelection(1); Connect(m_playerItem->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(gbtInsertMoveDialog::OnPlayer)); m_infosetItem = new wxChoice(this, -1); m_infosetItem->Append(_("at a new information set")); Gambit::GamePlayer player = m_doc->GetGame()->GetPlayer(1); for (int iset = 1; iset <= player->NumInfosets(); iset++) { wxString s = _("at information set "); Gambit::GameInfoset infoset = player->GetInfoset(iset); if (infoset->GetLabel() != "") { s += wxString(infoset->GetLabel().c_str(), *wxConvCurrent); } else { s += wxString::Format(wxT("%d"), iset); } s += wxString::Format(wxT(" (%d action"), infoset->NumActions()); if (infoset->NumActions() > 1) { s += wxT("s"); } s += wxString::Format(wxT(", %d member node"), infoset->NumMembers()); if (infoset->NumMembers() > 1) { s += wxT("s)"); } else { s += wxT(")"); } m_infosetItem->Append(s); } m_infosetItem->SetSelection(0); Connect(m_infosetItem->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(gbtInsertMoveDialog::OnInfoset)); wxBoxSizer *actionSizer = new wxBoxSizer(wxHORIZONTAL); actionSizer->Add(new wxStaticText(this, wxID_STATIC, _("with")), 0, wxALL | wxALIGN_CENTER, 5); m_actions = new wxSpinCtrl(this, -1, _T("2"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 10000, 2); m_actions->Enable(m_infosetItem->GetSelection() == 0); actionSizer->Add(m_actions, 0, wxALL, 5); actionSizer->Add(new wxStaticText(this, wxID_STATIC, _("actions")), 0, wxALL | wxALIGN_CENTER, 5); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 5); wxButton *okButton = new wxButton(this, wxID_OK, _("OK")); okButton->SetDefault(); buttonSizer->Add(okButton, 0, wxALL, 5); wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); topSizer->Add(m_playerItem, 0, wxALL | wxEXPAND | wxALIGN_CENTER, 5); topSizer->Add(m_infosetItem, 0, wxALL | wxEXPAND | wxALIGN_CENTER, 5); topSizer->Add(actionSizer, 0, wxALL | wxALIGN_CENTER, 5); topSizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); CenterOnParent(); } void gbtInsertMoveDialog::OnPlayer(wxCommandEvent &) { int playerNumber = m_playerItem->GetSelection(); Gambit::GamePlayer player; if (playerNumber == 0) player = m_doc->GetGame()->GetChance(); else if (playerNumber <= m_doc->NumPlayers()) player = m_doc->GetGame()->GetPlayer(playerNumber); m_infosetItem->Clear(); m_infosetItem->Append(_("at a new information set")); if (!player) { m_infosetItem->SetSelection(0); m_actions->Enable(true); return; } for (int iset = 1; iset <= player->NumInfosets(); iset++) { wxString s = _("at information set "); Gambit::GameInfoset infoset = player->GetInfoset(iset); if (infoset->GetLabel() != "") { s += wxString(infoset->GetLabel().c_str(), *wxConvCurrent); } else { s += wxString::Format(wxT("%d"), iset); } s += wxString::Format(wxT(" (%d action"), infoset->NumActions()); if (infoset->NumActions() > 1) { s += wxT("s"); } s += wxString::Format(wxT(", %d member node"), infoset->NumMembers()); if (infoset->NumMembers() > 1) { s += wxT("s)"); } else { s += wxT(")"); } m_infosetItem->Append(s); } m_infosetItem->SetSelection(0); m_actions->Enable(true); } void gbtInsertMoveDialog::OnInfoset(wxCommandEvent &) { int infosetNumber = m_infosetItem->GetSelection(); if (infosetNumber > 0) { int playerNumber = m_playerItem->GetSelection(); Gambit::GameInfoset infoset; if (playerNumber == 0) infoset = m_doc->GetGame()->GetChance()->GetInfoset(infosetNumber); else infoset = m_doc->GetGame()->GetPlayer(playerNumber)->GetInfoset(infosetNumber); m_actions->Enable(false); m_actions->SetValue(infoset->NumActions()); } else { m_actions->Enable(true); } } Gambit::GamePlayer gbtInsertMoveDialog::GetPlayer(void) const { int playerNumber = m_playerItem->GetSelection(); if (playerNumber == 0) { return m_doc->GetGame()->GetChance(); } else if (playerNumber <= m_doc->NumPlayers()) { return m_doc->GetGame()->GetPlayer(playerNumber); } else { Gambit::GamePlayer player = m_doc->GetGame()->NewPlayer(); player->SetLabel("Player " + Gambit::ToText(m_doc->NumPlayers())); return player; } } Gambit::GameInfoset gbtInsertMoveDialog::GetInfoset(void) const { if (m_playerItem->GetSelection() <= m_doc->NumPlayers()) { Gambit::GamePlayer player = GetPlayer(); int infosetNumber = m_infosetItem->GetSelection(); if (player && infosetNumber > 0) { return player->GetInfoset(infosetNumber); } else { return 0; } } else { return 0; } } int gbtInsertMoveDialog::GetActions(void) const { return ((GetInfoset()) ? GetInfoset()->NumActions() : m_actions->GetValue()); } gambit-0.2010.09.01/src/gui/dlinsertmove.h0000644000076500007650000000307211435216101014673 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlinsertmove.h // Declaration of dialog to insert move into a tree // // 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 DLINSERTMOVE_H #define DLINSERTMOVE_H #include #include "gamedoc.h" class gbtInsertMoveDialog : public wxDialog { private: gbtGameDocument *m_doc; wxChoice *m_playerItem, *m_infosetItem; wxSpinCtrl *m_actions; void OnPlayer(wxCommandEvent &); void OnInfoset(wxCommandEvent &); public: // Constructor gbtInsertMoveDialog(wxWindow *, gbtGameDocument *); // Data access (only valid if ShowModal() returns wxID_OK. // If GetInfoset() returns null, user selected "new infoset" Gambit::GamePlayer GetPlayer(void) const; Gambit::GameInfoset GetInfoset(void) const; int GetActions(void) const; }; #endif // DLINSERTMOVE_H gambit-0.2010.09.01/src/gui/dlnash.cc0000644000076500007650000002217311441446350013602 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlnash.cc // Dialog for selecting algorithms to compute Nash equilibria // // 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 #include #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "dlnash.h" static wxString s_recommended(wxT("with Gambit's recommended method")); static wxString s_enumpure(wxT("by looking for pure strategy equilibria")); static wxString s_enummixed(wxT("by enumerating extreme points")); static wxString s_enumpoly(wxT("by solving systems of polynomial equations")); static wxString s_lp(wxT("by solving a linear program")); static wxString s_lcp(wxT("by solving a linear complementarity program")); static wxString s_liap(wxT("by minimizing the Lyapunov function")); static wxString s_logit(wxT("by tracing logit equilibria")); static wxString s_simpdiv(wxT("by simplicial subdivision")); gbtNashChoiceDialog::gbtNashChoiceDialog(wxWindow *p_parent, gbtGameDocument *p_doc) : wxDialog(p_parent, -1, wxT("Compute Nash equilibria"), wxDefaultPosition), m_doc(p_doc) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxString countChoices[] = { wxT("Compute one Nash equilibrium"), wxT("Compute as many Nash equilibria as possible"), wxT("Compute all Nash equilibria") }; m_countChoice = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 3, countChoices); m_countChoice->SetSelection(2); Connect(m_countChoice->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(gbtNashChoiceDialog::OnCount)); topSizer->Add(m_countChoice, 0, wxALL | wxEXPAND, 5); if (p_doc->NumPlayers() == 2) { wxString methodChoices[] = { s_recommended, s_enummixed, s_enumpoly }; m_methodChoice = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 3, methodChoices); } else { wxString methodChoices[] = { s_recommended, s_enumpoly }; m_methodChoice = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 2, methodChoices); } m_methodChoice->SetSelection(0); topSizer->Add(m_methodChoice, 0, wxALL | wxEXPAND, 5); if (m_doc->IsTree()) { wxString repChoices[] = { wxT("using the extensive game"), wxT("using the strategic game") }; m_repChoice = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 2, repChoices); m_repChoice->SetSelection(0); topSizer->Add(m_repChoice, 0, wxALL | wxEXPAND, 5); // We only need to respond to changes in method when we have an // extensive game Connect(m_methodChoice->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(gbtNashChoiceDialog::OnMethod)); } else { m_repChoice = 0; } wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 5); wxButton *okButton = new wxButton(this, wxID_OK, _("OK")); okButton->SetDefault(); buttonSizer->Add(okButton, 0, wxALL, 5); topSizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(topSizer); topSizer->Fit(this); topSizer->SetSizeHints(this); Layout(); CenterOnParent(); } void gbtNashChoiceDialog::OnCount(wxCommandEvent &p_event) { m_methodChoice->Clear(); m_methodChoice->Append(s_recommended); if (p_event.GetSelection() == 0) { if (m_doc->IsConstSum()) { m_methodChoice->Append(s_lp); } m_methodChoice->Append(s_simpdiv); m_methodChoice->Append(s_logit); } else if (p_event.GetSelection() == 1) { if (m_doc->NumPlayers() == 2) { m_methodChoice->Append(s_lcp); } m_methodChoice->Append(s_enumpure); m_methodChoice->Append(s_liap); } else { if (m_doc->NumPlayers() == 2) { m_methodChoice->Append(s_enummixed); } m_methodChoice->Append(s_enumpoly); } m_methodChoice->SetSelection(0); } void gbtNashChoiceDialog::OnMethod(wxCommandEvent &p_event) { wxString method = m_methodChoice->GetString(p_event.GetSelection()); if (method == s_simpdiv || method == s_enummixed) { m_repChoice->SetSelection(1); m_repChoice->Enable(false); } else { m_repChoice->Enable(true); } } gbtAnalysisOutput *gbtNashChoiceDialog::GetCommand(void) const { bool useEfg = m_repChoice && m_repChoice->GetSelection() == 0; gbtAnalysisOutput *cmd = 0; wxString method = m_methodChoice->GetStringSelection(); wxString prefix, options, game, count; #ifdef __WXMAC__ // For the moment, Mac assumes the command-line tools are in /usr/local prefix = wxT("/usr/local/bin/gambit-"); #else prefix = wxT("gambit-"); #endif // __WXMAC__ if (useEfg) { game = wxT("in extensive game"); } else { options = wxT(" -S "); game = wxT("in strategic game"); } if (m_countChoice->GetSelection() == 0) { count = wxT("One equilibrium"); } else if (m_countChoice->GetSelection() == 1) { count = wxT("Some equilibria"); } else { count = wxT("All equilibria"); } if (method == s_recommended) { if (m_countChoice->GetSelection() == 0) { if (m_doc->NumPlayers() == 2 && m_doc->IsConstSum()) { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("lp") + options); cmd->SetDescription(wxT("One equilibrium by solving a linear program ") + game); } else { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("logit -e -d 10")); cmd->SetDescription(wxT("One equilibrium by logit tracing ") + game); } } else if (m_countChoice->GetSelection() == 1) { if (m_doc->NumPlayers() == 2) { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("lcp") + options); cmd->SetDescription(wxT("Some equilibria by solving a linear " "complementarity program ") + game); } else { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("enumpoly -d 10") + options); cmd->SetDescription(wxT("Some equilibria by solving polynomial " "systems ") + game); } } else { if (m_doc->NumPlayers() == 2) { cmd = new gbtAnalysisProfileList(m_doc, false); cmd->SetCommand(prefix + wxT("enummixed")); cmd->SetDescription(wxT("All equilibria by enumeration of mixed " "strategies in strategic game")); } else { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("enumpoly -d 10") + options); cmd->SetDescription(wxT("All equilibria by solving polynomial " "systems ") + game); } } } else if (method == s_enumpure) { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("enumpure") + options); cmd->SetDescription(count + wxT(" in pure strategies ") + game); } else if (method == s_enummixed) { cmd = new gbtAnalysisProfileList(m_doc, false); cmd->SetCommand(prefix + wxT("enummixed") + options); cmd->SetDescription(count + wxT(" by enumeration of mixed strategies " "in strategic game")); } else if (method == s_enumpoly) { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("enumpoly -d 10") + options); cmd->SetDescription(count + wxT(" by solving polynomial systems ") + game); } else if (method == s_lp) { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("lp") + options); cmd->SetDescription(count + wxT(" by solving a linear program ") + game); } else if (method == s_lcp) { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("lcp") + options); cmd->SetDescription(count + wxT(" by solving a linear complementarity " "program ") + game); } else if (method == s_liap) { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("liap -d 10") + options); cmd->SetDescription(count + wxT(" by function minimization ") + game); } else if (method == s_logit) { cmd = new gbtAnalysisProfileList(m_doc, useEfg); cmd->SetCommand(prefix + wxT("logit -e -d 10") + options); cmd->SetDescription(count + wxT(" by logit tracing ") + game); } else if (method == s_simpdiv) { cmd = new gbtAnalysisProfileList(m_doc, false); cmd->SetCommand(prefix + wxT("simpdiv") + options); cmd->SetDescription(count + wxT(" by simplicial subdivision " "in strategic game")); } else { // Shouldn't happen! } return cmd; } gambit-0.2010.09.01/src/gui/dlnash.h0000644000076500007650000000250611435216101013432 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlnash.h // Dialog for selecting algorithms to compute Nash equilibria // // 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 DLNASH_H #define DLNASH_H #include "gamedoc.h" class gbtNashChoiceDialog : public wxDialog { private: gbtGameDocument *m_doc; wxChoice *m_countChoice, *m_methodChoice, *m_repChoice; // Event handlers void OnCount(wxCommandEvent &); void OnMethod(wxCommandEvent &); public: gbtNashChoiceDialog(wxWindow *, gbtGameDocument *); gbtAnalysisOutput *GetCommand(void) const; }; #endif // DLNFGNASH_H gambit-0.2010.09.01/src/gui/dlnashmon.cc0000644000076500007650000001465211437425500014316 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlnashmon.cc // Dialog for monitoring progress of logit equilibrium computation // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include #include "dlnashmon.h" #include "gamedoc.h" #include "efgprofile.h" #include "nfgprofile.h" const int GBT_ID_TIMER = 1000; const int GBT_ID_PROCESS = 1001; BEGIN_EVENT_TABLE(gbtNashMonitorDialog, wxDialog) EVT_END_PROCESS(GBT_ID_PROCESS, gbtNashMonitorDialog::OnEndProcess) EVT_IDLE(gbtNashMonitorDialog::OnIdle) EVT_TIMER(GBT_ID_TIMER, gbtNashMonitorDialog::OnTimer) END_EVENT_TABLE() #include "bitmaps/stop.xpm" gbtNashMonitorDialog::gbtNashMonitorDialog(wxWindow *p_parent, gbtGameDocument *p_doc, gbtAnalysisOutput *p_command) : wxDialog(p_parent, -1, wxT("Computing Nash equilibria"), wxDefaultPosition), m_doc(p_doc), m_process(0), m_timer(this, GBT_ID_TIMER), m_output(p_command) { wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *startSizer = new wxBoxSizer(wxHORIZONTAL); m_statusText = new wxStaticText(this, wxID_STATIC, wxT("The computation is currently in progress.")); m_statusText->SetForegroundColour(*wxBLUE); startSizer->Add(m_statusText, 0, wxALL | wxALIGN_CENTER, 5); m_countText = new wxStaticText(this, wxID_STATIC, wxT("Number of equilibria found so far: 0 ")); startSizer->Add(m_countText, 0, wxALL | wxALIGN_CENTER, 5); m_stopButton = new wxBitmapButton(this, wxID_CANCEL, wxBitmap(stop_xpm)); m_stopButton->Enable(false); m_stopButton->SetToolTip(_("Stop the computation")); startSizer->Add(m_stopButton, 0, wxALL | wxALIGN_CENTER, 5); Connect(wxID_CANCEL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtNashMonitorDialog::OnStop)); sizer->Add(startSizer, 0, wxALL | wxALIGN_CENTER, 5); if (p_command->IsBehavior()) { m_profileList = new gbtBehavProfileList(this, m_doc); } else { m_profileList = new gbtMixedProfileList(this, m_doc); } m_profileList->SetSizeHints(wxSize(500, 300)); sizer->Add(m_profileList, 1, wxALL | wxEXPAND, 5); m_okButton = new wxButton(this, wxID_OK, wxT("OK")); sizer->Add(m_okButton, 0, wxALL | wxALIGN_RIGHT, 5); m_okButton->Enable(false); SetSizer(sizer); sizer->Fit(this); sizer->SetSizeHints(this); Layout(); CenterOnParent(); Start(p_command); } void gbtNashMonitorDialog::Start(gbtAnalysisOutput *p_command) { if (!p_command->IsBehavior()) { // Make sure we have a normal form representation m_doc->BuildNfg(); } m_doc->AddProfileList(p_command); m_process = new wxProcess(this, GBT_ID_PROCESS); m_process->Redirect(); m_pid = wxExecute(p_command->GetCommand(), wxEXEC_ASYNC, m_process); std::ostringstream s; if (p_command->IsBehavior()) { m_doc->GetGame()->WriteEfgFile(s); } else { m_doc->GetGame()->WriteNfgFile(s); } wxString str(wxString(s.str().c_str(), *wxConvCurrent)); // It is possible that the whole string won't write on one go, so // we should take this possibility into account. If the write doesn't // complete the whole way, we take a 100-millisecond siesta and try // again. (This seems to primarily be an issue with -- you guessed it -- // Windows!) while (str.length() > 0) { wxTextOutputStream os(*m_process->GetOutputStream()); // It appears that (at least with mingw) the string itself contains // only '\n' for newlines. If we don't SetMode here, these get // converted to '\r\n' sequences, and so the number of characters // LastWrite() returns does not match the number of characters in // our string. Setting this explicitly solves this problem. os.SetMode(wxEOL_UNIX); os.WriteString(str); str.Remove(0, m_process->GetOutputStream()->LastWrite()); wxMilliSleep(100); } m_process->CloseOutput(); m_stopButton->Enable(true); m_timer.Start(1000, false); } void gbtNashMonitorDialog::OnIdle(wxIdleEvent &p_event) { if (!m_process) return; if (m_process->IsInputAvailable()) { wxTextInputStream tis(*m_process->GetInputStream()); wxString msg; msg << tis.ReadLine(); m_output->AddOutput(msg); m_countText->SetLabel(wxString::Format(wxT("Number of equilibria found so far: %d"), m_output->NumProfiles())); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); p_event.RequestMore(); } else { m_timer.Start(1000, false); } } void gbtNashMonitorDialog::OnTimer(wxTimerEvent &p_event) { wxWakeUpIdle(); } void gbtNashMonitorDialog::OnEndProcess(wxProcessEvent &p_event) { m_stopButton->Enable(false); m_timer.Stop(); while (m_process->IsInputAvailable()) { wxTextInputStream tis(*m_process->GetInputStream()); wxString msg; msg << tis.ReadLine(); if (msg != wxT("")) { m_output->AddOutput(msg); m_countText->SetLabel(wxString::Format(wxT("Number of equilibria found so far: %d"), m_output->NumProfiles())); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } } if (p_event.GetExitCode() == 0) { m_statusText->SetLabel(wxT("The computation has completed.")); m_statusText->SetForegroundColour(wxColour(0, 192, 0)); } else { m_statusText->SetLabel(wxT("The computation ended abnormally.")); m_statusText->SetForegroundColour(*wxRED); } m_okButton->Enable(true); } void gbtNashMonitorDialog::OnStop(wxCommandEvent &p_event) { // Per the wxWidgets wiki, under Windows, programs that run // without a console window don't respond to the more polite // SIGTERM, so instead we must be rude and SIGKILL it. m_stopButton->Enable(false); #ifdef __WXMSW__ wxProcess::Kill(m_pid, wxSIGKILL); #else wxProcess::Kill(m_pid, wxSIGTERM); #endif // __WXMSW__ } gambit-0.2010.09.01/src/gui/dlnashmon.h0000644000076500007650000000320011435216101014134 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlnashmon.h // Dialog for monitoring Nash equilibrium computation progress // // 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 DLNASHMON_H #define DLNASHMON_H #include #include "wx/sheet/sheet.h" #include "gamedoc.h" class gbtNashMonitorDialog : public wxDialog { private: gbtGameDocument *m_doc; int m_pid; wxProcess *m_process; wxWindow *m_profileList; wxStaticText *m_statusText, *m_countText; wxButton *m_stopButton, *m_okButton; wxTimer m_timer; gbtAnalysisOutput *m_output; void Start(gbtAnalysisOutput *); void OnStop(wxCommandEvent &); void OnTimer(wxTimerEvent &); void OnIdle(wxIdleEvent &); void OnEndProcess(wxProcessEvent &); public: gbtNashMonitorDialog(wxWindow *p_parent, gbtGameDocument *p_doc, gbtAnalysisOutput *p_command); DECLARE_EVENT_TABLE() }; #endif // DLNASHMON_H gambit-0.2010.09.01/src/gui/dlnfglogit.cc0000644000076500007650000006527311435216101014462 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/dlnfglogit.cc // Dialog for monitoring progress of logit equilibrium computation // // 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 #include #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include #include #include #include #include "wx/sheet/sheet.h" #include "wx/plotctrl/plotctrl.h" #include "wx/wxthings/spinctld.h" // for wxSpinCtrlDbl #include "gamedoc.h" #include "menuconst.h" // for tool IDs using namespace Gambit; // Use an anonymous namespace to encapsulate the helper classes namespace { //======================================================================== // class LogitMixedBranch //======================================================================== /// Represents one branch of a logit equilibrium correspondence class LogitMixedBranch { private: gbtGameDocument *m_doc; List m_lambdas; List > m_profiles; public: LogitMixedBranch(gbtGameDocument *p_doc) : m_doc(p_doc) { } void AddProfile(const wxString &p_text); int NumPoints(void) const { return m_lambdas.Length(); } double GetLambda(int p_index) const { return m_lambdas[p_index]; } const List &GetLambdas(void) const { return m_lambdas; } const MixedStrategyProfile &GetProfile(int p_index) { return m_profiles[p_index]; } const List > &GetProfiles(void) const { return m_profiles; } }; void LogitMixedBranch::AddProfile(const wxString &p_text) { MixedStrategyProfile profile(m_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); m_lambdas.Append((double) ToNumber(std::string((const char *) tok.GetNextToken().mb_str()))); for (int i = 1; i <= profile.Length(); i++) { profile[i] = ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } m_profiles.Append(profile); } //======================================================================== // class LogitMixedSheet //======================================================================== class LogitMixedSheet : public wxSheet { private: gbtGameDocument *m_doc; LogitMixedBranch &m_branch; // Overriding wxSheet members for data access wxString GetCellValue(const wxSheetCoords &); wxSheetCellAttr GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const; // Overriding wxSheet members to disable selection behavior bool SelectRow(int, bool = false, bool = false) { return false; } bool SelectRows(int, int, bool = false, bool = false) { return false; } bool SelectCol(int, bool = false, bool = false) { return false; } bool SelectCols(int, int, bool = false, bool = false) { return false; } bool SelectCell(const wxSheetCoords&, bool = false, bool = false) { return false; } bool SelectBlock(const wxSheetBlock&, bool = false, bool = false) { return false; } bool SelectAll(bool = false) { return false; } // Overriding wxSheet member to suppress drawing of cursor void DrawCursorCellHighlight(wxDC&, const wxSheetCellAttr &) { } public: LogitMixedSheet(wxWindow *p_parent, gbtGameDocument *p_doc, LogitMixedBranch &p_branch); virtual ~LogitMixedSheet(); }; LogitMixedSheet::LogitMixedSheet(wxWindow *p_parent, gbtGameDocument *p_doc, LogitMixedBranch &p_branch) : wxSheet(p_parent, -1), m_doc(p_doc), m_branch(p_branch) { CreateGrid(p_branch.NumPoints(), p_doc->GetGame()->MixedProfileLength()+1); SetRowLabelWidth(40); SetColLabelHeight(25); } LogitMixedSheet::~LogitMixedSheet() { } wxString LogitMixedSheet::GetCellValue(const wxSheetCoords &p_coords) { if (!m_doc->GetGame()) return wxT(""); if (IsRowLabelCell(p_coords)) { return wxString::Format(wxT("%d"), p_coords.GetRow() + 1); } else if (IsColLabelCell(p_coords)) { if (p_coords.GetCol() == 0) { return wxT("Lambda"); } else { int index = 1; for (int pl = 1; pl <= m_doc->GetGame()->NumPlayers(); pl++) { GamePlayer player = m_doc->GetGame()->GetPlayer(pl); for (int st = 1; st <= player->NumStrategies(); st++) { if (index++ == p_coords.GetCol()) { return (wxString::Format(wxT("%d: "), pl) + wxString(player->GetStrategy(st)->GetLabel().c_str(), *wxConvCurrent)); } } } return wxT(""); } } else if (IsCornerLabelCell(p_coords)) { return wxT("#"); } if (p_coords.GetCol() == 0) { return wxString(ToText(m_branch.GetLambda(p_coords.GetRow()+1), m_doc->GetStyle().NumDecimals()).c_str(), *wxConvCurrent); } else { const MixedStrategyProfile &profile = m_branch.GetProfile(p_coords.GetRow()+1); return wxString(ToText(profile[p_coords.GetCol()], m_doc->GetStyle().NumDecimals()).c_str(), *wxConvCurrent); } } static wxColour GetPlayerColor(gbtGameDocument *p_doc, int p_index) { if (!p_doc->GetGame()) return *wxBLACK; int index = 1; for (int pl = 1; pl <= p_doc->GetGame()->NumPlayers(); pl++) { GamePlayer player = p_doc->GetGame()->GetPlayer(pl); for (int st = 1; st <= player->NumStrategies(); st++) { if (index++ == p_index) { return p_doc->GetStyle().GetPlayerColor(pl); } } } return *wxBLACK; } wxSheetCellAttr LogitMixedSheet::GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const { if (IsRowLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultRowLabelAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); return attr; } else if (IsColLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultColLabelAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); attr.SetForegroundColour(GetPlayerColor(m_doc, p_coords.GetCol())); return attr; } else if (IsCornerLabelCell(p_coords)) { return GetSheetRefData()->m_defaultCornerLabelAttr; } wxSheetCellAttr attr(GetSheetRefData()->m_defaultGridCellAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); attr.SetAlignment(wxALIGN_RIGHT, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetForegroundColour(GetPlayerColor(m_doc, p_coords.GetCol())); attr.SetReadOnly(true); return attr; } class LogitBranchDialog : public wxDialog { private: LogitMixedSheet *m_sheet; public: LogitBranchDialog(wxWindow *p_parent, gbtGameDocument *p_doc, LogitMixedBranch &p_branch); }; LogitBranchDialog::LogitBranchDialog(wxWindow *p_parent, gbtGameDocument *p_doc, LogitMixedBranch &p_branch) : wxDialog(p_parent, wxID_ANY, wxT("Logit equilibrium correspondence"), wxDefaultPosition) { m_sheet = new LogitMixedSheet(this, p_doc, p_branch); m_sheet->AutoSizeCol(0); wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(m_sheet, 0, wxALL, 5); sizer->Add(CreateButtonSizer(wxOK), 0, wxALL | wxEXPAND, 5); SetSizer(sizer); sizer->Fit(this); sizer->SetSizeHints(this); Layout(); CenterOnParent(); } //======================================================================== // class gbtLogitPlotCtrl //======================================================================== class gbtLogitPlotCtrl : public wxPlotCtrl { private: gbtGameDocument *m_doc; double m_scaleFactor; /// Overriding x (lambda) axis labeling void CalcXAxisTickPositions(void); public: gbtLogitPlotCtrl(wxWindow *p_parent, gbtGameDocument *p_doc); double LambdaToX(double p_lambda) { return m_scaleFactor*p_lambda / (1.0 + m_scaleFactor*p_lambda); } double XToLambda(double p_x) { return p_x / (m_scaleFactor * (1.0 - p_x)); } void SetScaleFactor(double p_scale) { m_scaleFactor = p_scale; } }; gbtLogitPlotCtrl::gbtLogitPlotCtrl(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPlotCtrl(p_parent), m_doc(p_doc), m_scaleFactor(1.0) { SetAxisLabelColour(*wxBLUE); wxFont labelFont(8, wxSWISS, wxNORMAL, wxBOLD); SetAxisLabelFont(labelFont); SetAxisColour(*wxBLUE); SetAxisFont(labelFont); SetDrawSymbols(false); // SetAxisFont resets the width of the y axis labels, assuming // a fairly long label. int x=6, y=12, descent=0, leading=0; GetTextExtent(wxT("0.88"), &x, &y, &descent, &leading, &labelFont); m_y_axis_text_width = x + leading; SetXAxisLabel(wxT("Lambda")); SetShowXAxisLabel(true); SetYAxisLabel(wxT("Probability")); SetShowYAxisLabel(true); SetShowKey(true); m_xAxisTick_step = 0.2; SetViewRect(wxRect2DDouble(0, 0, 1, 1)); } // // This differs from the wxPlotWindow original only by the use of // XToLambda() to construct the tick labels. // void gbtLogitPlotCtrl::CalcXAxisTickPositions(void) { double current = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step; m_xAxisTicks.Clear(); m_xAxisTickLabels.Clear(); int i, x, windowWidth = GetPlotAreaRect().width; for (i=0; i= -1) && (x < windowWidth+2)) { m_xAxisTicks.Add(x); m_xAxisTickLabels.Add(wxString::Format(m_xAxisTickFormat.c_str(), XToLambda(current))); } current += m_xAxisTick_step; } } //======================================================================== // class gbtLogitPlotStrategyList //======================================================================== class gbtLogitPlotStrategyList : public wxSheet { private: gbtGameDocument *m_doc; //! //! @name Overriding wxSheet members to disable selection behavior //! //@{ bool SelectRow(int, bool = false, bool = false) { return false; } bool SelectRows(int, int, bool = false, bool = false) { return false; } bool SelectCol(int, bool = false, bool = false) { return false; } bool SelectCols(int, int, bool = false, bool = false) { return false; } bool SelectCell(const wxSheetCoords&, bool = false, bool = false) { return false; } bool SelectBlock(const wxSheetBlock&, bool = false, bool = false) { return false; } bool SelectAll(bool = false) { return false; } bool HasSelection(bool = true) const { return false; } bool IsCellSelected(const wxSheetCoords &) const { return false; } bool IsRowSelected(int) const { return false; } bool IsColSelected(int) const { return false; } bool DeselectBlock(const wxSheetBlock &, bool = false) { return false; } bool ClearSelection(bool = false) { return false; } //@} /// Overriding wxSheet member to suppress drawing of cursor void DrawCursorCellHighlight(wxDC&, const wxSheetCellAttr &) { } // Event handlers // This disables moving the (unseen) cursor void OnLeftDown(wxSheetEvent &) { } void OnLeftUp(wxSheetEvent &); public: gbtLogitPlotStrategyList(wxWindow *p_parent, gbtGameDocument *p_doc); bool IsShown(int p_index) { return GetCellValue(wxSheetCoords(p_index-1, 2)) == wxT("1"); } }; gbtLogitPlotStrategyList::gbtLogitPlotStrategyList(wxWindow *p_parent, gbtGameDocument *p_doc) : wxSheet(p_parent, wxID_ANY), m_doc(p_doc) { CreateGrid(m_doc->GetGame()->MixedProfileLength(), 3); SetRowLabelWidth(0); SetColLabelHeight(0); SetGridLineColour(*wxWHITE); for (int st = 1; st <= m_doc->GetGame()->MixedProfileLength(); st++) { GameStrategy strategy = m_doc->GetGame()->GetStrategy(st); GamePlayer player = strategy->GetPlayer(); wxColour color = m_doc->GetStyle().GetPlayerColor(player->GetNumber()); if (strategy->GetNumber() == 1) { SetCellSpan(wxSheetCoords(st-1, 0), wxSheetCoords(player->NumStrategies(), 1)); SetCellValue(wxSheetCoords(st-1, 0), wxString(player->GetLabel().c_str(), *wxConvCurrent)); SetAttrForegroundColour(wxSheetCoords(st-1, 0), color); SetAttrAlignment(wxSheetCoords(st-1, 0), wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); } SetCellValue(wxSheetCoords(st-1, 1), wxString(strategy->GetLabel().c_str(), *wxConvCurrent)); SetAttrForegroundColour(wxSheetCoords(st-1, 1), color); SetCellValue(wxSheetCoords(st-1, 2), wxT("1")); SetAttrForegroundColour(wxSheetCoords(st-1, 2), color); SetAttrRenderer(wxSheetCoords(st-1, 2), wxSheetCellRenderer(new wxSheetCellBoolRendererRefData())); SetAttrEditor(wxSheetCoords(st-1, 2), wxSheetCellEditor(new wxSheetCellBoolEditorRefData())); } AutoSizeCols(); Connect(GetId(), wxEVT_SHEET_CELL_LEFT_DOWN, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtLogitPlotStrategyList::OnLeftDown))); Connect(GetId(), wxEVT_SHEET_CELL_LEFT_UP, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtLogitPlotStrategyList::OnLeftUp))); } void gbtLogitPlotStrategyList::OnLeftUp(wxSheetEvent &p_event) { if (p_event.GetCoords().GetCol() != 2) { return; } if (GetCellValue(p_event.GetCoords()) == wxT("1")) { SetCellValue(p_event.GetCoords(), wxT("0")); } else { SetCellValue(p_event.GetCoords(), wxT("1")); } // Allow normal processing -- parent window will want to update p_event.Skip(); } //======================================================================== // class LogitPlotPanel //======================================================================== class LogitPlotPanel : public wxPanel { private: gbtGameDocument *m_doc; LogitMixedBranch m_branch; gbtLogitPlotStrategyList *m_plotStrategies; gbtLogitPlotCtrl *m_plotCtrl; // Event handlers void OnChangeStrategies(wxSheetEvent &) { Plot(); } public: LogitPlotPanel(wxWindow *p_parent, gbtGameDocument *p_doc); void AddProfile(const wxString &p_text) { m_branch.AddProfile(p_text); } void SetScaleFactor(double p_scale); void FitZoom(void); void Plot(void); LogitMixedBranch &GetBranch(void) { return m_branch; } wxPlotCtrl *GetPlotCtrl(void) const { return m_plotCtrl; } }; LogitPlotPanel::LogitPlotPanel(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, wxID_ANY), m_doc(p_doc), m_branch(p_doc) { m_plotCtrl = new gbtLogitPlotCtrl(this, p_doc); m_plotCtrl->SetSizeHints(wxSize(600, 400)); m_plotStrategies = new gbtLogitPlotStrategyList(this, p_doc); wxStaticBoxSizer *playerSizer = new wxStaticBoxSizer(wxHORIZONTAL, this, wxT("Show strategies")); playerSizer->Add(m_plotStrategies, 1, wxALL | wxEXPAND, 5); wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(playerSizer, 0, wxALL | wxEXPAND, 5); sizer->Add(m_plotCtrl, 0, wxALL, 5); Connect(m_plotStrategies->GetId(), wxEVT_SHEET_CELL_LEFT_UP, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&LogitPlotPanel::OnChangeStrategies))); SetSizer(sizer); Layout(); } void LogitPlotPanel::Plot(void) { if (m_branch.NumPoints() == 0) return; m_plotCtrl->DeleteCurve(-1); for (int st = 1; st <= m_doc->GetGame()->MixedProfileLength(); st++) { if (!m_plotStrategies->IsShown(st)) continue; wxPlotData *curve = new wxPlotData(m_branch.NumPoints()); GameStrategy strategy = m_doc->GetGame()->GetStrategy(st); GamePlayer player = strategy->GetPlayer(); curve->SetFilename(wxString(player->GetLabel().c_str(), *wxConvCurrent) + wxT(":") + wxString(strategy->GetLabel().c_str(), *wxConvCurrent)); for (int i = 0; i < m_branch.NumPoints(); i++) { curve->SetValue(i, m_plotCtrl->LambdaToX(m_branch.GetLambda(i+1)), m_branch.GetProfile(i+1)[st]); } curve->SetPen(wxPLOTPEN_NORMAL, wxPen(m_doc->GetStyle().GetPlayerColor(player->GetNumber()), 1, wxSOLID)); m_plotCtrl->AddCurve(curve, false); } } void LogitPlotPanel::SetScaleFactor(double p_scale) { m_plotCtrl->SetScaleFactor(p_scale); Plot(); } void LogitPlotPanel::FitZoom(void) { m_plotCtrl->MakeCurveVisible(-1); } //======================================================================== // class LogitPrintout //======================================================================== class LogitPrintout : public wxPrintout { private: wxPlotCtrl *m_plot; public: LogitPrintout(wxPlotCtrl *p_plot, const wxString &p_label) : wxPrintout(p_label), m_plot(p_plot) { } virtual ~LogitPrintout() { } bool OnPrintPage(int) { wxSize size = GetDC()->GetSize(); m_plot->DrawWholePlot(GetDC(), wxRect(50, 50, size.GetWidth() - 100, size.GetHeight() - 100)); return true; } bool HasPage(int page) { return (page <= 1); } void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) { *minPage = 1; *maxPage = 1; *selPageFrom = 1; *selPageTo = 1; } }; //======================================================================== // class LogitMixedDialog //======================================================================== class LogitMixedDialog : public wxDialog { private: gbtGameDocument *m_doc; int m_pid; wxProcess *m_process; LogitPlotPanel *m_plot; wxSpinCtrlDbl *m_scaler; wxToolBar *m_toolBar; wxStaticText *m_statusText; wxButton *m_stopButton, *m_okButton; wxTimer m_timer; wxString m_output; void OnStop(wxCommandEvent &); void OnTimer(wxTimerEvent &); void OnIdle(wxIdleEvent &); void OnEndProcess(wxProcessEvent &); void OnSave(wxCommandEvent &); void OnPrint(wxCommandEvent &); void OnChangeScale(wxSpinEvent &); void OnZoomFit(wxCommandEvent &); void OnViewData(wxCommandEvent &); void Start(void); public: LogitMixedDialog(wxWindow *p_parent, gbtGameDocument *p_doc); DECLARE_EVENT_TABLE() }; const int GBT_ID_TIMER = 2000; const int GBT_ID_PROCESS = 2001; const int GBT_MENU_VIEW_DATA = 2002; BEGIN_EVENT_TABLE(LogitMixedDialog, wxDialog) EVT_END_PROCESS(GBT_ID_PROCESS, LogitMixedDialog::OnEndProcess) EVT_IDLE(LogitMixedDialog::OnIdle) EVT_TIMER(GBT_ID_TIMER, LogitMixedDialog::OnTimer) EVT_MENU(wxID_SAVE, LogitMixedDialog::OnSave) EVT_MENU(wxID_PRINT, LogitMixedDialog::OnPrint) EVT_MENU(GBT_MENU_VIEW_ZOOMFIT, LogitMixedDialog::OnZoomFit) EVT_MENU(GBT_MENU_VIEW_DATA, LogitMixedDialog::OnViewData) END_EVENT_TABLE() #include "bitmaps/stop.xpm" #include "bitmaps/print.xpm" #include "bitmaps/savedata.xpm" #include "bitmaps/datasrc.xpm" #include "bitmaps/zoomfit.xpm" LogitMixedDialog::LogitMixedDialog(wxWindow *p_parent, gbtGameDocument *p_doc) : wxDialog(p_parent, -1, wxT("Compute quantal response equilibria"), wxDefaultPosition), m_doc(p_doc), m_process(0), m_timer(this, GBT_ID_TIMER) { wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *startSizer = new wxBoxSizer(wxHORIZONTAL); m_statusText = new wxStaticText(this, wxID_STATIC, wxT("The computation is currently in progress.")); m_statusText->SetForegroundColour(*wxBLUE); startSizer->Add(m_statusText, 0, wxALL | wxALIGN_CENTER, 5); m_stopButton = new wxBitmapButton(this, wxID_CANCEL, wxBitmap(stop_xpm)); m_stopButton->SetToolTip(_("Stop the computation")); startSizer->Add(m_stopButton, 0, wxALL | wxALIGN_CENTER, 5); Connect(wxID_CANCEL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(LogitMixedDialog::OnStop)); sizer->Add(startSizer, 0, wxALL | wxALIGN_CENTER, 5); m_toolBar = new wxToolBar(this, wxID_ANY); m_toolBar->SetWindowStyle(wxTB_HORIZONTAL | wxTB_FLAT); m_toolBar->SetMargins(4, 4); m_toolBar->SetToolBitmapSize(wxSize(24, 24)); m_toolBar->AddTool(wxID_SAVE, wxBitmap(savedata_xpm), wxNullBitmap, false, -1, -1, 0, _("Save the correspondence to a CSV file"), _("Save the correspondence to a CSV file")); m_toolBar->EnableTool(wxID_SAVE, false); m_toolBar->AddTool(GBT_MENU_VIEW_DATA, wxBitmap(datasrc_xpm), wxNullBitmap, false, -1, -1, 0, _("View the points in the correspondence"), _("View the points in the correspondence")); m_toolBar->EnableTool(GBT_MENU_VIEW_DATA, false); m_toolBar->AddTool(wxID_PRINT, wxBitmap(print_xpm), wxNullBitmap, false, -1, -1, 0, _("Print the graph"), _("Print the graph")); m_toolBar->AddSeparator(); m_toolBar->AddTool(GBT_MENU_VIEW_ZOOMFIT, wxBitmap(zoomfit_xpm), wxNullBitmap, false, -1, -1, 0, _("Show the whole graph"), _("Show the whole graph")); m_toolBar->AddControl(new wxStaticText(m_toolBar, wxID_STATIC, wxT("Graph scaling:"))); m_scaler = new wxSpinCtrlDbl(*m_toolBar, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0, 0.1, 10.0, 1.0, 0.1); m_toolBar->AddControl(m_scaler); Connect(m_scaler->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(LogitMixedDialog::OnChangeScale)); m_toolBar->Realize(); sizer->Add(m_toolBar, 0, wxALL | wxEXPAND, 5); wxBoxSizer *midSizer = new wxBoxSizer(wxHORIZONTAL); m_plot = new LogitPlotPanel(this, m_doc); midSizer->Add(m_plot, 0, wxALL | wxALIGN_CENTER, 5); sizer->Add(midSizer, 0, wxALL | wxALIGN_CENTER, 5); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); m_okButton = new wxButton(this, wxID_OK, wxT("OK")); buttonSizer->Add(m_okButton, 0, wxALL | wxALIGN_CENTER, 5); m_okButton->Enable(false); sizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5); SetSizer(sizer); sizer->Fit(this); sizer->SetSizeHints(this); Layout(); CenterOnParent(); Start(); } void LogitMixedDialog::Start(void) { m_doc->BuildNfg(); m_process = new wxProcess(this, GBT_ID_PROCESS); m_process->Redirect(); #ifdef __WXMAC__ m_pid = wxExecute(wxT("/usr/local/bin/gambit-logit -S"), wxEXEC_ASYNC, m_process); #else m_pid = wxExecute(wxT("gambit-logit -S"), wxEXEC_ASYNC, m_process); #endif // __WXMAC__ std::ostringstream s; m_doc->GetGame()->WriteNfgFile(s); wxString str(wxString(s.str().c_str(), *wxConvCurrent)); // It is possible that the whole string won't write on one go, so // we should take this possibility into account. If the write doesn't // complete the whole way, we take a 100-millisecond siesta and try // again. (This seems to primarily be an issue with -- you guessed it -- // Windows!) while (str.length() > 0) { wxTextOutputStream os(*m_process->GetOutputStream()); // It appears that (at least with mingw) the string itself contains // only '\n' for newlines. If we don't SetMode here, these get // converted to '\r\n' sequences, and so the number of characters // LastWrite() returns does not match the number of characters in // our string. Setting this explicitly solves this problem. os.SetMode(wxEOL_UNIX); os.WriteString(str); str.Remove(0, m_process->GetOutputStream()->LastWrite()); wxMilliSleep(100); } m_process->CloseOutput(); m_timer.Start(1000, false); } void LogitMixedDialog::OnIdle(wxIdleEvent &p_event) { if (!m_process) return; if (m_process->IsInputAvailable()) { wxTextInputStream tis(*m_process->GetInputStream()); wxString msg; msg << tis.ReadLine(); m_plot->AddProfile(msg); //m_mixedList->AddProfile(msg, false); m_output += msg; m_output += wxT("\n"); p_event.RequestMore(); } else { m_timer.Start(1000, false); } } void LogitMixedDialog::OnTimer(wxTimerEvent &p_event) { wxWakeUpIdle(); } void LogitMixedDialog::OnEndProcess(wxProcessEvent &p_event) { m_stopButton->Enable(false); m_timer.Stop(); while (m_process->IsInputAvailable()) { wxTextInputStream tis(*m_process->GetInputStream()); wxString msg; msg << tis.ReadLine(); if (msg != wxT("")) { m_plot->AddProfile(msg); //m_mixedList->AddProfile(msg, true); m_output += msg; m_output += wxT("\n"); } } if (p_event.GetExitCode() == 0) { m_statusText->SetLabel(wxT("The computation has completed.")); m_statusText->SetForegroundColour(wxColour(0, 192, 0)); } else { m_statusText->SetLabel(wxT("The computation ended abnormally.")); m_statusText->SetForegroundColour(*wxRED); } m_okButton->Enable(true); m_toolBar->EnableTool(wxID_SAVE, true); m_toolBar->EnableTool(GBT_MENU_VIEW_DATA, true); m_plot->Plot(); } void LogitMixedDialog::OnStop(wxCommandEvent &) { // Per the wxWidgets wiki, under Windows, programs that run // without a console window don't respond to the more polite // SIGTERM, so instead we must be rude and SIGKILL it. m_stopButton->Enable(false); #ifdef __WXMSW__ wxProcess::Kill(m_pid, wxSIGKILL); #else wxProcess::Kill(m_pid, wxSIGTERM); #endif // __WXMSW__ } void LogitMixedDialog::OnSave(wxCommandEvent &) { wxFileDialog dialog(this, _("Choose file"), wxT(""), wxT(""), wxT("CSV files (*.csv)|*.csv|" "All files (*.*)|*.*"), wxSAVE | wxOVERWRITE_PROMPT); if (dialog.ShowModal() == wxID_OK) { std::ofstream file((const char *) dialog.GetPath().mb_str()); file << ((const char *) m_output.mb_str()); } } void LogitMixedDialog::OnPrint(wxCommandEvent &) { wxPrintDialogData data; wxPrinter printer(&data); wxPrintout *printout = new LogitPrintout(m_plot->GetPlotCtrl(), wxT("Logit correspondence")); if (!printer.Print(this, printout, true)) { if (wxPrinter::GetLastError() == wxPRINTER_ERROR) { wxMessageBox(_("There was an error in printing"), _("Error"), wxOK); } // Otherwise, user hit "cancel"; just be quiet and return. return; } } void LogitMixedDialog::OnChangeScale(wxSpinEvent &) { m_plot->SetScaleFactor(m_scaler->GetValue()); } void LogitMixedDialog::OnZoomFit(wxCommandEvent &) { m_plot->FitZoom(); } void LogitMixedDialog::OnViewData(wxCommandEvent &) { LogitBranchDialog dialog(this, m_doc, m_plot->GetBranch()); dialog.ShowModal(); } } // end encapsulating anonymous namespace //======================================================================== // External interface //======================================================================== void LogitStrategic(wxWindow *p_parent, gbtGameDocument *p_doc) { LogitMixedDialog(p_parent, p_doc).ShowModal(); } gambit-0.2010.09.01/src/gui/edittext.cc0000644000076500007650000001066511435216101014156 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/edittext.cc // A widget that functions as an editable wxStaticText // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "edittext.h" //========================================================================= // class gbtStaticTextButton //========================================================================= BEGIN_EVENT_TABLE(gbtStaticTextButton, wxStaticText) EVT_LEFT_DOWN(gbtStaticTextButton::OnLeftClick) END_EVENT_TABLE() gbtStaticTextButton::gbtStaticTextButton(wxWindow *p_parent, int p_id, const wxString &p_label, const wxPoint &p_position, const wxSize &p_size, long p_style) : wxStaticText(p_parent, -1, p_label, p_position, p_size, p_style) { } void gbtStaticTextButton::OnLeftClick(wxMouseEvent &p_event) { wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED); event.SetId(GetId()); wxPostEvent(GetParent(), event); p_event.Skip(); } //========================================================================= // class gbtEditableText //========================================================================= gbtEditableText::gbtEditableText(wxWindow *p_parent, int p_id, const wxString &p_value, const wxPoint &p_position, const wxSize &p_size) : wxPanel(p_parent, p_id, p_position, p_size) { m_staticText = new gbtStaticTextButton(this, -1, p_value, wxPoint(0, 0), p_size, wxALIGN_LEFT); Connect(m_staticText->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtEditableText::OnClick)); m_textCtrl = new wxTextCtrl(this, -1, p_value, wxPoint(0, 0), p_size, wxTE_PROCESS_ENTER); Connect(m_textCtrl->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(gbtEditableText::OnAccept)); wxBoxSizer *topSizer = new wxBoxSizer(wxHORIZONTAL); topSizer->Add(m_staticText, 1, wxALIGN_CENTER, 0); topSizer->Add(m_textCtrl, 1, wxEXPAND | wxALIGN_CENTER, 0); topSizer->Show(m_textCtrl, false); SetSizer(topSizer); Layout(); } void gbtEditableText::BeginEdit(void) { m_textCtrl->SetValue(m_staticText->GetLabel()); m_textCtrl->SetSelection(-1, -1); GetSizer()->Show(m_staticText, false); GetSizer()->Show(m_textCtrl, true); GetSizer()->Layout(); m_textCtrl->SetFocus(); } void gbtEditableText::EndEdit(bool p_accept) { if (p_accept) { m_staticText->SetLabel(m_textCtrl->GetValue()); } GetSizer()->Show(m_textCtrl, false); GetSizer()->Show(m_staticText, true); GetSizer()->Layout(); } wxString gbtEditableText::GetValue(void) const { if (GetSizer()->IsShown(m_textCtrl)) { return m_textCtrl->GetValue(); } else { return m_staticText->GetLabel(); } } void gbtEditableText::SetValue(const wxString &p_value) { m_textCtrl->SetValue(p_value); m_staticText->SetLabel(p_value); } bool gbtEditableText::SetForegroundColour(const wxColour &p_color) { m_staticText->SetForegroundColour(p_color); m_textCtrl->SetForegroundColour(p_color); return true; } bool gbtEditableText::SetBackgroundColour(const wxColour &p_color) { m_staticText->SetBackgroundColour(p_color); m_textCtrl->SetBackgroundColour(p_color); return true; } bool gbtEditableText::SetFont(const wxFont &p_font) { m_staticText->SetFont(p_font); m_textCtrl->SetFont(p_font); return true; } void gbtEditableText::OnClick(wxCommandEvent &) { wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED); event.SetId(GetId()); wxPostEvent(GetParent(), event); } void gbtEditableText::OnAccept(wxCommandEvent &) { EndEdit(true); wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER); event.SetId(GetId()); wxPostEvent(GetParent(), event); } gambit-0.2010.09.01/src/gui/edittext.h0000644000076500007650000000456511435216101014022 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/edittext.h // A widget that functions as an editable wxStaticText // // 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 EDITTEXT_H #define EDITTEXT_H //! //! A gbtStaticTextButton is a wxStaticText object that generates a //! button click event when it is left-clicked //! class gbtStaticTextButton : public wxStaticText { private: // Event handlers void OnLeftClick(wxMouseEvent &); public: gbtStaticTextButton(wxWindow *p_parent, int p_id, const wxString &, const wxPoint & = wxDefaultPosition, const wxSize & = wxDefaultSize, long = 0); DECLARE_EVENT_TABLE() }; //! //! This control looks like a wxStaticText, but when clicked it shows //! a wxTextCtrl to edit the value. //! class gbtEditableText : public wxPanel { private: gbtStaticTextButton *m_staticText; wxTextCtrl *m_textCtrl; /// @name Event handlers //@{ /// Called when the static text is clicked void OnClick(wxCommandEvent &); /// Called when the text control is dismissed via enter void OnAccept(wxCommandEvent &); //@} public: gbtEditableText(wxWindow *p_parent, int p_id, const wxString &p_value, const wxPoint &p_position, const wxSize &p_size); bool IsEditing(void) const { return GetSizer()->IsShown(m_textCtrl); } void BeginEdit(void); void EndEdit(bool p_accept = true); wxString GetValue(void) const; void SetValue(const wxString &p_value); // @name Overriding wxWindow methods //@{ bool SetForegroundColour(const wxColour &); bool SetBackgroundColour(const wxColour &); bool SetFont(const wxFont &); //@} }; #endif // EDITTEXT_H gambit-0.2010.09.01/src/gui/efgdisplay.cc0000644000076500007650000007143711435216101014457 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/efgdisplay.cc // Implementation of window class to display extensive form tree // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include // for drag-and-drop support #include #include "libgambit/libgambit.h" #include "efgdisplay.h" #include "menuconst.h" //-------------------------------------------------------------------------- // class gbtPayoffEditor //-------------------------------------------------------------------------- BEGIN_EVENT_TABLE(gbtPayoffEditor, wxTextCtrl) EVT_CHAR(gbtPayoffEditor::OnChar) END_EVENT_TABLE() gbtPayoffEditor::gbtPayoffEditor(wxWindow *p_parent) : wxTextCtrl(p_parent, -1, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER) { Show(false); } void gbtPayoffEditor::BeginEdit(gbtNodeEntry *p_entry, int p_player) { m_entry = p_entry; m_outcome = p_entry->GetNode()->GetOutcome(); m_player = p_player; SetValue(wxString(m_outcome->GetPayoff(p_player).c_str(), *wxConvCurrent)); SetSelection(-1, -1); Show(true); SetFocus(); } void gbtPayoffEditor::EndEdit(void) { Show(false); } void gbtPayoffEditor::OnChar(wxKeyEvent &p_event) { if (p_event.GetKeyCode() == WXK_TAB) { // We handle the event and pass it to the parent wxPostEvent(GetParent(), p_event); } else { // Default processing p_event.Skip(); } } //-------------------------------------------------------------------------- // Bitmap drawing functions //-------------------------------------------------------------------------- static wxBitmap MakeOutcomeBitmap(void) { wxBitmap bitmap(24, 24); wxMemoryDC dc; dc.SelectObject(bitmap); dc.Clear(); dc.SetPen(wxPen(*wxBLACK, 1, wxSOLID)); // Make a gold-colored background dc.SetBrush(wxBrush(wxColour(255, 215, 0), wxSOLID)); dc.DrawCircle(12, 12, 10); dc.SetFont(wxFont(12, wxSWISS, wxNORMAL, wxBOLD)); dc.SetTextForeground(wxColour(0, 192, 0)); int width, height; dc.GetTextExtent(wxT("u"), &width, &height); dc.DrawText(wxT("u"), 12 - width/2, 12 - height/2); return bitmap; } //-------------------------------------------------------------------------- // class gbtPlayerDropTarget //-------------------------------------------------------------------------- class gbtPlayerDropTarget : public wxTextDropTarget { private: gbtEfgDisplay *m_owner; public: gbtPlayerDropTarget(gbtEfgDisplay *p_owner) { m_owner = p_owner; } bool OnDropText(wxCoord x, wxCoord y, const wxString &p_text); }; // // This recurses the subtree starting at 'p_node' looking for a node // with the ID 'p_id'. // static Gambit::GameNode GetNode(Gambit::GameNode p_node, int p_id) { if (p_node->GetNumber() == p_id) { return p_node; } else if (p_node->NumChildren() == 0) { return 0; } else { for (int i = 1; i <= p_node->NumChildren(); i++) { Gambit::GameNode node = GetNode(p_node->GetChild(i), p_id); if (node) return node; } return 0; } } bool gbtPlayerDropTarget::OnDropText(wxCoord p_x, wxCoord p_y, const wxString &p_text) { Gambit::Game efg = m_owner->GetDocument()->GetGame(); int x, y; #if defined( __WXMSW__) // The +12 here is designed to effectively make the hot spot on // the cursor the center of the cursor image (they're currently // 24 pixels wide). m_owner->CalcUnscrolledPosition(p_x + 12, p_y + 12, &x, &y); #else // Under GTK, there is an angle in the upper left-hand corner which // serves to identify the hot spot. Thus, no adjustment is used m_owner->CalcUnscrolledPosition(p_x, p_y, &x, &y); #endif // __WXMSW__ or defined(__WXMAC__) x = (int) ((float) x / (.01 * m_owner->GetZoom())); y = (int) ((float) y / (.01 * m_owner->GetZoom())); Gambit::GameNode node = m_owner->GetLayout().NodeHitTest(x, y); if (node) { switch (p_text[0]) { case 'P': { long pl; p_text.Right(p_text.Length() - 1).ToLong(&pl); Gambit::GamePlayer player; if (pl == 0) { player = efg->GetChance(); } else { player = efg->GetPlayer(pl); } if (node->NumChildren() == 0) { Gambit::GameInfoset infoset = node->AppendMove(player, 2); infoset->GetAction(1)->SetLabel("1"); infoset->GetAction(2)->SetLabel("2"); } else if (node->GetPlayer() == player) { Gambit::GameAction action = node->GetInfoset()->InsertAction(); action->SetLabel(Gambit::ToText(action->GetNumber())); } else if (!player->IsChance() && !node->GetPlayer()->IsChance()) { // Currently don't support switching nodes to/from chance player node->GetInfoset()->SetPlayer(player); } else { return false; } m_owner->GetDocument()->UpdateViews(GBT_DOC_MODIFIED_GAME); return true; } case 'C': { long n; p_text.Right(p_text.Length() - 1).ToLong(&n); Gambit::GameNode srcNode = GetNode(m_owner->GetDocument()->GetGame()->GetRoot(), n); if (!srcNode) { return false; } if (node->NumChildren() == 0 && srcNode->NumChildren() > 0) { node->CopyTree(srcNode); m_owner->GetDocument()->UpdateViews(GBT_DOC_MODIFIED_GAME); return true; } return false; } case 'M': { long n; p_text.Right(p_text.Length() - 1).ToLong(&n); Gambit::GameNode srcNode = GetNode(efg->GetRoot(), n); if (!srcNode) { return false; } if (node->NumChildren() == 0 && srcNode->NumChildren() > 0) { node->MoveTree(srcNode); m_owner->GetDocument()->UpdateViews(GBT_DOC_MODIFIED_GAME); return true; } return false; } case 'I': { long n; p_text.Right(p_text.Length() - 1).ToLong(&n); Gambit::GameNode srcNode = GetNode(efg->GetRoot(), n); if (!srcNode) { return false; } if (node->NumChildren() > 0 && node->NumChildren() == srcNode->NumChildren()) { node->SetInfoset(srcNode->GetInfoset()); m_owner->GetDocument()->UpdateViews(GBT_DOC_MODIFIED_GAME); return true; } else if (node->NumChildren() == 0 && srcNode->NumChildren() > 0) { node->AppendMove(srcNode->GetInfoset()); m_owner->GetDocument()->UpdateViews(GBT_DOC_MODIFIED_GAME); return true; } return false; } case 'O': { long n; p_text.Right(p_text.Length() - 1).ToLong(&n); Gambit::GameNode srcNode = GetNode(efg->GetRoot(), n); if (!srcNode || node == srcNode) { return false; } node->SetOutcome(srcNode->GetOutcome()); m_owner->GetDocument()->UpdateViews(GBT_DOC_MODIFIED_PAYOFFS); return true; } case 'o': { long n; p_text.Right(p_text.Length() - 1).ToLong(&n); Gambit::GameNode srcNode = GetNode(efg->GetRoot(), n); if (!srcNode || node == srcNode) { return false; } node->SetOutcome(srcNode->GetOutcome()); srcNode->SetOutcome(0); m_owner->GetDocument()->UpdateViews(GBT_DOC_MODIFIED_PAYOFFS); return true; } case 'p': { long n; p_text.Right(p_text.Length() - 1).ToLong(&n); Gambit::GameNode srcNode = GetNode(efg->GetRoot(), n); if (!srcNode || node == srcNode) { return false; } Gambit::GameOutcome outcome = srcNode->GetGame()->NewOutcome(); outcome->SetLabel("Outcome" + Gambit::ToText(outcome->GetNumber())); for (int pl = 1; pl <= srcNode->GetGame()->NumPlayers(); pl++) { outcome->SetPayoff(pl, srcNode->GetOutcome()->GetPayoff(pl)); } node->SetOutcome(outcome); m_owner->GetDocument()->UpdateViews(GBT_DOC_MODIFIED_PAYOFFS); return true; } } } return false; } //---------------------------------------------------------------------- // gbtEfgDisplay: Member functions //---------------------------------------------------------------------- BEGIN_EVENT_TABLE(gbtEfgDisplay, wxScrolledWindow) EVT_MOTION(gbtEfgDisplay::OnMouseMotion) EVT_LEFT_DOWN(gbtEfgDisplay::OnLeftClick) EVT_LEFT_DCLICK(gbtEfgDisplay::OnLeftDoubleClick) EVT_RIGHT_DOWN(gbtEfgDisplay::OnRightClick) EVT_CHAR(gbtEfgDisplay::OnKeyEvent) END_EVENT_TABLE() //---------------------------------------------------------------------- // gbtEfgDisplay: Constructor and destructor //---------------------------------------------------------------------- gbtEfgDisplay::gbtEfgDisplay(wxWindow *p_parent, gbtGameDocument *p_doc) : wxScrolledWindow(p_parent), gbtGameView(p_doc), m_layout(this, p_doc), m_zoom(100) { SetBackgroundColour(wxColour(250, 250, 250)); m_payoffEditor = new gbtPayoffEditor(this); SetDropTarget(new gbtPlayerDropTarget(this)); MakeMenus(); Connect(m_payoffEditor->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(gbtEfgDisplay::OnAcceptPayoffEdit)); } void gbtEfgDisplay::MakeMenus(void) { m_nodeMenu = new wxMenu; m_nodeMenu->Append(wxID_UNDO, _("&Undo\tCtrl-Z"), _("Undo the last change")); m_nodeMenu->Append(wxID_REDO, _("&Redo\tCtrl-Y"), _("Redo the last undone change")); m_nodeMenu->AppendSeparator(); m_nodeMenu->Append(GBT_MENU_EDIT_INSERT_MOVE, _("&Insert move"), _("Insert a move")); m_nodeMenu->Append(GBT_MENU_EDIT_INSERT_ACTION, _("Insert &action"), _("Insert an action at the current move")); m_nodeMenu->Append(GBT_MENU_EDIT_REVEAL, _("&Reveal"), _("Reveal choice at node")); m_nodeMenu->AppendSeparator(); m_nodeMenu->Append(GBT_MENU_EDIT_DELETE_TREE, _("&Delete subtree"), _("Delete the subtree starting at the selected node")); m_nodeMenu->Append(GBT_MENU_EDIT_DELETE_PARENT, _("Delete &parent"), _("Delete the node directly before the selected node")); m_nodeMenu->Append(GBT_MENU_EDIT_REMOVE_OUTCOME, _("Remove &outcome"), _("Remove the outcome from the selected node")); m_nodeMenu->AppendSeparator(); m_nodeMenu->Append(GBT_MENU_EDIT_NODE, _("&Node properties"), _("Edit properties of the node")); m_nodeMenu->Append(GBT_MENU_EDIT_MOVE, _("&Move properties"), _("Edit properties of the move")); m_nodeMenu->AppendSeparator(); m_nodeMenu->Append(GBT_MENU_EDIT_GAME, _("&Game properties"), _("Edit properties of the game")); } //--------------------------------------------------------------------- // gbtEfgDisplay: Event-hook members //--------------------------------------------------------------------- static Gambit::GameNode PriorSameIset(const Gambit::GameNode &n) { Gambit::GameInfoset iset = n->GetInfoset(); if (!iset) return 0; for (int i = 1; i <= iset->NumMembers(); i++) if (iset->GetMember(i) == n) if (i > 1) return iset->GetMember(i-1); else return 0; return 0; } static Gambit::GameNode NextSameIset(const Gambit::GameNode &n) { Gambit::GameInfoset iset = n->GetInfoset(); if (!iset) return 0; for (int i = 1; i <= iset->NumMembers(); i++) if (iset->GetMember(i) == n) if (i < iset->NumMembers()) return iset->GetMember(i+1); else return 0; return 0; } // // OnKeyEvent -- handle keypress events // Currently we support the following keys: // left arrow: go to parent of current node // right arrow: go to first child of current node // up arrow: go to previous sibling of current node // down arrow: go to next sibling of current node // ALT-up: go to previous member of information set // ALT-down: go to next member of information set // space: ensure the selected node is visible // 'R', 'r': select the root node (and make it visible) // delete: delete the subtree rooted at current node // backspace: delete the parent of the current node // 'M', 'm': edit the move at the current node // 'N', 'n': edit the properties of the current node // escape: cancel edit of payoff // tab: accept edit of payoff, edit next payoff (if any) // void gbtEfgDisplay::OnKeyEvent(wxKeyEvent &p_event) { Gambit::GameNode selectNode = m_doc->GetSelectNode(); if (p_event.GetKeyCode() == 'R' || p_event.GetKeyCode() == 'r') { m_doc->SetSelectNode(m_doc->GetGame()->GetRoot()); EnsureNodeVisible(m_doc->GetSelectNode()); return; } if (m_payoffEditor->IsEditing()) { if (p_event.GetKeyCode() == WXK_ESCAPE) { m_payoffEditor->EndEdit(); return; } else if (p_event.GetKeyCode() == WXK_TAB) { m_payoffEditor->EndEdit(); Gambit::GameOutcome outcome = m_payoffEditor->GetOutcome(); int player = m_payoffEditor->GetPlayer(); try { outcome->SetPayoff(player, (const char *) m_payoffEditor->GetValue().mb_str()); } catch (ValueException &) { // For the moment, we will just silently discard edits which // give payoffs that are not valid numbers return; } // When we update views, the node entries get redone... Gambit::GameNode node = m_payoffEditor->GetEntry()->GetNode(); m_doc->UpdateViews(GBT_DOC_MODIFIED_PAYOFFS); // Payoff rectangles are actually set during drawing, so // force a refresh wxClientDC dc(this); PrepareDC(dc); OnDraw(dc); if (player < m_doc->NumPlayers()) { gbtNodeEntry *entry = m_layout.GetNodeEntry(node); wxRect rect = entry->GetPayoffExtent(player + 1); int xx, yy; CalcScrolledPosition((int) (.01 * (rect.x - 3) * m_zoom), (int) (.01 * (rect.y - 3) * m_zoom), &xx, &yy); int width = (int) (.01 * (rect.width + 10) * m_zoom); int height = (int) (.01 * (rect.height + 6) * m_zoom); m_payoffEditor->SetSize(xx, yy, width, height); m_payoffEditor->BeginEdit(entry, player + 1); } return; } } // After this point, all events involve moving relative to selected node. // So if there isn't a selected node, the event doesn't apply if (!selectNode) { p_event.Skip(); return; } switch (p_event.GetKeyCode()) { case 'M': case 'm': { wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, GBT_MENU_EDIT_MOVE); wxPostEvent(this, event); return; } case 'N': case 'n': { wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, GBT_MENU_EDIT_NODE); wxPostEvent(this, event); return; } case WXK_LEFT: if (selectNode->GetParent()) { m_doc->SetSelectNode(m_layout.GetValidParent(selectNode)->GetNode()); EnsureNodeVisible(m_doc->GetSelectNode()); } return; case WXK_RIGHT: if (m_layout.GetValidChild(selectNode)) { m_doc->SetSelectNode(m_layout.GetValidChild(selectNode)->GetNode()); EnsureNodeVisible(m_doc->GetSelectNode()); } return; case WXK_UP: { Gambit::GameNode prior = ((!p_event.AltDown()) ? m_layout.PriorSameLevel(selectNode) : PriorSameIset(selectNode)); if (prior) { m_doc->SetSelectNode(prior); EnsureNodeVisible(m_doc->GetSelectNode()); } return; } case WXK_DOWN: { Gambit::GameNode next = ((!p_event.AltDown()) ? m_layout.NextSameLevel(selectNode) : NextSameIset(selectNode)); if (next) { m_doc->SetSelectNode(next); EnsureNodeVisible(m_doc->GetSelectNode()); } return; } case WXK_SPACE: EnsureNodeVisible(m_doc->GetSelectNode()); return; case WXK_DELETE: { wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, GBT_MENU_EDIT_DELETE_TREE); wxPostEvent(this, event); return; } case WXK_BACK: { wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, GBT_MENU_EDIT_DELETE_PARENT); wxPostEvent(this, event); return; } default: // If nothing else applies, let event propagate p_event.Skip(); } } void gbtEfgDisplay::OnAcceptPayoffEdit(wxCommandEvent &) { m_payoffEditor->EndEdit(); Gambit::GameOutcome outcome = m_payoffEditor->GetOutcome(); int player = m_payoffEditor->GetPlayer(); try { outcome->SetPayoff(player, (const char *) m_payoffEditor->GetValue().mb_str()); } catch (ValueException &) { // For the moment, we will just silently discard edits which // give payoffs that are not valid numbers return; } m_doc->UpdateViews(GBT_DOC_MODIFIED_PAYOFFS); } //--------------------------------------------------------------------- // gbtEfgDisplay: Implementing gbtGameView members //--------------------------------------------------------------------- void gbtEfgDisplay::PostPendingChanges(void) { // FIXME: Save edit! m_payoffEditor->EndEdit(); } void gbtEfgDisplay::OnUpdate(void) { // First make sure that the selected node is in fact still valid if (m_doc->GetSelectNode()) { gbtNodeEntry *entry = m_layout.GetNodeEntry(m_doc->GetSelectNode()); if (!entry) { m_doc->SetSelectNode(0); } } // Force a rebuild on every change for now. RefreshTree(); Gambit::GameNode selectNode = m_doc->GetSelectNode(); m_nodeMenu->Enable(wxID_UNDO, m_doc->CanUndo()); m_nodeMenu->Enable(wxID_REDO, m_doc->CanRedo()); m_nodeMenu->Enable(GBT_MENU_EDIT_INSERT_MOVE, selectNode); m_nodeMenu->Enable(GBT_MENU_EDIT_INSERT_ACTION, selectNode && selectNode->GetInfoset()); m_nodeMenu->Enable(GBT_MENU_EDIT_REVEAL, selectNode && selectNode->GetInfoset()); m_nodeMenu->Enable(GBT_MENU_EDIT_DELETE_TREE, selectNode && selectNode->NumChildren() > 0); m_nodeMenu->Enable(GBT_MENU_EDIT_DELETE_PARENT, selectNode && selectNode->GetParent()); m_nodeMenu->Enable(GBT_MENU_EDIT_REMOVE_OUTCOME, selectNode && selectNode->GetOutcome()); m_nodeMenu->Enable(GBT_MENU_EDIT_NODE, selectNode); m_nodeMenu->Enable(GBT_MENU_EDIT_MOVE, selectNode && selectNode->GetInfoset()); } //--------------------------------------------------------------------- // gbtEfgDisplay: Drawing functions //--------------------------------------------------------------------- void gbtEfgDisplay::RefreshTree(void) { m_layout.BuildNodeList(m_doc->GetEfgSupport()); m_layout.Layout(m_doc->GetEfgSupport()); Refresh(); } void gbtEfgDisplay::AdjustScrollbarSteps(void) { int width, height; GetClientSize(&width, &height); int scrollX, scrollY; GetViewStart(&scrollX, &scrollY); SetScrollbars(50, 50, (int) (m_layout.MaxX() * (.01 * m_zoom) / 50 + 1), (int) (m_layout.MaxY() * (.01 * m_zoom) / 50 + 1), scrollX, scrollY); } void gbtEfgDisplay::FitZoom(void) { int width, height; GetClientSize(&width, &height); double zoomx = (double) width / (double) m_layout.MaxX(); double zoomy = (double) height / (double) m_layout.MaxY(); zoomx = Gambit::min(zoomx, 1.0); zoomy = Gambit::min(zoomy, 1.0); // never zoom in (only out) m_zoom = int(100.0 * (Gambit::min(zoomx, zoomy) * .9)); AdjustScrollbarSteps(); Refresh(); } void gbtEfgDisplay::SetZoom(int p_zoom) { m_zoom = p_zoom; AdjustScrollbarSteps(); EnsureNodeVisible(m_doc->GetSelectNode()); Refresh(); } void gbtEfgDisplay::OnDraw(wxDC &p_dc) { p_dc.SetUserScale(.01 * m_zoom, .01 * m_zoom); #if !wxCHECK_VERSION(2,7,0) p_dc.BeginDrawing(); #endif p_dc.Clear(); int maxX = m_layout.MaxX(); m_layout.Render(p_dc, false); #if !wxCHECK_VERSION(2,7,0) p_dc.EndDrawing(); #endif // When we draw, we might change the location of the right margin // (because of the outcome labels). Make sure scrollbars are adjusted // to reflect this. if (maxX != m_layout.MaxX()) { AdjustScrollbarSteps(); } } void gbtEfgDisplay::OnDraw(wxDC &p_dc, double p_zoom) { // Bit of a hack: this allows us to set zoom separately in printout code int saveZoom = m_zoom; m_zoom = int(100.0 * p_zoom); p_dc.SetUserScale(.01 * m_zoom, .01 * m_zoom); #if !wxCHECK_VERSION(2,7,0) p_dc.BeginDrawing(); #endif p_dc.Clear(); int maxX = m_layout.MaxX(); // A second hack: this is usually only called by functions for hardcopy // output (printouts or graphics images). We want to suppress the // use of the "hints" for these. // FIXME: Of course, this hack implies some useful refactor is called for! m_layout.Render(p_dc, true); #if !wxCHECK_VERSION(2,7,0) p_dc.EndDrawing(); #endif // When we draw, we might change the location of the right margin // (because of the outcome labels). Make sure scrollbars are adjusted // to reflect this. if (maxX != m_layout.MaxX()) { AdjustScrollbarSteps(); } m_zoom = saveZoom; } void gbtEfgDisplay::EnsureNodeVisible(Gambit::GameNode p_node) { if (!p_node) return; gbtNodeEntry *entry = m_layout.GetNodeEntry(p_node); int xScroll, yScroll; GetViewStart(&xScroll, &yScroll); int width, height; GetClientSize(&width, &height); int xx, yy; CalcScrolledPosition((int) (entry->X() * (.01 * m_zoom) - 20), (int) (entry->Y() * (.01 * m_zoom)), &xx, &yy); if (xx < 0) { xScroll -= -xx / 50 + 1; } CalcScrolledPosition((int) (entry->X() * (.01 * m_zoom)), (int) (entry->Y() * (.01 * m_zoom)), &xx, &yy); if (xx > width) { xScroll += (xx - width) / 50 + 1; } if (xScroll < 0) { xScroll = 0; } else if (xScroll > GetScrollRange(wxHORIZONTAL)) { xScroll = GetScrollRange(wxHORIZONTAL); } CalcScrolledPosition((int) (entry->X() * (.01 * m_zoom)), (int) (entry->Y() * (.01 * m_zoom) - 20), &xx, &yy); if (yy < 0) { yScroll -= -yy / 50 + 1; } CalcScrolledPosition((int) (entry->X() * (.01 * m_zoom)), (int) (entry->Y() * (.01 * m_zoom) + 20), &xx, &yy); if (yy > height) { yScroll += (yy - height) / 50 + 1; } if (yScroll < 0) { yScroll = 0; } else if (yScroll > GetScrollRange(wxVERTICAL)) { yScroll = GetScrollRange(wxVERTICAL); } Scroll(xScroll, yScroll); } // // Left mouse button click: // Without key modifiers, selects a node // With shift key, selects whole subtree (not yet implemented) // With control key, adds node to selection (not yet implemented) // void gbtEfgDisplay::OnLeftClick(wxMouseEvent &p_event) { int x, y; CalcUnscrolledPosition(p_event.GetX(), p_event.GetY(), &x, &y); x = (int) ((float) x / (.01 * m_zoom)); y = (int) ((float) y / (.01 * m_zoom)); Gambit::GameNode node = m_layout.NodeHitTest(x, y); if (node != m_doc->GetSelectNode()) { m_doc->SetSelectNode(node); } } // // Left mouse button double-click: // Sets selection, brings up node properties dialog // void gbtEfgDisplay::OnLeftDoubleClick(wxMouseEvent &p_event) { int x, y; CalcUnscrolledPosition(p_event.GetX(), p_event.GetY(), &x, &y); x = (int) ((float) x / (.01 * m_zoom)); y = (int) ((float) y / (.01 * m_zoom)); Gambit::GameNode node = m_layout.NodeHitTest(x, y); if (node) { m_doc->SetSelectNode(node); wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, GBT_MENU_EDIT_NODE); wxPostEvent(this, event); return; } node = m_layout.OutcomeHitTest(x, y); if (node) { if (!node->GetOutcome()) { // Create a new outcome node->SetOutcome(m_doc->GetGame()->NewOutcome()); m_doc->UpdateViews(GBT_DOC_MODIFIED_PAYOFFS); // Payoff rectangles are actually set during drawing, so // force a refresh wxClientDC dc(this); PrepareDC(dc); OnDraw(dc); gbtNodeEntry *entry = m_layout.GetNodeEntry(node); wxRect rect = entry->GetPayoffExtent(1); int xx, yy; CalcScrolledPosition((int) (.01 * (rect.x - 3) * m_zoom), (int) (.01 * (rect.y - 3) * m_zoom), &xx, &yy); int width = (int) (.01 * (rect.width + 10) * m_zoom); int height = (int) (.01 * (rect.height + 6) * m_zoom); m_payoffEditor->SetSize(xx, yy, width, height); m_payoffEditor->BeginEdit(entry, 1); return; } // Editing an existing outcome gbtNodeEntry *entry = m_layout.GetNodeEntry(node); for (int pl = 1; pl <= m_doc->NumPlayers(); pl++) { wxRect rect = entry->GetPayoffExtent(pl); #if wxCHECK_VERSION(2,7,0) if (rect.Contains(x, y)) { #else if (rect.Inside(x, y)) { #endif int xx, yy; CalcScrolledPosition((int) (.01 * (rect.x - 3) * m_zoom), (int) (.01 * (rect.y - 3) * m_zoom), &xx, &yy); int width = (int) (.01 * (rect.width + 10) * m_zoom); int height = (int) (.01 * (rect.height + 6) * m_zoom); m_payoffEditor->SetSize(xx, yy, width, height); m_payoffEditor->BeginEdit(entry, pl); return; } } return; } if (m_doc->GetStyle().BranchAboveLabel() == GBT_BRANCH_LABEL_LABEL) { node = m_layout.BranchAboveHitTest(x, y); if (node) { m_doc->SetSelectNode(node); wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, GBT_MENU_EDIT_MOVE); wxPostEvent(this, event); return; } } if (m_doc->GetStyle().BranchBelowLabel() == GBT_BRANCH_LABEL_LABEL) { node = m_layout.BranchBelowHitTest(x, y); if (node) { m_doc->SetSelectNode(node); wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, GBT_MENU_EDIT_MOVE); wxPostEvent(this, event); return; } } } #include "bitmaps/tree.xpm" #include "bitmaps/move.xpm" void gbtEfgDisplay::OnMouseMotion(wxMouseEvent &p_event) { if (p_event.LeftIsDown() && p_event.Dragging()) { int x, y; CalcUnscrolledPosition(p_event.GetX(), p_event.GetY(), &x, &y); x = (int) ((float) x / (.01 * GetZoom())); y = (int) ((float) y / (.01 * GetZoom())); Gambit::GameNode node = m_layout.NodeHitTest(x, y); if (node && node->NumChildren() > 0) { Gambit::GamePlayer player = node->GetPlayer(); wxString label; if (p_event.ShiftDown()) { label = wxT("i"); } else { label = wxString(player->GetLabel().c_str(), *wxConvCurrent); } if (p_event.ControlDown()) { // Copy subtree wxBitmap bitmap(tree_xpm); #if defined( __WXMSW__) or defined(__WXMAC__) wxImage image = bitmap.ConvertToImage(); #else wxIcon image; image.CopyFromBitmap(bitmap); #endif // _WXMSW__ wxTextDataObject textData(wxString::Format(wxT("C%d"), node->GetNumber())); wxDropSource source(textData, this, image, image, image); /*wxDragResult result =*/ source.DoDragDrop(true); } else if (p_event.ShiftDown()) { // Copy move (information set) // This should be the pawn icon! wxBitmap bitmap(move_xpm); #if defined( __WXMSW__) or defined(__WXMAC__) wxImage image = bitmap.ConvertToImage(); #else wxIcon image; image.CopyFromBitmap(bitmap); #endif // _WXMSW__ wxTextDataObject textData(wxString::Format(wxT("I%d"), node->GetNumber())); wxDropSource source(textData, this, image, image, image); /*wxDragResult result =*/ source.DoDragDrop(wxDrag_DefaultMove); } else { // Move subtree wxBitmap bitmap(tree_xpm); #if defined( __WXMSW__) or defined(__WXMAC__) wxImage image = bitmap.ConvertToImage(); #else wxIcon image; image.CopyFromBitmap(bitmap); #endif // _WXMSW__ wxTextDataObject textData(wxString::Format(wxT("M%d"), node->GetNumber())); wxDropSource source(textData, this, image, image, image); /*wxDragResult result =*/ source.DoDragDrop(wxDrag_DefaultMove); } return; } node = m_layout.OutcomeHitTest(x, y); if (node && node->GetOutcome()) { wxBitmap bitmap = MakeOutcomeBitmap(); #if defined( __WXMSW__) or defined(__WXMAC__) wxImage image = bitmap.ConvertToImage(); #else wxIcon image; image.CopyFromBitmap(bitmap); #endif // _WXMSW__ if (p_event.ControlDown()) { wxTextDataObject textData(wxString::Format(wxT("O%d"), node->GetNumber())); wxDropSource source(textData, this, image, image, image); /*wxDragResult result =*/ source.DoDragDrop(true); } else if (p_event.ShiftDown()) { wxTextDataObject textData(wxString::Format(wxT("p%d"), node->GetNumber())); wxDropSource source(textData, this, image, image, image); /*wxDragResult result =*/ source.DoDragDrop(true); } else { wxTextDataObject textData(wxString::Format(wxT("o%d"), node->GetNumber())); wxDropSource source(textData, this, image, image, image); /*wxDragResult result =*/ source.DoDragDrop(wxDrag_DefaultMove); } } } } // // Right mouse-button click: // Set selection, display context-sensitive popup menu // void gbtEfgDisplay::OnRightClick(wxMouseEvent &p_event) { int x, y; CalcUnscrolledPosition(p_event.GetX(), p_event.GetY(), &x, &y); x = (int) ((float) x / (.01 * m_zoom)); y = (int) ((float) y / (.01 * m_zoom)); Gambit::GameNode node = m_layout.NodeHitTest(x, y); if (node != m_doc->GetSelectNode()) { m_doc->SetSelectNode(node); } PopupMenu(m_nodeMenu); } gambit-0.2010.09.01/src/gui/efgdisplay.h0000644000076500007650000000524611435216101014314 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/efgdisplay.h // Declaration of window class to display extensive form tree // // 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 EFGDISPLAY_H #define EFGDISPLAY_H #include "gamedoc.h" #include "efglayout.h" class gbtPayoffEditor : public wxTextCtrl { private: gbtNodeEntry *m_entry; Gambit::GameOutcome m_outcome; int m_player; /// @name Event handlers //@{ void OnChar(wxKeyEvent &); //@} public: gbtPayoffEditor(wxWindow *p_parent); void BeginEdit(gbtNodeEntry *p_node, int p_player); void EndEdit(void); bool IsEditing(void) const { return IsShown(); } gbtNodeEntry *GetEntry(void) const { return m_entry; } Gambit::GameOutcome GetOutcome(void) const { return m_outcome; } int GetPlayer(void) const { return m_player; } DECLARE_EVENT_TABLE() }; class gbtEfgDisplay : public wxScrolledWindow, public gbtGameView { private: gbtTreeLayout m_layout; int m_zoom; wxMenu *m_nodeMenu; gbtPayoffEditor *m_payoffEditor; // Private Functions void MakeMenus(void); void AdjustScrollbarSteps(void); /// @name Event handlers //@{ void OnMouseMotion(wxMouseEvent &); void OnLeftClick(wxMouseEvent &); void OnRightClick(wxMouseEvent &); void OnLeftDoubleClick(wxMouseEvent &); void OnKeyEvent(wxKeyEvent &); /// Payoff editor changes accepted with enter void OnAcceptPayoffEdit(wxCommandEvent &); //@} /// @name Overriding gbtGameView members //@{ void OnUpdate(void); void PostPendingChanges(void); //@} void RefreshTree(void); public: gbtEfgDisplay(wxWindow *p_parent, gbtGameDocument *p_doc); virtual void OnDraw(wxDC &dc); void OnDraw(wxDC &, double); int GetZoom(void) const { return m_zoom; } void SetZoom(int p_zoom); void FitZoom(void); const gbtTreeLayout &GetLayout(void) const { return m_layout; } void EnsureNodeVisible(Gambit::GameNode); DECLARE_EVENT_TABLE() }; #endif // EFGDISPLAY_H gambit-0.2010.09.01/src/gui/efglayout.cc0000644000076500007650000007510611435216101014324 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/efglayout.cc // Implementation of tree layout representation // // 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 #include #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "libgambit/libgambit.h" #include "efgdisplay.h" //----------------------------------------------------------------------- // class gbtNodeEntry: Member functions //----------------------------------------------------------------------- gbtNodeEntry::gbtNodeEntry(Gambit::GameNode p_node) : m_node(p_node), m_parent(0), m_x(-1), m_y(-1), m_nextMember(0), m_inSupport(true), m_size(20), m_token(GBT_NODE_TOKEN_CIRCLE), m_branchStyle(GBT_BRANCH_STYLE_LINE), m_branchLabel(GBT_BRANCH_LABEL_HORIZONTAL), m_branchLength(0), m_sublevel(0), m_actionProb(0) { } int gbtNodeEntry::GetChildNumber(void) const { if (m_node->GetParent()) { return m_node->GetPriorAction()->GetNumber(); } else { return 0; } } // // Draws the node token itself, as well as the incoming branch // (if not the root node) // void gbtNodeEntry::Draw(wxDC &p_dc, Gambit::GameNode p_selection, bool p_noHints) const { if (m_node->GetParent() && m_inSupport) { DrawIncomingBranch(p_dc); } else { m_branchAboveRect = wxRect(); m_branchBelowRect = wxRect(); } p_dc.SetPen(*wxThePenList->FindOrCreatePen(m_color, (p_selection == m_node) ? 6 : 3, wxSOLID)); p_dc.SetTextForeground(m_color); if (m_token == GBT_NODE_TOKEN_LINE) { p_dc.DrawLine(m_x, m_y, m_x + m_size, m_y); if (m_branchStyle == GBT_BRANCH_STYLE_FORKTINE) { // "classic" Gambit style: draw a small 'token' to separate // the fork from the node p_dc.DrawEllipse(m_x - 1, m_y - 1, 3, 3); } } else if (m_token == GBT_NODE_TOKEN_BOX) { p_dc.SetBrush(*wxWHITE_BRUSH); p_dc.DrawRectangle(m_x, m_y - m_size / 2, m_size, m_size); } else if (m_token == GBT_NODE_TOKEN_DIAMOND) { wxPoint points[4] = { wxPoint(m_x + m_size / 2, m_y - m_size / 2), wxPoint(m_x, m_y), wxPoint(m_x + m_size / 2, m_y + m_size / 2), wxPoint(m_x + m_size, m_y) }; p_dc.SetBrush(*wxWHITE_BRUSH); p_dc.DrawPolygon(4, points); } else if (m_token == GBT_NODE_TOKEN_DOT) { p_dc.SetBrush(wxBrush(m_color, wxSOLID)); p_dc.DrawEllipse(m_x, m_y - m_size / 2, m_size, m_size); } else { // Default: draw circles p_dc.SetBrush(*wxWHITE_BRUSH); p_dc.DrawEllipse(m_x, m_y - m_size / 2, m_size, m_size); } int textWidth, textHeight; p_dc.SetFont(m_nodeAboveFont); p_dc.GetTextExtent(m_nodeAboveLabel, &textWidth, &textHeight); p_dc.DrawText(m_nodeAboveLabel, m_x + (m_size - textWidth) / 2, m_y - textHeight - 9); p_dc.SetFont(m_nodeBelowFont); p_dc.GetTextExtent(m_nodeBelowLabel, &textWidth, &textHeight); p_dc.DrawText(m_nodeBelowLabel, m_x + (m_size - textWidth) / 2, m_y + 9); p_dc.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); DrawOutcome(p_dc, p_noHints); } void gbtNodeEntry::DrawIncomingBranch(wxDC &p_dc) const { int xStart = m_parent->m_x + m_parent->m_size; int xEnd = m_x; int yStart = m_parent->m_y; int yEnd = m_y; p_dc.SetPen(*wxThePenList->FindOrCreatePen(m_parent->m_color, 4, wxSOLID)); p_dc.SetTextForeground(m_parent->m_color); if (m_branchStyle == GBT_BRANCH_STYLE_LINE) { p_dc.DrawLine(xStart, yStart, xEnd, yEnd); // Draw in the highlight indicating action probabilities if (m_actionProb >= Gambit::Rational(0)) { p_dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4, wxSOLID)); p_dc.DrawLine(xStart, yStart, xStart + (int) ((double) (xEnd - xStart) * (double) m_actionProb), yStart + (int) ((double) (yEnd - yStart) * (double) m_actionProb)); } int textWidth, textHeight; p_dc.SetFont(m_branchAboveFont); p_dc.GetTextExtent(m_branchAboveLabel, &textWidth, &textHeight); // The angle of the branch double theta = -atan((double) (yEnd - yStart) / (double) (xEnd - xStart)); // The "centerpoint" of the branch int xbar = (xStart + xEnd) / 2; int ybar = (yStart + yEnd) / 2; if (m_branchLabel == GBT_BRANCH_LABEL_HORIZONTAL) { if (yStart >= yEnd) { p_dc.DrawText(m_branchAboveLabel, xbar - textWidth / 2, ybar - textHeight + textWidth / 2 * (yEnd - yStart) / (xEnd - xStart)); m_branchAboveRect = wxRect(xbar - textWidth / 2, ybar - textHeight + textWidth / 2 * (yEnd - yStart) / (xEnd - xStart), textWidth, textHeight); } else { p_dc.DrawText(m_branchAboveLabel, xbar - textWidth / 2, ybar - textHeight - textWidth / 2 * (yEnd - yStart) / (xEnd - xStart)); m_branchAboveRect = wxRect(xbar - textWidth / 2, ybar - textHeight - textWidth / 2 * (yEnd - yStart) / (xEnd - xStart), textWidth, textHeight); } } else { // Draw the text rotated appropriately p_dc.DrawRotatedText(m_branchAboveLabel, (int) ((double) xbar - (double) textHeight * sin(theta) - (double) textWidth * cos(theta) / 2.0), (int) ((double) ybar - (double) textHeight * cos(theta) + (double) textWidth * sin(theta) / 2.0), theta * 180.0 / 3.14159); m_branchAboveRect = wxRect(); } p_dc.SetFont(m_branchBelowFont); p_dc.GetTextExtent(m_branchBelowLabel, &textWidth, &textHeight); if (m_branchLabel == GBT_BRANCH_LABEL_HORIZONTAL) { if (yStart >= yEnd) { p_dc.DrawText(m_branchBelowLabel, xbar - textWidth / 2, ybar - textWidth/2 * (yEnd - yStart) / (xEnd - xStart)); m_branchBelowRect = wxRect(xbar - textWidth / 2, ybar - textWidth/2 * (yEnd - yStart) / (xEnd - xStart), textWidth, textHeight); } else { p_dc.DrawText(m_branchBelowLabel, xbar - textWidth / 2, ybar + textWidth/2 * (yEnd - yStart) / (xEnd - xStart)); m_branchBelowRect = wxRect(xbar - textWidth / 2, ybar + textWidth/2 * (yEnd - yStart) / (xEnd - xStart), textWidth, textHeight); } } else { // Draw the text rotated appropriately p_dc.DrawRotatedText(m_branchBelowLabel, (int) ((double) xbar - (double) textWidth * cos(theta) / 2.0), (int) ((double) ybar + (double) textWidth * sin(theta) / 2.0), theta * 180.0 / 3.14159); m_branchBelowRect = wxRect(); } } else { // Old style fork-tine p_dc.DrawLine(xStart, yStart, xStart + m_branchLength, yEnd); p_dc.DrawLine(xStart + m_branchLength, yEnd, xEnd, yEnd); // Draw in the highlight indicating action probabilities if (m_actionProb >= Gambit::Rational(0)) { p_dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 2, wxSOLID)); p_dc.DrawLine(xStart, yStart, xStart + (int) ((double) m_branchLength * (double) m_actionProb), yStart + (int) ((double) (yEnd - yStart) * (double) m_actionProb)); } int textWidth, textHeight; p_dc.SetFont(m_branchAboveFont); p_dc.GetTextExtent(m_branchAboveLabel, &textWidth, &textHeight); p_dc.DrawText(m_branchAboveLabel, xStart + m_branchLength + 3, yEnd - textHeight - 3); m_branchAboveRect = wxRect(xStart + m_branchLength + 3, yEnd - textHeight - 3, textWidth, textHeight); p_dc.SetFont(m_branchBelowFont); p_dc.GetTextExtent(m_branchBelowLabel, &textWidth, &textHeight); p_dc.DrawText(m_branchBelowLabel, xStart + m_branchLength + 3, yEnd + 3); m_branchBelowRect = wxRect(xStart + m_branchLength + 3, yEnd + +3, textWidth, textHeight); } } static wxPoint DrawFraction(wxDC &p_dc, wxPoint p_point, const Gambit::Rational &p_value) { p_dc.SetFont(wxFont(7, wxSWISS, wxNORMAL, wxBOLD)); int numWidth, numHeight; wxString num = wxString(ToText(p_value.numerator()).c_str(), *wxConvCurrent); p_dc.GetTextExtent(num, &numWidth, &numHeight); int denWidth, denHeight; wxString den = wxString(ToText(p_value.denominator()).c_str(), *wxConvCurrent); p_dc.GetTextExtent(den, &denWidth, &denHeight); int width = ((numWidth > denWidth) ? numWidth : denWidth); p_dc.DrawLine(p_point.x, p_point.y, p_point.x + width + 4, p_point.y); p_dc.DrawText(num, p_point.x + 2 + (width - numWidth) / 2, p_point.y - 2 - numHeight); p_dc.DrawText(den, p_point.x + 2 + (width - denWidth) / 2, p_point.y + 2); p_point.x += width + 14; return p_point; } void gbtNodeEntry::DrawOutcome(wxDC &p_dc, bool p_noHints) const { wxPoint point(m_x + m_size + 20, m_y); Gambit::GameOutcome outcome = m_node->GetOutcome(); if (!outcome) { if (p_noHints) return; int width, height; p_dc.SetFont(wxFont(9, wxSWISS, wxITALIC, wxBOLD)); p_dc.SetTextForeground(*wxLIGHT_GREY); p_dc.GetTextExtent(wxT("(u)"), &width, &height); p_dc.DrawText(wxT("(u)"), point.x, point.y - height / 2); m_outcomeRect = wxRect(point.x, point.y - height / 2, width, height); m_payoffRect = Gambit::Array(); return; } int width, height = 25; m_payoffRect = Gambit::Array(); for (int pl = 1; pl <= m_node->GetGame()->NumPlayers(); pl++) { Gambit::GamePlayer player = m_node->GetGame()->GetPlayer(pl); p_dc.SetTextForeground(m_style->GetPlayerColor(pl)); std::string payoff = outcome->GetPayoff(pl); if (payoff.find('/') != (unsigned int) -1) { p_dc.SetPen(wxPen(m_style->GetPlayerColor(pl), 1, wxSOLID)); int oldX = point.x; point = DrawFraction(p_dc, point, outcome->GetPayoff(pl)); m_payoffRect.Append(wxRect(oldX - 5, point.y - height / 2, point.x - oldX + 10, height)); } else { wxString label = wxString(payoff.c_str(), *wxConvCurrent); p_dc.SetFont(wxFont(9, wxSWISS, wxNORMAL, wxBOLD)); p_dc.GetTextExtent(label, &width, &height); p_dc.DrawText(label, point.x, point.y - height / 2); m_payoffRect.Append(wxRect(point.x - 5, point.y - height / 2, width + 10, height)); point.x += width + 10; } } if (height == 0) { // Happens if all payoffs are fractional height = 25; } m_outcomeRect = wxRect(m_x + m_size + 20, m_y - height / 2, point.x - (m_x + m_size + 20), height); } bool gbtNodeEntry::NodeHitTest(int p_x, int p_y) const { if (p_x < m_x || p_x >= m_x + m_size) { return false; } if (m_token == GBT_NODE_TOKEN_LINE) { const int DELTA = 8; // a fudge factor for "almost" hitting the node return (p_y >= m_y - DELTA && p_y <= m_y + DELTA); } else { return (p_y >= m_y - m_size / 2 && p_y <= m_y + m_size / 2); } } //----------------------------------------------------------------------- // class gbtTreeLayout: Member functions //----------------------------------------------------------------------- gbtTreeLayout::gbtTreeLayout(gbtEfgDisplay *p_parent, gbtGameDocument *p_doc) : gbtGameView(p_doc), m_parent(p_parent), m_infosetSpacing(40), c_leftMargin(20), c_topMargin(40) { } Gambit::GameNode gbtTreeLayout::NodeHitTest(int p_x, int p_y) const { for (int i = 1; i <= m_nodeList.Length(); i++) { if (m_nodeList[i]->NodeHitTest(p_x, p_y)) { return m_nodeList[i]->GetNode(); } } return 0; } Gambit::GameNode gbtTreeLayout::OutcomeHitTest(int p_x, int p_y) const { for (int i = 1; i <= m_nodeList.Length(); i++) { if (m_nodeList[i]->OutcomeHitTest(p_x, p_y)) { return m_nodeList[i]->GetNode(); } } return 0; } Gambit::GameNode gbtTreeLayout::BranchAboveHitTest(int p_x, int p_y) const { for (int i = 1; i <= m_nodeList.Length(); i++) { if (m_nodeList[i]->BranchAboveHitTest(p_x, p_y)) { return m_nodeList[i]->GetNode()->GetParent(); } } return 0; } Gambit::GameNode gbtTreeLayout::BranchBelowHitTest(int p_x, int p_y) const { for (int i = 1; i <= m_nodeList.Length(); i++) { if (m_nodeList[i]->BranchAboveHitTest(p_x, p_y)) { return m_nodeList[i]->GetNode()->GetParent(); } } return 0; } Gambit::GameNode gbtTreeLayout::InfosetHitTest(int p_x, int p_y) const { for (int i = 1; i <= m_nodeList.Length(); i++) { gbtNodeEntry *entry = m_nodeList[i]; if (entry->GetNextMember() && entry->GetNode()->GetInfoset()) { if (p_x > entry->X() + entry->GetSublevel() * m_infosetSpacing - 2 && p_x < entry->X() + entry->GetSublevel() * m_infosetSpacing + 2) { if (p_y > entry->Y() && p_y < entry->GetNextMember()->Y()) { // next iset is below this one return entry->GetNode(); } else if (p_y > entry->GetNextMember()->Y() && p_y < entry->Y()) { // next iset is above this one return entry->GetNode(); } } } } return 0; } wxString gbtTreeLayout::CreateNodeLabel(const gbtNodeEntry *p_entry, int p_which) const { Gambit::GameNode n = p_entry->GetNode(); try { switch (p_which) { case GBT_NODE_LABEL_NOTHING: return wxT(""); case GBT_NODE_LABEL_LABEL: return wxString(n->GetLabel().c_str(), *wxConvCurrent); case GBT_NODE_LABEL_PLAYER: if (n->GetPlayer()) { return wxString(n->GetPlayer()->GetLabel().c_str(), *wxConvCurrent); } else { return wxT(""); } case GBT_NODE_LABEL_ISETLABEL: if (n->GetInfoset()) { return wxString(n->GetInfoset()->GetLabel().c_str(), *wxConvCurrent); } else { return wxT(""); } case GBT_NODE_LABEL_ISETID: if (n->GetInfoset()) { if (n->GetInfoset()->IsChanceInfoset()) { return wxString::Format(wxT("C:%d"), n->GetInfoset()->GetNumber()); } else { return wxString::Format(wxT("%d:%d"), n->GetPlayer()->GetNumber(), n->GetInfoset()->GetNumber()); } } else { return _T(""); } case GBT_NODE_LABEL_REALIZPROB: return wxString(m_doc->GetProfiles().GetRealizProb(n).c_str(), *wxConvCurrent); case GBT_NODE_LABEL_BELIEFPROB: return wxString(m_doc->GetProfiles().GetBeliefProb(n).c_str(), *wxConvCurrent); case GBT_NODE_LABEL_VALUE: if (n->GetInfoset() && n->GetPlayer()->GetNumber() > 0) { return wxString(m_doc->GetProfiles().GetNodeValue(n, n->GetPlayer()->GetNumber()).c_str(), *wxConvCurrent); } else { return wxT(""); } default: return wxT(""); } } catch (...) { return wxT(""); } } wxString gbtTreeLayout::CreateBranchLabel(const gbtNodeEntry *p_entry, int p_which) const { Gambit::GameNode parent = p_entry->GetParent()->GetNode(); try { switch (p_which) { case GBT_BRANCH_LABEL_NOTHING: return wxT(""); case GBT_BRANCH_LABEL_LABEL: return wxString(parent->GetInfoset()->GetAction(p_entry->GetChildNumber())->GetLabel().c_str(), *wxConvCurrent); case GBT_BRANCH_LABEL_PROBS: if (parent->GetPlayer() && parent->GetPlayer()->IsChance()) { return wxString(parent->GetInfoset()->GetActionProb(p_entry->GetChildNumber()).c_str(), *wxConvCurrent); } else if (m_doc->NumProfileLists() == 0) { return wxT(""); } else { return wxString(m_doc->GetProfiles().GetActionProb(parent, p_entry->GetChildNumber()).c_str(), *wxConvCurrent); } case GBT_BRANCH_LABEL_VALUE: if (m_doc->NumProfileLists() == 0) { return wxT(""); } else { return wxString(m_doc->GetProfiles().GetActionValue(parent, p_entry->GetChildNumber()).c_str(), *wxConvCurrent); } default: return wxT(""); } } catch (...) { return wxT(""); } } gbtNodeEntry *gbtTreeLayout::GetValidParent(Gambit::GameNode e) { gbtNodeEntry *n = GetNodeEntry(e->GetParent()); if (n) { return n; } else { return GetValidParent(e->GetParent()); } } gbtNodeEntry *gbtTreeLayout::GetValidChild(Gambit::GameNode e) { for (int i = 1; i <= e->NumChildren(); i++) { gbtNodeEntry *n = GetNodeEntry(e->GetChild(i)); if (n) { return n; } else { n = GetValidChild(e->GetChild(i)); if (n) return n; } } return 0; } gbtNodeEntry *gbtTreeLayout::GetEntry(Gambit::GameNode p_node) const { for (int i = 1; i <= m_nodeList.Length(); i++) { if (m_nodeList[i]->GetNode() == p_node) { return m_nodeList[i]; } } return 0; } Gambit::GameNode gbtTreeLayout::PriorSameLevel(Gambit::GameNode p_node) const { gbtNodeEntry *entry = GetEntry(p_node); if (entry) { for (int i = m_nodeList.Find(entry) - 1; i >= 1; i--) { if (m_nodeList[i]->GetLevel() == entry->GetLevel()) return m_nodeList[i]->GetNode(); } } return 0; } Gambit::GameNode gbtTreeLayout::NextSameLevel(Gambit::GameNode p_node) const { gbtNodeEntry *entry = GetEntry(p_node); if (entry) { for (int i = m_nodeList.Find(entry) + 1; i <= m_nodeList.Length(); i++) { if (m_nodeList[i]->GetLevel() == entry->GetLevel()) { return m_nodeList[i]->GetNode(); } } } return 0; } int gbtTreeLayout::LayoutSubtree(Gambit::GameNode p_node, const Gambit::BehavSupport &p_support, int &p_maxy, int &p_miny, int &p_ycoord) { int y1 = -1, yn = 0; const gbtStyle &settings = m_doc->GetStyle(); gbtNodeEntry *entry = GetEntry(p_node); entry->SetNextMember(0); if (m_doc->GetStyle().RootReachable() && p_node->GetInfoset() && !p_node->GetInfoset()->GetPlayer()->IsChance()) { Gambit::GameInfoset infoset = p_node->GetInfoset(); for (int i = 1; i <= p_support.NumActions(infoset); i++) { yn = LayoutSubtree(p_node->GetChild(p_support.GetAction(infoset, i)->GetNumber()), p_support, p_maxy, p_miny, p_ycoord); if (y1 == -1) { y1 = yn; } } entry->SetY((y1 + yn) / 2); } else { if (p_node->NumChildren() > 0) { for (int i = 1; i <= p_node->NumChildren(); i++) { yn = LayoutSubtree(p_node->GetChild(i), p_support, p_maxy, p_miny, p_ycoord); if (y1 == -1) { y1 = yn; } if (!p_node->GetPlayer()->IsChance() && !p_support.Contains(p_node->GetInfoset()->GetAction(i))) { m_nodeList[p_node->GetChild(i)->GetNumber()]->SetInSupport(false); } } entry->SetY((y1 + yn) / 2); } else { entry->SetY(p_ycoord); p_ycoord += settings.TerminalSpacing(); } } if (settings.BranchStyle() == GBT_BRANCH_STYLE_LINE) { entry->SetX(c_leftMargin + entry->GetLevel() * (settings.NodeSize() + settings.BranchLength())); } else { entry->SetX(c_leftMargin + entry->GetLevel() * (settings.NodeSize() + settings.BranchLength() + settings.TineLength())); } if (p_node->GetPlayer() && p_node->GetPlayer()->IsChance()) { entry->SetColor(settings.ChanceColor()); entry->SetToken(settings.ChanceToken()); } else if (p_node->GetPlayer()) { entry->SetColor(settings.GetPlayerColor(p_node->GetPlayer()->GetNumber())); entry->SetToken(settings.PlayerToken()); } else { entry->SetColor(settings.TerminalColor()); entry->SetToken(settings.TerminalToken()); } entry->SetSize(settings.NodeSize()); entry->SetBranchStyle(settings.BranchStyle()); if (settings.BranchStyle() == GBT_BRANCH_STYLE_LINE) { entry->SetBranchLabelStyle(settings.BranchLabels()); } entry->SetBranchLength(settings.BranchLength()); p_maxy = Gambit::max(entry->Y(), p_maxy); p_miny = Gambit::min(entry->Y(), p_miny); return entry->Y(); } // // Checks if there are any nodes in the same infoset as e that are either // on the same level (if SHOWISET_SAME) or on any level (if SHOWISET_ALL) // gbtNodeEntry *gbtTreeLayout::NextInfoset(gbtNodeEntry *e) { const gbtStyle &draw_settings = m_doc->GetStyle(); for (int pos = m_nodeList.Find(e) + 1; pos <= m_nodeList.Length(); pos++) { gbtNodeEntry *e1 = m_nodeList[pos]; // infosets are the same and the nodes are on the same level if (e->GetNode()->GetInfoset() == e1->GetNode()->GetInfoset()) { if (draw_settings.InfosetConnect() == GBT_INFOSET_CONNECT_ALL) { return e1; } else if (e->GetLevel() == e1->GetLevel()) { return e1; } } } return 0; } // // CheckInfosetEntry. Checks how many infoset lines are to be drawn at each // level, spaces them by setting each infoset's node's num to the previous // infoset node+1. Also lengthens the nodes by the amount of space taken up // by the infoset lines. // void gbtTreeLayout::CheckInfosetEntry(gbtNodeEntry *e) { int pos; gbtNodeEntry *infoset_entry, *e1; // Check if the infoset this entry belongs to (on this level) has already // been processed. If so, make this entry->num the same as the one already // processed and return infoset_entry = NextInfoset(e); for (pos = 1; pos <= m_nodeList.Length(); pos++) { e1 = m_nodeList[pos]; // if the infosets are the same and they are on the same level and e1 has been processed if (e->GetNode()->GetInfoset() == e1->GetNode()->GetInfoset() && e->GetLevel() == e1->GetLevel() && e1->GetSublevel() > 0) { e->SetSublevel(e1->GetSublevel()); if (infoset_entry) { e->SetNextMember(infoset_entry); } return; } } // If we got here, this entry does not belong to any processed infoset yet. // Check if it belongs to ANY infoset, if not just return if (!infoset_entry) return; // If we got here, then this entry is new and is connected to other entries // find the entry on the same level with the maximum num. // This entry will have num = num+1. int num = 0; for (pos = 1; pos <= m_nodeList.Length(); pos++) { e1 = m_nodeList[pos]; // Find the max num for this level if (e->GetLevel() == e1->GetLevel()) { num = Gambit::max(e1->GetSublevel(), num); } } num++; e->SetSublevel(num); e->SetNextMember(infoset_entry); } void gbtTreeLayout::FillInfosetTable(Gambit::GameNode n, const Gambit::BehavSupport &cur_sup) { const gbtStyle &draw_settings = m_doc->GetStyle(); gbtNodeEntry *entry = GetNodeEntry(n); if (n->NumChildren() > 0) { for (int i = 1; i <= n->NumChildren(); i++) { bool in_sup = true; if (n->GetPlayer()->GetNumber()) { in_sup = cur_sup.Contains(n->GetInfoset()->GetAction(i)); } if (in_sup || !draw_settings.RootReachable()) { FillInfosetTable(n->GetChild(i), cur_sup); } } } if (entry) { CheckInfosetEntry(entry); } } void gbtTreeLayout::UpdateTableInfosets(void) { // Note that levels are numbered from 0, not 1. // create an array to hold max num for each level Gambit::Array nums(0, m_maxLevel + 1); for (int i = 0; i <= m_maxLevel + 1; nums[i++] = 0); // find the max e->num for each level for (int pos = 1; pos <= m_nodeList.Length(); pos++) { gbtNodeEntry *entry = m_nodeList[pos]; nums[entry->GetLevel()] = Gambit::max(entry->GetSublevel() + 1, nums[entry->GetLevel()]); } for (int i = 0; i <= m_maxLevel; i++) { nums[i+1] += nums[i]; } // now add the needed length to each level, and set maxX accordingly m_maxX = 0; for (int pos = 1; pos <= m_nodeList.Length(); pos++) { gbtNodeEntry *entry = m_nodeList[pos]; if (entry->GetLevel() != 0) { entry->SetX(entry->X() + (nums[entry->GetLevel()-1] + entry->GetSublevel()) * m_infosetSpacing); } m_maxX = Gambit::max(m_maxX, entry->X() + entry->GetSize()); } } void gbtTreeLayout::UpdateTableParents(void) { for (int pos = 1; pos <= m_nodeList.Length(); pos++) { gbtNodeEntry *e = m_nodeList[pos]; e->SetParent((e->GetNode() == m_doc->GetGame()->GetRoot()) ? e : GetValidParent(e->GetNode())); } } void gbtTreeLayout::Layout(const Gambit::BehavSupport &p_support) { // Kinda kludgey; probably should query draw settings whenever needed. m_infosetSpacing = (m_doc->GetStyle().InfosetJoin() == GBT_INFOSET_JOIN_LINES) ? 10 : 40; if (m_nodeList.Length() != m_doc->GetGame()->NumNodes()) { // A rebuild is in order; force it BuildNodeList(p_support); } int miny = 0, maxy = 0, ycoord = c_topMargin; LayoutSubtree(m_doc->GetGame()->GetRoot(), p_support, maxy, miny, ycoord); const gbtStyle &draw_settings = m_doc->GetStyle(); if (draw_settings.InfosetConnect() != GBT_INFOSET_CONNECT_NONE) { // FIXME! This causes lines to disappear... sometimes. FillInfosetTable(m_doc->GetGame()->GetRoot(), p_support); UpdateTableInfosets(); } UpdateTableParents(); GenerateLabels(); m_maxY = maxy + 25; } void gbtTreeLayout::BuildNodeList(Gambit::GameNode p_node, const Gambit::BehavSupport &p_support, int p_level) { gbtNodeEntry *entry = new gbtNodeEntry(p_node); entry->SetStyle(&m_doc->GetStyle()); m_nodeList.Append(entry); entry->SetLevel(p_level); if (m_doc->GetStyle().RootReachable()) { Gambit::GameInfoset infoset = p_node->GetInfoset(); if (infoset) { if (infoset->GetPlayer()->IsChance()) { for (int i = 1; i <= p_node->NumChildren(); i++) { BuildNodeList(p_node->GetChild(i), p_support, p_level + 1); } } else { for (int i = 1; i <= p_support.NumActions(infoset); i++) { BuildNodeList(p_node->GetChild(p_support.GetAction(infoset, i)->GetNumber()), p_support, p_level + 1); } } } } else { for (int i = 1; i <= p_node->NumChildren(); i++) { BuildNodeList(p_node->GetChild(i), p_support, p_level + 1); } } m_maxLevel = Gambit::max(p_level, m_maxLevel); } void gbtTreeLayout::BuildNodeList(const Gambit::BehavSupport &p_support) { while (m_nodeList.Length() > 0) { delete m_nodeList.Remove(1); } m_maxLevel = 0; BuildNodeList(m_doc->GetGame()->GetRoot(), p_support, 0); } void gbtTreeLayout::GenerateLabels(void) { const gbtStyle &settings = m_doc->GetStyle(); for (int i = 1; i <= m_nodeList.Length(); i++) { gbtNodeEntry *entry = m_nodeList[i]; entry->SetNodeAboveLabel(CreateNodeLabel(entry, settings.NodeAboveLabel())); entry->SetNodeAboveFont(settings.GetFont()); entry->SetNodeBelowLabel(CreateNodeLabel(entry, settings.NodeBelowLabel())); entry->SetNodeBelowFont(settings.GetFont()); if (entry->GetChildNumber() > 0) { entry->SetBranchAboveLabel(CreateBranchLabel(entry, settings.BranchAboveLabel())); entry->SetBranchAboveFont(settings.GetFont()); entry->SetBranchBelowLabel(CreateBranchLabel(entry, settings.BranchBelowLabel())); entry->SetBranchBelowFont(settings.GetFont()); Gambit::GameNode parent = entry->GetNode()->GetParent(); if (parent->GetPlayer()->IsChance()) { entry->SetActionProb(parent->GetInfoset()->GetActionProb(entry->GetChildNumber())); } else { int profile = m_doc->GetCurrentProfile(); if (profile > 0) { try { entry->SetActionProb((double) Gambit::ToNumber(m_doc->GetProfiles().GetActionProb(parent, entry->GetChildNumber()))); } catch (ValueException &) { // This occurs when the probability is undefined entry->SetActionProb(0.0); } } } } } } // // RenderSubtree: Render branches and labels // // The following speed optimizations have been added: // The algorithm now traverses the tree as a linear linked list, eliminating // expensive searches. // // There was some clipping code in here, but it didn't correctly // deal with drawing information sets while scrolling. So, the code // has temporarily been removed. It remains to be seen whether // performance will require a more sophisticated solution to the // problem. (TLT 5/2001) // void gbtTreeLayout::RenderSubtree(wxDC &p_dc, bool p_noHints) const { const gbtStyle &settings = m_doc->GetStyle(); for (int pos = 1; pos <= m_nodeList.Length(); pos++) { gbtNodeEntry *entry = m_nodeList[pos]; gbtNodeEntry *parentEntry = entry->GetParent(); if (entry->GetChildNumber() == 1) { parentEntry->Draw(p_dc, m_doc->GetSelectNode(), p_noHints); if (m_doc->GetStyle().InfosetConnect() != GBT_INFOSET_CONNECT_NONE && parentEntry->GetNextMember()) { int nextX = parentEntry->GetNextMember()->X(); int nextY = parentEntry->GetNextMember()->Y(); if ((m_doc->GetStyle().InfosetConnect() != GBT_INFOSET_CONNECT_SAMELEVEL) || parentEntry->X() == nextX) { #ifdef __WXGTK__ // A problem with using styled pens and user scaling on wxGTK p_dc.SetPen(wxPen(parentEntry->GetColor(), 1, wxSOLID)); #else p_dc.SetPen(wxPen(parentEntry->GetColor(), 1, wxDOT)); #endif // __WXGTK__ p_dc.DrawLine(parentEntry->X(), parentEntry->Y(), parentEntry->X(), nextY); if (settings.InfosetJoin() == GBT_INFOSET_JOIN_CIRCLES) { p_dc.DrawLine(parentEntry->X() + parentEntry->GetSize(), parentEntry->Y(), parentEntry->X() + parentEntry->GetSize(), nextY); } if (parentEntry->GetNextMember()->X() != parentEntry->X()) { // Draw a little arrow in the direction of the iset. int startX, endX; if (settings.InfosetJoin() == GBT_INFOSET_JOIN_LINES) { startX = parentEntry->X(); endX = (startX + m_infosetSpacing * ((parentEntry->GetNextMember()->X() > parentEntry->X()) ? 1 : -1)); } else { if (parentEntry->GetNextMember()->X() < parentEntry->X()) { // information set is continued to the left startX = parentEntry->X() + parentEntry->GetSize(); endX = parentEntry->X() - m_infosetSpacing; } else { // information set is continued to the right startX = parentEntry->X(); endX = (parentEntry->X() + parentEntry->GetSize() + m_infosetSpacing); } } p_dc.DrawLine(startX, nextY, endX, nextY); if (startX > endX) { p_dc.DrawLine(endX, nextY, endX + m_infosetSpacing / 2, nextY + m_infosetSpacing / 2); p_dc.DrawLine(endX, nextY, endX + m_infosetSpacing / 2, nextY - m_infosetSpacing / 2); } else { p_dc.DrawLine(endX, nextY, endX - m_infosetSpacing / 2, nextY + m_infosetSpacing / 2); p_dc.DrawLine(endX, nextY, endX - m_infosetSpacing / 2, nextY - m_infosetSpacing / 2); } } } } } if (entry->GetNode()->NumChildren() == 0) { entry->Draw(p_dc, m_doc->GetSelectNode(), p_noHints); } // As we draw, we determine the outcome label extents. Adjust the // overall size of the plot accordingly. if (entry->GetOutcomeExtent().GetRight() > m_maxX) { m_maxX = entry->GetOutcomeExtent().GetRight(); } } } void gbtTreeLayout::Render(wxDC &p_dc, bool p_noHints) const { RenderSubtree(p_dc, p_noHints); } gambit-0.2010.09.01/src/gui/efglayout.h0000644000076500007650000002011111435216101014150 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/efglayout.h // Interface to tree layout representation // // 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 EFGLAYOUT_H #define EFGLAYOUT_H #include "libgambit/libgambit.h" #include "style.h" #include "gamedoc.h" class gbtNodeEntry { private: Gambit::GameNode m_node; // the corresponding node in the game gbtNodeEntry *m_parent; // parent node int m_x, m_y; // Cartesian coordinates of node gbtNodeEntry *m_nextMember; // entry of next information set member bool m_inSupport; // true if node reachable in current support int m_size; // horizontal size of the node mutable wxRect m_outcomeRect; mutable Gambit::Array m_payoffRect; mutable wxRect m_branchAboveRect, m_branchBelowRect; int m_token; // token to draw for node wxColour m_color; // color of node int m_branchStyle; // lines or fork-tine int m_branchLabel; // horizontal or rotated int m_branchLength; // length of branch (exclusive of tine, if present) int m_level; // depth of the node in tree int m_sublevel; // # of the infoset line on this level double m_actionProb; // probability incoming action is taken wxString m_nodeAboveLabel, m_nodeBelowLabel; wxString m_branchAboveLabel, m_branchBelowLabel; wxFont m_nodeAboveFont, m_nodeBelowFont; wxFont m_branchAboveFont, m_branchBelowFont; gbtStyle *m_style; public: gbtNodeEntry(Gambit::GameNode p_parent); Gambit::GameNode GetNode(void) const { return m_node; } gbtNodeEntry *GetParent(void) const { return m_parent; } void SetParent(gbtNodeEntry *p_parent) { m_parent = p_parent; } int X(void) const { return m_x; } void SetX(int p_x) { m_x = p_x; } int Y(void) const { return m_y; } void SetY(int p_y) { m_y = p_y; } gbtNodeEntry *GetNextMember(void) const { return m_nextMember; } void SetNextMember(gbtNodeEntry *p_member) { m_nextMember = p_member; } bool InSupport(void) const { return m_inSupport; } void SetInSupport(bool p_inSupport) { m_inSupport = p_inSupport; } int GetChildNumber(void) const; const wxColour &GetColor(void) const { return m_color; } void SetColor(const wxColour &p_color) { m_color = p_color; } int GetSize(void) const { return m_size; } void SetSize(int p_size) { m_size = p_size; } int GetToken(void) const { return m_token; } void SetToken(int p_token) { m_token = p_token; } int GetBranchStyle(void) const { return m_branchStyle; } void SetBranchStyle(int p_style) { m_branchStyle = p_style; } int GetBranchLabelStyle(void) const { return m_branchLabel; } void SetBranchLabelStyle(int p_style) { m_branchLabel = p_style; } int GetBranchLength(void) const { return m_branchLength; } void SetBranchLength(int p_length) { m_branchLength = p_length; } int GetLevel(void) const { return m_level; } void SetLevel(int p_level) { m_level = p_level; } int GetSublevel(void) const { return m_sublevel; } void SetSublevel(int p_sublevel) { m_sublevel = p_sublevel; } const wxString &GetNodeAboveLabel(void) const { return m_nodeAboveLabel; } void SetNodeAboveLabel(const wxString &p_label) { m_nodeAboveLabel = p_label; } const wxString &GetNodeBelowLabel(void) const { return m_nodeBelowLabel; } void SetNodeBelowLabel(const wxString &p_label) { m_nodeBelowLabel = p_label; } const wxString &GetBranchAboveLabel(void) const { return m_branchAboveLabel; } void SetBranchAboveLabel(const wxString &p_label) { m_branchAboveLabel = p_label; } const wxString &GetBranchBelowLabel(void) const { return m_branchBelowLabel; } void SetBranchBelowLabel(const wxString &p_label) { m_branchBelowLabel = p_label; } const wxFont &GetNodeAboveFont(void) const { return m_nodeAboveFont; } void SetNodeAboveFont(const wxFont &p_font) { m_nodeAboveFont = p_font; } const wxFont &GetNodeBelowFont(void) const { return m_nodeBelowFont; } void SetNodeBelowFont(const wxFont &p_font) { m_nodeBelowFont = p_font; } const wxFont &GetBranchAboveFont(void) const { return m_branchAboveFont; } void SetBranchAboveFont(const wxFont &p_font) { m_branchAboveFont = p_font; } const wxFont &GetBranchBelowFont(void) const { return m_branchBelowFont; } void SetBranchBelowFont(const wxFont &p_font) { m_branchBelowFont = p_font; } const double &GetActionProb(void) const { return m_actionProb; } void SetActionProb(const double &p_prob) { m_actionProb = p_prob; } void SetStyle(gbtStyle *p_style) { m_style = p_style; } bool NodeHitTest(int p_x, int p_y) const; #if wxCHECK_VERSION(2,7,0) bool OutcomeHitTest(int p_x, int p_y) const { return (m_outcomeRect.Contains(p_x, p_y)); } bool BranchAboveHitTest(int p_x, int p_y) const { return (m_branchAboveRect.Contains(p_x, p_y)); } bool BranchBelowHitTest(int p_x, int p_y) const { return (m_branchBelowRect.Contains(p_x, p_y)); } #else bool OutcomeHitTest(int p_x, int p_y) const { return (m_outcomeRect.Inside(p_x, p_y)); } bool BranchAboveHitTest(int p_x, int p_y) const { return (m_branchAboveRect.Inside(p_x, p_y)); } bool BranchBelowHitTest(int p_x, int p_y) const { return (m_branchBelowRect.Inside(p_x, p_y)); } #endif const wxRect &GetOutcomeExtent(void) const { return m_outcomeRect; } const wxRect &GetPayoffExtent(int pl) const { return m_payoffRect[pl]; } void Draw(wxDC &, Gambit::GameNode selection, bool p_noHints) const; void DrawIncomingBranch(wxDC &) const; void DrawOutcome(wxDC &, bool p_noHints) const; }; class gbtEfgDisplay; class gbtTreeLayout : public gbtGameView { private: gbtEfgDisplay *m_parent; Gambit::Array m_nodeList; mutable int m_maxX, m_maxY, m_maxLevel; int m_infosetSpacing; const int c_leftMargin, c_topMargin; gbtNodeEntry *GetEntry(Gambit::GameNode) const; gbtNodeEntry *NextInfoset(gbtNodeEntry *); void CheckInfosetEntry(gbtNodeEntry *); void BuildNodeList(Gambit::GameNode, const Gambit::BehavSupport &, int); int LayoutSubtree(Gambit::GameNode, const Gambit::BehavSupport &, int &, int &, int &); void FillInfosetTable(Gambit::GameNode, const Gambit::BehavSupport &); void UpdateTableInfosets(void); void UpdateTableParents(void); wxString CreateNodeLabel(const gbtNodeEntry *, int) const; wxString CreateBranchLabel(const gbtNodeEntry *, int) const; void RenderSubtree(wxDC &dc, bool p_noHints) const; // Overriding gbtGameView members void OnUpdate(void) { } public: gbtTreeLayout(gbtEfgDisplay *p_parent, gbtGameDocument *p_doc); virtual ~gbtTreeLayout() { } Gambit::GameNode PriorSameLevel(Gambit::GameNode) const; Gambit::GameNode NextSameLevel(Gambit::GameNode) const; void BuildNodeList(const Gambit::BehavSupport &); void Layout(const Gambit::BehavSupport &); void GenerateLabels(void); // The following member functions are for temporary compatibility only gbtNodeEntry *GetNodeEntry(Gambit::GameNode p_node) const { return GetEntry(p_node); } gbtNodeEntry *GetValidParent(Gambit::GameNode); gbtNodeEntry *GetValidChild(Gambit::GameNode); int MaxX(void) const { return m_maxX; } int MaxY(void) const { return m_maxY; } Gambit::GameNode NodeHitTest(int, int) const; Gambit::GameNode OutcomeHitTest(int, int) const; Gambit::GameNode BranchAboveHitTest(int, int) const; Gambit::GameNode BranchBelowHitTest(int, int) const; Gambit::GameNode InfosetHitTest(int, int) const; void Render(wxDC &, bool p_noHints) const; }; #endif // EFGLAYOUT_H gambit-0.2010.09.01/src/gui/efgpanel.cc0000644000076500007650000006032711435216101014105 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/efgpanel.cc // Main viewing panel for extensive forms // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include // for drag-and-drop features #include // for creating drag-and-drop cursor #include // for printing support #include // for picking player colors #include "dcsvg.h" // for SVG output #include "efgpanel.h" #include "efgdisplay.h" // FIXME: communicate with tree window via events. #include "menuconst.h" #include "edittext.h" //===================================================================== // class gbtBehavDominanceToolbar //===================================================================== //! //! This panel serves as a toolbar for interactively viewing //! dominance information on extensive forms. //! class gbtBehavDominanceToolbar : public wxPanel, public gbtGameView { private: wxButton *m_topButton, *m_prevButton, *m_nextButton, *m_allButton; wxStaticText *m_level; // Overriding gbtGameView members void OnUpdate(void); // Event handlers void OnStrength(wxCommandEvent &); void OnTopLevel(wxCommandEvent &); void OnPreviousLevel(wxCommandEvent &); void OnNextLevel(wxCommandEvent &); void OnLastLevel(wxCommandEvent &); void OnShowReachable(wxCommandEvent &); public: gbtBehavDominanceToolbar(wxWindow *p_parent, gbtGameDocument *p_doc); virtual ~gbtBehavDominanceToolbar() { } }; #include "bitmaps/next.xpm" #include "bitmaps/prev.xpm" #include "bitmaps/tobegin.xpm" #include "bitmaps/toend.xpm" gbtBehavDominanceToolbar::gbtBehavDominanceToolbar(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, -1), gbtGameView(p_doc) { wxBoxSizer *topSizer = new wxBoxSizer(wxHORIZONTAL); topSizer->Add(new wxStaticText(this, wxID_STATIC, wxT("Hide actions which are ")), 0, wxALL | wxALIGN_CENTER, 5); wxString domChoices[] = { wxT("strictly"), wxT("strictly or weakly") }; wxChoice *choice = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 2, domChoices); choice->SetSelection(0); Connect(choice->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(gbtBehavDominanceToolbar::OnStrength)); topSizer->Add(choice, 0, wxALL | wxALIGN_CENTER, 5); topSizer->Add(new wxStaticText(this, wxID_STATIC, wxT("dominated:")), 0, wxALL | wxALIGN_CENTER, 5); m_topButton = new wxBitmapButton(this, -1, wxBitmap(tobegin_xpm)); m_topButton->SetToolTip(_("Show all strategies")); Connect(m_topButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtBehavDominanceToolbar::OnTopLevel)); topSizer->Add(m_topButton, 0, wxALL | wxALIGN_CENTER, 5); m_prevButton = new wxBitmapButton(this, -1, wxBitmap(prev_xpm)); m_prevButton->SetToolTip(_("Previous round of elimination")); Connect(m_prevButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtBehavDominanceToolbar::OnPreviousLevel)); topSizer->Add(m_prevButton, 0, wxALL | wxALIGN_CENTER, 5); m_level = new wxStaticText(this, wxID_STATIC, wxT("All actions shown"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER | wxST_NO_AUTORESIZE); topSizer->Add(m_level, 0, wxALL | wxALIGN_CENTER, 5); m_nextButton = new wxBitmapButton(this, -1, wxBitmap(next_xpm)); m_nextButton->SetToolTip(_("Next round of elimination")); Connect(m_nextButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtBehavDominanceToolbar::OnNextLevel)); topSizer->Add(m_nextButton, 0, wxALL | wxALIGN_CENTER, 5); m_allButton = new wxBitmapButton(this, -1, wxBitmap(toend_xpm)); m_allButton->SetToolTip(_("Eliminate iteratively")); Connect(m_allButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtBehavDominanceToolbar::OnLastLevel)); topSizer->Add(m_allButton, 0, wxALL | wxALIGN_CENTER, 5); wxCheckBox *showReachable = new wxCheckBox(this, -1, wxT("Show only reachable nodes")); showReachable->SetValue(m_doc->GetStyle().RootReachable()); Connect(showReachable->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(gbtBehavDominanceToolbar::OnShowReachable)); topSizer->Add(showReachable, 0, wxALL | wxALIGN_CENTER, 5); SetSizer(topSizer); Layout(); } void gbtBehavDominanceToolbar::OnStrength(wxCommandEvent &p_event) { m_doc->SetBehavElimStrength(p_event.GetSelection() == 0); } void gbtBehavDominanceToolbar::OnTopLevel(wxCommandEvent &) { m_doc->TopBehavElimLevel(); } void gbtBehavDominanceToolbar::OnPreviousLevel(wxCommandEvent &) { m_doc->PreviousBehavElimLevel(); } void gbtBehavDominanceToolbar::OnNextLevel(wxCommandEvent &) { m_doc->NextBehavElimLevel(); } void gbtBehavDominanceToolbar::OnLastLevel(wxCommandEvent &) { while (m_doc->NextBehavElimLevel()); } void gbtBehavDominanceToolbar::OnShowReachable(wxCommandEvent &) { m_doc->GetStyle().SetRootReachable(!m_doc->GetStyle().RootReachable()); m_doc->UpdateViews(GBT_DOC_MODIFIED_NONE); } void gbtBehavDominanceToolbar::OnUpdate(void) { m_topButton->Enable(m_doc->GetBehavElimLevel() > 1); m_prevButton->Enable(m_doc->GetBehavElimLevel() > 1); m_nextButton->Enable(m_doc->CanBehavElim()); m_allButton->Enable(m_doc->CanBehavElim()); if (m_doc->GetBehavElimLevel() == 1) { m_level->SetLabel(wxT("All actions shown")); } else if (m_doc->GetBehavElimLevel() == 2) { m_level->SetLabel(wxT("Eliminated 1 level")); } else { m_level->SetLabel(wxString::Format(wxT("Eliminated %d levels"), m_doc->GetBehavElimLevel()-1)); } GetSizer()->Layout(); } #include "bitmaps/color.xpm" #include "bitmaps/person.xpm" class gbtTreePlayerIcon : public wxStaticBitmap { private: int m_player; // Event handlers void OnLeftClick(wxMouseEvent &); public: gbtTreePlayerIcon(wxWindow *p_parent, int p_player); DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(gbtTreePlayerIcon, wxStaticBitmap) EVT_LEFT_DOWN(gbtTreePlayerIcon::OnLeftClick) END_EVENT_TABLE() gbtTreePlayerIcon::gbtTreePlayerIcon(wxWindow *p_parent, int p_player) : wxStaticBitmap(p_parent, -1, wxBitmap(person_xpm)), m_player(p_player) { } void gbtTreePlayerIcon::OnLeftClick(wxMouseEvent &) { wxBitmap bitmap(person_xpm); #if defined( __WXMSW__) or defined(__WXMAC__) wxImage image = bitmap.ConvertToImage(); #else wxIcon image; image.CopyFromBitmap(bitmap); #endif // _WXMSW__ wxTextDataObject textData(wxString::Format(wxT("P%d"), m_player)); wxDropSource source(textData, this, image, image, image); source.DoDragDrop(wxDrag_DefaultMove); } class gbtTreePlayerPanel : public wxPanel { private: gbtGameDocument *m_doc; int m_player; gbtEditableText *m_playerLabel; wxStaticText *m_payoff, *m_nodeValue, *m_nodeProb; wxStaticText *m_infosetValue, *m_infosetProb, *m_belief; /// @name Event handlers //@{ /// The set color icon is clicked void OnSetColor(wxCommandEvent &); /// Start the editing of the player label void OnEditPlayerLabel(wxCommandEvent &); /// End the editing of the player label after enter is pressed void OnAcceptPlayerLabel(wxCommandEvent &); /// Process a keypress event void OnChar(wxKeyEvent &); //@} public: gbtTreePlayerPanel(wxWindow *, gbtGameDocument *, int p_player); void OnUpdate(void); void PostPendingChanges(void); DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(gbtTreePlayerPanel, wxPanel) EVT_CHAR(gbtTreePlayerPanel::OnChar) END_EVENT_TABLE() gbtTreePlayerPanel::gbtTreePlayerPanel(wxWindow *p_parent, gbtGameDocument *p_doc, int p_player) : wxPanel(p_parent, -1), m_doc(p_doc), m_player(p_player) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *labelSizer = new wxBoxSizer(wxHORIZONTAL); wxStaticBitmap *playerIcon = new gbtTreePlayerIcon(this, m_player); labelSizer->Add(playerIcon, 0, wxALL | wxALIGN_CENTER, 0); wxBitmapButton *setColorIcon = new wxBitmapButton(this, -1, wxBitmap(color_xpm), wxDefaultPosition, wxDefaultSize, wxNO_BORDER); setColorIcon->SetToolTip(_("Change the color for this player")); labelSizer->Add(setColorIcon, 0, wxALL | wxALIGN_CENTER, 0); Connect(setColorIcon->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtTreePlayerPanel::OnSetColor)); m_playerLabel = new gbtEditableText(this, -1, wxT(""), wxDefaultPosition, wxSize(125, -1)); m_playerLabel->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); labelSizer->Add(m_playerLabel, 1, wxLEFT | wxEXPAND, 10); Connect(m_playerLabel->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtTreePlayerPanel::OnEditPlayerLabel)); Connect(m_playerLabel->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(gbtTreePlayerPanel::OnAcceptPlayerLabel)); topSizer->Add(labelSizer, 0, wxALL, 0); m_payoff = new wxStaticText(this, wxID_STATIC, wxT("Payoff:"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER | wxST_NO_AUTORESIZE); m_payoff->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); topSizer->Add(m_payoff, 0, wxALL | wxEXPAND, 0); topSizer->Show(m_payoff, false); m_nodeValue = new wxStaticText(this, wxID_STATIC, wxT("Node value:"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER | wxST_NO_AUTORESIZE); m_nodeValue->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); topSizer->Add(m_nodeValue, 0, wxALL | wxEXPAND, 0); topSizer->Show(m_nodeValue, false); m_nodeProb = new wxStaticText(this, wxID_STATIC, wxT("Node reached:"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER | wxST_NO_AUTORESIZE); m_nodeProb->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); topSizer->Add(m_nodeProb, 0, wxALL | wxEXPAND, 0); topSizer->Show(m_nodeProb, false); m_infosetValue = new wxStaticText(this, wxID_STATIC, wxT("Infoset value:"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER | wxST_NO_AUTORESIZE); m_infosetValue->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); topSizer->Add(m_infosetValue, 0, wxALL | wxEXPAND, 0); topSizer->Show(m_infosetValue, false); m_infosetProb = new wxStaticText(this, wxID_STATIC, wxT("Infoset reached:"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER | wxST_NO_AUTORESIZE); m_infosetProb->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); topSizer->Add(m_infosetProb, 0, wxALL | wxEXPAND, 0); topSizer->Show(m_infosetProb, false); m_belief = new wxStaticText(this, wxID_STATIC, wxT("Belief:"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER | wxST_NO_AUTORESIZE); m_belief->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); topSizer->Add(m_belief, 0, wxALL | wxEXPAND, 0); topSizer->Show(m_belief, false); SetSizer(topSizer); topSizer->SetSizeHints(this); topSizer->Fit(this); Layout(); } void gbtTreePlayerPanel::OnUpdate(void) { if (!m_doc->IsTree()) return; wxColour color = m_doc->GetStyle().GetPlayerColor(m_player); m_playerLabel->SetForegroundColour(color); m_playerLabel->SetValue(wxString(m_doc->GetGame()->GetPlayer(m_player)->GetLabel().c_str(), *wxConvCurrent)); m_payoff->SetForegroundColour(color); if (m_doc->GetCurrentProfile() > 0) { std::string pay = m_doc->GetProfiles().GetPayoff(m_player); m_payoff->SetLabel(wxT("Payoff: ") + wxString(pay.c_str(), *wxConvCurrent)); GetSizer()->Show(m_payoff, true); Gambit::GameNode node = m_doc->GetSelectNode(); if (node) { m_nodeValue->SetForegroundColour(color); std::string value = m_doc->GetProfiles().GetNodeValue(node, m_player); m_nodeValue->SetLabel(wxT("Node value: ") + wxString(value.c_str(), *wxConvCurrent)); GetSizer()->Show(m_nodeValue, true); if (node->GetInfoset() && node->GetPlayer()->GetNumber() == m_player) { m_nodeProb->SetForegroundColour(color); std::string value = m_doc->GetProfiles().GetRealizProb(node); m_nodeProb->SetLabel(wxT("Node reached: ") + wxString(value.c_str(), *wxConvCurrent)); GetSizer()->Show(m_nodeProb, true); m_infosetValue->SetForegroundColour(color); value = m_doc->GetProfiles().GetInfosetValue(node); m_infosetValue->SetLabel(wxT("Infoset value: ") + wxString(value.c_str(), *wxConvCurrent)); GetSizer()->Show(m_infosetValue, true); m_infosetProb->SetForegroundColour(color); value = m_doc->GetProfiles().GetInfosetProb(node); m_infosetProb->SetLabel(wxT("Infoset reached: ") + wxString(value.c_str(), *wxConvCurrent)); GetSizer()->Show(m_infosetProb, true); m_belief->SetForegroundColour(color); value = m_doc->GetProfiles().GetBeliefProb(node); m_belief->SetLabel(wxT("Belief: ") + wxString(value.c_str(), *wxConvCurrent)); GetSizer()->Show(m_belief, true); } else { GetSizer()->Show(m_nodeProb, false); GetSizer()->Show(m_infosetValue, false); GetSizer()->Show(m_infosetProb, false); GetSizer()->Show(m_belief, false); } } else { GetSizer()->Show(m_nodeValue, false); } } else { GetSizer()->Show(m_payoff, false); GetSizer()->Show(m_nodeValue, false); GetSizer()->Show(m_nodeProb, false); GetSizer()->Show(m_infosetValue, false); GetSizer()->Show(m_infosetProb, false); GetSizer()->Show(m_belief, false); } GetSizer()->Layout(); GetSizer()->SetSizeHints(this); GetSizer()->Fit(this); } void gbtTreePlayerPanel::OnChar(wxKeyEvent &p_event) { if (p_event.GetKeyCode() == WXK_ESCAPE) { m_playerLabel->EndEdit(false); } else { p_event.Skip(); } } void gbtTreePlayerPanel::OnSetColor(wxCommandEvent &) { wxColourData data; data.SetColour(m_doc->GetStyle().GetPlayerColor(m_player)); wxColourDialog dialog(this, &data); dialog.SetTitle(wxString::Format(_("Choose color for player %d"), m_player)); if (dialog.ShowModal() == wxID_OK) { wxColour color = dialog.GetColourData().GetColour(); m_doc->GetStyle().SetPlayerColor(m_player, color); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } } void gbtTreePlayerPanel::OnEditPlayerLabel(wxCommandEvent &) { m_doc->PostPendingChanges(); m_playerLabel->BeginEdit(); } void gbtTreePlayerPanel::OnAcceptPlayerLabel(wxCommandEvent &) { m_doc->GetGame()->GetPlayer(m_player)->SetLabel((const char *) m_playerLabel->GetValue().mb_str()); m_doc->UpdateViews(GBT_DOC_MODIFIED_LABELS); } void gbtTreePlayerPanel::PostPendingChanges(void) { if (m_playerLabel->IsEditing()) { m_playerLabel->EndEdit(true); m_doc->GetGame()->GetPlayer(m_player)->SetLabel((const char *) m_playerLabel->GetValue().mb_str()); m_doc->UpdateViews(GBT_DOC_MODIFIED_LABELS); } } #include "bitmaps/dice.xpm" class gbtTreeChanceIcon : public wxStaticBitmap { private: // Event handlers void OnLeftClick(wxMouseEvent &); public: gbtTreeChanceIcon(wxWindow *p_parent); DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(gbtTreeChanceIcon, wxStaticBitmap) EVT_LEFT_DOWN(gbtTreeChanceIcon::OnLeftClick) END_EVENT_TABLE() gbtTreeChanceIcon::gbtTreeChanceIcon(wxWindow *p_parent) : wxStaticBitmap(p_parent, -1, wxBitmap(dice_xpm)) { } void gbtTreeChanceIcon::OnLeftClick(wxMouseEvent &) { wxBitmap bitmap(dice_xpm); #if defined( __WXMSW__) or defined(__WXMAC__) wxImage image = bitmap.ConvertToImage(); #else wxIcon image; image.CopyFromBitmap(bitmap); #endif // _WXMSW__ wxTextDataObject textData(wxT("P0")); wxDropSource source(textData, this, image, image, image); source.DoDragDrop(wxDrag_DefaultMove); } class gbtTreeChancePanel : public wxPanel, public gbtGameView { private: wxStaticText *m_playerLabel; // Implementation of gbtGameView members void OnUpdate(void); /// @name Event handlers //@{ /// The set color icon is clicked void OnSetColor(wxCommandEvent &); //@} public: gbtTreeChancePanel(wxWindow *, gbtGameDocument *); }; gbtTreeChancePanel::gbtTreeChancePanel(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, -1), gbtGameView(p_doc) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *labelSizer = new wxBoxSizer(wxHORIZONTAL); wxStaticBitmap *playerIcon = new gbtTreeChanceIcon(this); labelSizer->Add(playerIcon, 0, wxALL | wxALIGN_CENTER, 0); wxBitmapButton *setColorIcon = new wxBitmapButton(this, -1, wxBitmap(color_xpm), wxDefaultPosition, wxDefaultSize, wxNO_BORDER); setColorIcon->SetToolTip(_("Change the color for this player")); labelSizer->Add(setColorIcon, 0, wxALL | wxALIGN_CENTER, 0); Connect(setColorIcon->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtTreeChancePanel::OnSetColor)); m_playerLabel = new wxStaticText(this, wxID_STATIC, wxT("Chance"), wxDefaultPosition, wxSize(125, -1), wxALIGN_LEFT); m_playerLabel->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); labelSizer->Add(m_playerLabel, 1, wxLEFT | wxALIGN_CENTER, 10); topSizer->Add(labelSizer, 0, wxALL, 0); SetSizer(topSizer); topSizer->SetSizeHints(this); topSizer->Fit(this); Layout(); } void gbtTreeChancePanel::OnUpdate(void) { if (!m_doc->GetGame()) return; m_playerLabel->SetForegroundColour(m_doc->GetStyle().ChanceColor()); GetSizer()->Layout(); } void gbtTreeChancePanel::OnSetColor(wxCommandEvent &) { wxColourData data; data.SetColour(m_doc->GetStyle().ChanceColor()); wxColourDialog dialog(this, &data); dialog.SetTitle(wxT("Choose color for chance player")); if (dialog.ShowModal() == wxID_OK) { wxColour color = dialog.GetColourData().GetColour(); m_doc->GetStyle().SetChanceColor(color); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } } //===================================================================== // class gbtTreePlayerToolbar //===================================================================== class gbtTreePlayerToolbar : public wxPanel, public gbtGameView { private: gbtTreeChancePanel *m_chancePanel; Gambit::Array m_playerPanels; // @name Implementation of gbtGameView members //@{ void OnUpdate(void); void PostPendingChanges(void); //@} public: gbtTreePlayerToolbar(wxWindow *p_parent, gbtGameDocument *p_doc); }; gbtTreePlayerToolbar::gbtTreePlayerToolbar(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, -1, wxDefaultPosition, wxSize(110, -1)), gbtGameView(p_doc) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); m_chancePanel = new gbtTreeChancePanel(this, m_doc); topSizer->Add(m_chancePanel, 0, wxALL | wxEXPAND, 5); for (int pl = 1; pl <= m_doc->NumPlayers(); pl++) { m_playerPanels.Append(new gbtTreePlayerPanel(this, m_doc, pl)); topSizer->Add(m_playerPanels[pl], 0, wxALL | wxEXPAND, 5); } SetSizer(topSizer); Layout(); } void gbtTreePlayerToolbar::OnUpdate(void) { while (m_playerPanels.Length() < m_doc->NumPlayers()) { gbtTreePlayerPanel *panel = new gbtTreePlayerPanel(this, m_doc, m_playerPanels.Length()+1); m_playerPanels.Append(panel); GetSizer()->Add(panel, 0, wxALL | wxEXPAND, 5); } while (m_playerPanels.Length() > m_doc->NumPlayers()) { gbtTreePlayerPanel *panel = m_playerPanels.Remove(m_playerPanels.Length()); GetSizer()->Remove(panel); panel->Destroy(); } for (int pl = 1; pl <= m_playerPanels.Length(); pl++) { m_playerPanels[pl]->OnUpdate(); } GetSizer()->Layout(); } void gbtTreePlayerToolbar::PostPendingChanges(void) { for (int pl = 1; pl <= m_playerPanels.Length(); pl++) { m_playerPanels[pl]->PostPendingChanges(); } } //===================================================================== // Implementation of class gbtEfgPanel //===================================================================== BEGIN_EVENT_TABLE(gbtEfgPanel, wxPanel) EVT_MENU(GBT_MENU_TOOLS_DOMINANCE, gbtEfgPanel::OnToolsDominance) EVT_MENU(GBT_MENU_VIEW_ZOOMIN, gbtEfgPanel::OnViewZoomIn) EVT_MENU(GBT_MENU_VIEW_ZOOMOUT, gbtEfgPanel::OnViewZoomOut) EVT_MENU(GBT_MENU_VIEW_ZOOM100, gbtEfgPanel::OnViewZoom100) EVT_MENU(GBT_MENU_VIEW_ZOOMFIT, gbtEfgPanel::OnViewZoomFit) END_EVENT_TABLE() gbtEfgPanel::gbtEfgPanel(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, -1), gbtGameView(p_doc) { m_treeWindow = new gbtEfgDisplay(this, m_doc); m_playerToolbar = new gbtTreePlayerToolbar(this, m_doc); m_dominanceToolbar = new gbtBehavDominanceToolbar(this, m_doc); wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); topSizer->Add(m_dominanceToolbar, 0, wxEXPAND, 0); topSizer->Show(m_dominanceToolbar, false); wxBoxSizer *treeSizer = new wxBoxSizer(wxHORIZONTAL); treeSizer->Add(m_playerToolbar, 0, wxEXPAND, 0); treeSizer->Add(m_treeWindow, 1, wxEXPAND, 0); topSizer->Add(treeSizer, 1, wxEXPAND, 0); SetSizer(topSizer); Layout(); } void gbtEfgPanel::OnToolsDominance(wxCommandEvent &p_event) { GetSizer()->Show(m_dominanceToolbar, p_event.IsChecked(), true); GetSizer()->Layout(); } void gbtEfgPanel::OnViewZoomIn(wxCommandEvent &) { int zoom = m_treeWindow->GetZoom(); if (zoom < 150) zoom += 10; m_treeWindow->SetZoom(zoom); } void gbtEfgPanel::OnViewZoomOut(wxCommandEvent &) { int zoom = m_treeWindow->GetZoom(); if (zoom > 10) zoom -= 10; m_treeWindow->SetZoom(zoom); } void gbtEfgPanel::OnViewZoom100(wxCommandEvent &) { m_treeWindow->SetZoom(100); } void gbtEfgPanel::OnViewZoomFit(wxCommandEvent &) { m_treeWindow->FitZoom(); } class gbtEfgPrintout : public wxPrintout { private: gbtEfgPanel *m_efgPanel; public: gbtEfgPrintout(gbtEfgPanel *p_efgPanel, const wxString &p_label) : wxPrintout(p_label), m_efgPanel(p_efgPanel) { } virtual ~gbtEfgPrintout() { } bool OnPrintPage(int) { m_efgPanel->RenderGame(*GetDC(), 50, 50); return true; } bool HasPage(int page) { return (page <= 1); } void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) { *minPage = 1; *maxPage = 1; *selPageFrom = 1; *selPageTo = 1; } }; wxPrintout *gbtEfgPanel::GetPrintout(void) { return new gbtEfgPrintout(this, wxString(m_doc->GetGame()->GetTitle().c_str(), *wxConvCurrent)); } bool gbtEfgPanel::GetBitmap(wxBitmap &p_bitmap, int p_marginX, int p_marginY) { if (m_treeWindow->GetLayout().MaxX() > 65000 || m_treeWindow->GetLayout().MaxY() > 65000) { // This is just too huge to export to graphics return false; } wxMemoryDC dc; p_bitmap = wxBitmap(m_treeWindow->GetLayout().MaxX() + 2 * p_marginX, m_treeWindow->GetLayout().MaxY() + 2 * p_marginY); dc.SelectObject(p_bitmap); RenderGame(dc, p_marginX, p_marginY); return true; } void gbtEfgPanel::GetSVG(const wxString &p_filename, int p_marginX, int p_marginY) { // The size of the image to be drawn int maxX = m_treeWindow->GetLayout().MaxX(); int maxY = m_treeWindow->GetLayout().MaxY(); wxSVGFileDC dc(p_filename, maxX + 2*p_marginX, maxY + 2*p_marginY); // For some reason, this needs to be initialized dc.SetLogicalScale(1.0, 1.0); RenderGame(dc, p_marginX, p_marginY); } void gbtEfgPanel::RenderGame(wxDC &p_dc, int p_marginX, int p_marginY) { // The size of the image to be drawn int maxX = m_treeWindow->GetLayout().MaxX(); int maxY = m_treeWindow->GetLayout().MaxY(); // Get the size of the DC in pixels wxCoord w, h; p_dc.GetSize(&w, &h); // Calculate a scaling factor double scaleX = (double) w / (double) (maxX + 2*p_marginX); double scaleY = (double) h / (double) (maxY + 2*p_marginY); double scale = (scaleX < scaleY) ? scaleX : scaleY; // Never zoom in if (scale > 1.0) scale = 1.0; p_dc.SetUserScale(scale, scale); // Calculate the position on the DC to center the tree double posX = (double) ((w - (maxX * scale)) / 2.0); double posY = (double) ((h - (maxY * scale)) / 2.0); p_dc.SetDeviceOrigin((int) posX, (int) posY); printf("Drawing with scale %f\n", scale); // Draw! m_treeWindow->OnDraw(p_dc, scale); } gambit-0.2010.09.01/src/gui/efgpanel.h0000644000076500007650000000413611435216101013743 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/efgpanel.h // Main viewing panel for extensive forms // // 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 EFGPANEL_H #define EFGPANEL_H #include "gamedoc.h" class wxPrintout; class gbtEfgDisplay; class gbtEfgPanel : public wxPanel, public gbtGameView { private: gbtEfgDisplay *m_treeWindow; wxWindow *m_dominanceToolbar, *m_playerToolbar; // Overriding gbtGameView members void OnUpdate(void) { } /// @name Command event handlers //@{ void OnToolsDominance(wxCommandEvent &); void OnViewZoomIn(wxCommandEvent &); void OnViewZoomOut(wxCommandEvent &); void OnViewZoom100(wxCommandEvent &); void OnViewZoomFit(wxCommandEvent &); //@} public: gbtEfgPanel(wxWindow *p_parent, gbtGameDocument *p_doc); virtual ~gbtEfgPanel() { } /// @name Exporting/printing graphics //@{ /// Creates a printout object of the game as currently displayed wxPrintout *GetPrintout(void); /// Creates a bitmap of the game as currently displayed bool GetBitmap(wxBitmap &, int marginX, int marginY); /// Outputs the game as currently displayed to a SVG file void GetSVG(const wxString &p_filename, int marginX, int marginY); /// Prints the game as currently displayed, centered on the DC void RenderGame(wxDC &p_dc, int marginX, int marginY); //@} DECLARE_EVENT_TABLE() }; #endif // EFGPANEL_H gambit-0.2010.09.01/src/gui/efgprofile.cc0000644000076500007650000001426411441446350014455 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/efgprofile.cc // Extensive form behavior profile window // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "efgprofile.h" #include "menuconst.h" #include "renratio.h" // for rational number rendering //------------------------------------------------------------------------- // class gbtBehavProfileList: Member functions //------------------------------------------------------------------------- gbtBehavProfileList::gbtBehavProfileList(wxWindow *p_parent, gbtGameDocument *p_doc) : wxSheet(p_parent, -1), gbtGameView(p_doc) { CreateGrid(0, 0); SetRowLabelWidth(40); SetColLabelHeight(25); Connect(GetId(), wxEVT_SHEET_LABEL_LEFT_DOWN, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtBehavProfileList::OnLabelClick))); Connect(GetId(), wxEVT_SHEET_CELL_LEFT_DOWN, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtBehavProfileList::OnCellClick))); } gbtBehavProfileList::~gbtBehavProfileList() { } void gbtBehavProfileList::OnLabelClick(wxSheetEvent &p_event) { if (p_event.GetCol() == -1) { m_doc->SetCurrentProfile(p_event.GetRow() + 1); } else { // Clicking on an action column sets the selected node to the first // member of that information set. Gambit::GameAction action = m_doc->GetGame()->GetAction(p_event.GetCol()+1); m_doc->SetSelectNode(action->GetInfoset()->GetMember(1)); } } void gbtBehavProfileList::OnCellClick(wxSheetEvent &p_event) { m_doc->SetCurrentProfile(p_event.GetRow() + 1); } wxString gbtBehavProfileList::GetCellValue(const wxSheetCoords &p_coords) { if (IsRowLabelCell(p_coords)) { return wxString::Format(wxT("%d"), p_coords.GetRow() + 1); } else if (IsColLabelCell(p_coords)) { Gambit::GameAction action = m_doc->GetGame()->GetAction(p_coords.GetCol()+1); return (wxString::Format(wxT("%d: "), action->GetInfoset()->GetNumber()) + wxString(action->GetLabel().c_str(), *wxConvCurrent)); } else if (IsCornerLabelCell(p_coords)) { return wxT("#"); } return wxString(m_doc->GetProfiles().GetActionProb(p_coords.GetCol()+1, p_coords.GetRow()+1).c_str(), *wxConvCurrent); } static wxColour GetPlayerColor(gbtGameDocument *p_doc, int p_index) { Gambit::GameAction action = p_doc->GetGame()->GetAction(p_index+1); return p_doc->GetStyle().GetPlayerColor(action->GetInfoset()->GetPlayer()->GetNumber()); } wxSheetCellAttr gbtBehavProfileList::GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const { int currentProfile = m_doc->GetCurrentProfile(); if (IsRowLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultRowLabelAttr); if (p_coords.GetRow()+1 == currentProfile) { attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); } else { attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); } attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); return attr; } else if (IsColLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultColLabelAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); if (p_coords.GetRow() > 0) { attr.SetForegroundColour(GetPlayerColor(m_doc, p_coords.GetCol())); } return attr; } else if (IsCornerLabelCell(p_coords)) { return GetSheetRefData()->m_defaultCornerLabelAttr; } wxSheetCellAttr attr(GetSheetRefData()->m_defaultGridCellAttr); if (p_coords.GetRow()+1 == currentProfile) { attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); } else { attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); } attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetRenderer(wxSheetCellRenderer(new gbtRationalRendererRefData())); try { Gambit::GameAction action = m_doc->GetGame()->GetAction(p_coords.GetCol()+1); attr.SetForegroundColour(m_doc->GetStyle().GetPlayerColor(action->GetInfoset()->GetPlayer()->GetNumber())); if (action->GetInfoset()->GetNumber() % 2 == 0) { attr.SetBackgroundColour(wxColour(250, 250, 250)); } else { attr.SetBackgroundColour(wxColour(225, 225, 225)); } } catch (Gambit::IndexException) { // If GetAction() throws this, just handle it silently; can occur // when solving a trivial game via the strategic form } attr.SetReadOnly(true); return attr; } void gbtBehavProfileList::OnUpdate(void) { if (!m_doc->GetGame() || m_doc->NumProfileLists() == 0) { DeleteRows(0, GetNumberRows()); return; } const gbtAnalysisOutput &profiles = m_doc->GetProfiles(); int profileLength = m_doc->GetGame()->BehavProfileLength(); BeginBatch(); if (GetNumberRows() > profiles.NumProfiles()) { DeleteRows(0, GetNumberRows() - profiles.NumProfiles()); } else if (GetNumberRows() < profiles.NumProfiles()) { InsertRows(0, profiles.NumProfiles() - GetNumberRows()); } if (GetNumberCols() > profileLength) { DeleteCols(0, GetNumberCols() - profileLength); } else if (GetNumberCols() < profileLength) { InsertCols(0, profileLength - GetNumberCols()); } AutoSizeRows(); AutoSizeCols(); EndBatch(); } gambit-0.2010.09.01/src/gui/efgprofile.h0000644000076500007650000000434111435216101014302 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/efgprofile.h // Extensive form behavior profile window // // 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 EFGPROFILE_H #define EFGPROFILE_H #include "wx/sheet/sheet.h" #include "gamedoc.h" class gbtBehavProfileList : public wxSheet, public gbtGameView { private: // Overriding wxSheet members for data access wxString GetCellValue(const wxSheetCoords &); wxSheetCellAttr GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const; // Overriding wxSheet members to disable selection behavior bool SelectRow(int, bool = false, bool = false) { return false; } bool SelectRows(int, int, bool = false, bool = false) { return false; } bool SelectCol(int, bool = false, bool = false) { return false; } bool SelectCols(int, int, bool = false, bool = false) { return false; } bool SelectCell(const wxSheetCoords&, bool = false, bool = false) { return false; } bool SelectBlock(const wxSheetBlock&, bool = false, bool = false) { return false; } bool SelectAll(bool = false) { return false; } // Overriding wxSheet member to suppress drawing of cursor void DrawCursorCellHighlight(wxDC&, const wxSheetCellAttr &) { } // Event handlers void OnLabelClick(wxSheetEvent &); void OnCellClick(wxSheetEvent &); // Overriding gbtGameView members void OnUpdate(void); public: gbtBehavProfileList(wxWindow *p_parent, gbtGameDocument *p_doc); virtual ~gbtBehavProfileList(); }; #endif // EFGPROFILE_H gambit-0.2010.09.01/src/gui/gambit.cc0000644000076500007650000001132111435216101013555 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/gambit.cc // Implementation of main wxApp class // // 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 #include #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include #include #include "libgambit/libgambit.h" #include "gambit.h" #include "gameframe.h" gbtApplication::gbtApplication(void) : m_fileHistory(5) { } bool gbtApplication::OnInit(void) { #include "bitmaps/gambitbig.xpm" wxConfig config(_T("Gambit")); m_fileHistory.Load(config); // Immediately saving this back forces the entries to be created at // the "top level" of the config file when using the wxFileConfig // implementation (which seems to still be buggy). m_fileHistory.Save(config); config.Read(_T("/General/CurrentDirectory"), &m_currentDir, _T("")); wxBitmap bitmap(gambitbig_xpm); /*wxSplashScreen *splash =*/ new wxSplashScreen(bitmap, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT, 2000, NULL, -1, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER | wxSTAY_ON_TOP); wxYield(); // The number of game files successfully opened int nGames = 0; // Process command line arguments, if any. for (int i = 1; i < argc; i++) { gbtAppLoadResult result = LoadFile(argv[i]); if (result == GBT_APP_OPEN_FAILED) { wxMessageDialog dialog(0, wxT("Gambit could not open file '") + wxString(argv[i], *wxConvCurrent) + wxT("' for reading."), wxT("Unable to open file"), wxOK | wxICON_ERROR); dialog.ShowModal(); } else if (result == GBT_APP_PARSE_FAILED) { wxMessageDialog dialog(0, wxT("File '") + wxString(argv[i], *wxConvCurrent) + wxT("' is not in a format Gambit recognizes."), wxT("Unable to read file"), wxOK | wxICON_ERROR); dialog.ShowModal(); } else { nGames++; } } if (nGames == 0) { // If we don't have any game files -- whether because none were // specified on the command line, or because those specified couldn't // be read -- create a default document. Gambit::Game efg = new Gambit::GameRep; efg->NewPlayer()->SetLabel("Player 1"); efg->NewPlayer()->SetLabel("Player 2"); efg->SetTitle("Untitled Extensive Game"); gbtGameDocument *game = new gbtGameDocument(efg); (void) new gbtGameFrame(0, game); } // Set up the help system. wxInitAllImageHandlers(); return true; } gbtApplication::~gbtApplication() { wxConfig config(_T("Gambit")); m_fileHistory.Save(config); } gbtAppLoadResult gbtApplication::LoadFile(const wxString &p_filename) { std::ifstream infile((const char *) p_filename.mb_str()); if (!infile.good()) { return GBT_APP_OPEN_FAILED; } gbtGameDocument *doc = new gbtGameDocument(new Gambit::GameRep); if (doc->LoadDocument(p_filename)) { doc->SetFilename(p_filename); m_fileHistory.AddFileToHistory(p_filename); (void) new gbtGameFrame(0, doc); return GBT_APP_FILE_OK; } else { delete doc; } try { Gambit::Game nfg = Gambit::ReadGame(infile); m_fileHistory.AddFileToHistory(p_filename); gbtGameDocument *doc = new gbtGameDocument(nfg); doc->SetFilename(wxT("")); (void) new gbtGameFrame(0, doc); return GBT_APP_FILE_OK; } catch (Gambit::InvalidFileException) { return GBT_APP_PARSE_FAILED; } } bool gbtApplication::AreDocumentsModified(void) const { for (int i = 1; i <= m_documents.Length(); i++) { if (m_documents[i]->IsModified()) { return true; } } return false; } IMPLEMENT_APP(gbtApplication) // // A general-purpose dialog box to display the description of the exception // void gbtExceptionDialog(const std::string &p_message, wxWindow *p_parent, long p_style /*= wxOK | wxCENTRE*/) { std::string message = "An internal error occurred in Gambit:\n" + p_message; wxMessageBox(wxString(message.c_str(), *wxConvCurrent), _("Gambit Error"), p_style, p_parent); } gambit-0.2010.09.01/src/gui/gambit.h0000644000076500007650000000463711435216101013433 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/gambit.h // Declaration of application-level class for Gambit graphical interface // // 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 GAMBIT_H #define GAMBIT_H #include #include // for wxConfig #include // for wxFileHistory extern void gbtExceptionDialog(const std::string &p_message, wxWindow *p_parent, long p_style = wxOK | wxCENTRE); class gbtGameDocument; typedef enum { GBT_APP_FILE_OK = 0, GBT_APP_OPEN_FAILED = 1, GBT_APP_PARSE_FAILED = 2 } gbtAppLoadResult; class gbtApplication : public wxApp { private: wxString m_currentDir; /* Current position in directory tree. */ wxFileHistory m_fileHistory; Gambit::Array m_documents; bool OnInit(void); public: gbtApplication(void); virtual ~gbtApplication(); const wxString &GetCurrentDir(void) { return m_currentDir; } void SetCurrentDir(const wxString &p_dir) { m_currentDir = p_dir; } wxString GetHistoryFile(int index) const { return m_fileHistory.GetHistoryFile(index); } void AddMenu(wxMenu *p_menu) { m_fileHistory.UseMenu(p_menu); m_fileHistory.AddFilesToMenu(p_menu); } void RemoveMenu(wxMenu *p_menu) { m_fileHistory.RemoveMenu(p_menu); } gbtAppLoadResult LoadFile(const wxString &); //! //! These manage the list of open documents //! //@{ void AddDocument(gbtGameDocument *p_doc) { m_documents.Append(p_doc); } void RemoveDocument(gbtGameDocument *p_doc) { m_documents.Remove(m_documents.Find(p_doc)); } bool AreDocumentsModified(void) const; //@} }; DECLARE_APP(gbtApplication) #endif // GAMBIT_H gambit-0.2010.09.01/src/gui/gamedoc.cc0000644000076500007650000003634111435216101013722 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/gamedoc.cc // Implementation of game document class // // 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 #include #include #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include // used to create temp files for undo/redo #include "libgambit/libgambit.h" #include "tinyxml.h" // for XML parser for LoadDocument() #include "gambit.h" // for wxGetApp() #include "gamedoc.h" //========================================================================= // class gbtBehavDominanceStack //========================================================================= gbtBehavDominanceStack::gbtBehavDominanceStack(gbtGameDocument *p_doc, bool p_strict) : m_doc(p_doc), m_strict(p_strict), m_noFurther(false) { Reset(); } gbtBehavDominanceStack::~gbtBehavDominanceStack() { for (int i = 1; i <= m_supports.Length(); delete m_supports[i++]); } void gbtBehavDominanceStack::SetStrict(bool p_strict) { if (m_strict != p_strict) Reset(); m_strict = p_strict; } void gbtBehavDominanceStack::Reset(void) { for (int i = 1; i <= m_supports.Length(); delete m_supports[i++]); m_supports = Gambit::Array(); if (m_doc->IsTree()) { m_supports.Append(new Gambit::BehavSupport(m_doc->GetGame())); m_current = 1; } m_noFurther = false; } bool gbtBehavDominanceStack::NextLevel(void) { if (m_current < m_supports.Length()) { m_current++; return true; } if (m_noFurther) { return false; } Gambit::Array players; for (int pl = 1; pl <= m_doc->GetGame()->NumPlayers(); pl++) { players.Append(pl); } std::ostringstream gnull; Gambit::BehavSupport newSupport = m_supports[m_current]->Undominated(m_strict, true, players, gnull); if (newSupport != *m_supports[m_current]) { m_supports.Append(new Gambit::BehavSupport(newSupport)); m_current++; return true; } else { m_noFurther = true; return false; } } bool gbtBehavDominanceStack::PreviousLevel(void) { if (m_current > 1) { m_current--; return true; } else { return false; } } //========================================================================= // class gbtStrategyDominanceStack //========================================================================= gbtStrategyDominanceStack::gbtStrategyDominanceStack(gbtGameDocument *p_doc, bool p_strict) : m_doc(p_doc), m_strict(p_strict), m_noFurther(false) { Reset(); } gbtStrategyDominanceStack::~gbtStrategyDominanceStack() { for (int i = 1; i <= m_supports.Length(); delete m_supports[i++]); } void gbtStrategyDominanceStack::SetStrict(bool p_strict) { if (m_strict != p_strict) Reset(); m_strict = p_strict; } void gbtStrategyDominanceStack::Reset(void) { for (int i = 1; i <= m_supports.Length(); delete m_supports[i++]); m_supports = Gambit::Array(); if (m_doc->GetGame()->HasComputedValues()) { m_supports.Append(new Gambit::StrategySupport(m_doc->GetGame())); m_current = 1; m_noFurther = false; } } bool gbtStrategyDominanceStack::NextLevel(void) { if (m_current < m_supports.Length()) { m_current++; return true; } if (m_noFurther) { return false; } Gambit::Array players; for (int pl = 1; pl <= m_doc->GetGame()->NumPlayers(); pl++) { players.Append(pl); } Gambit::StrategySupport newSupport = m_supports[m_current]->Undominated(m_strict, players); if (newSupport != *m_supports[m_current]) { m_supports.Append(new Gambit::StrategySupport(newSupport)); m_current++; return true; } else { m_noFurther = true; return false; } } bool gbtStrategyDominanceStack::PreviousLevel(void) { if (m_current > 1) { m_current--; return true; } else { return false; } } //========================================================================= // class gbtGameDocument //========================================================================= gbtGameDocument::gbtGameDocument(Gambit::Game p_game) : m_game(p_game), m_selectNode(0), m_modified(false), m_behavSupports(this, true), m_stratSupports(this, true), m_currentProfileList(0) { m_game->Canonicalize(); wxGetApp().AddDocument(this); std::ostringstream s; SaveDocument(s); m_undoList.Append(s.str()); } gbtGameDocument::~gbtGameDocument() { wxGetApp().RemoveDocument(this); } bool gbtGameDocument::LoadDocument(const wxString &p_filename, bool p_saveUndo) { TiXmlDocument doc((const char *) p_filename.mb_str()); if (!doc.LoadFile()) { // Some error occurred. Do something smart later. return false; } TiXmlNode *docroot = doc.FirstChild("gambit:document"); if (!docroot) { // This is an "old-style" file that didn't have a proper root. docroot = &doc; } TiXmlNode *game = docroot->FirstChild("game"); if (!game) { // There ought to be at least one game child. If not... umm... return false; } TiXmlNode *efgfile = game->FirstChild("efgfile"); if (efgfile) { try { std::istringstream s(efgfile->FirstChild()->Value()); m_game = Gambit::ReadGame(s); } catch (...) { return false; } } TiXmlNode *nfgfile = game->FirstChild("nfgfile"); if (nfgfile) { try { std::istringstream s(nfgfile->FirstChild()->Value()); m_game = Gambit::ReadGame(s); } catch (...) { return false; } } if (!efgfile && !nfgfile) { // No game representation... punt! return false; } m_behavSupports.Reset(); m_stratSupports.Reset(); m_profiles = Gambit::List(); for (TiXmlNode *analysis = game->FirstChild("analysis"); analysis; analysis = analysis->NextSibling()) { const char *type = analysis->ToElement()->Attribute("type"); // const char *rep = analysis->ToElement()->Attribute("rep"); if (type && !strcmp(type, "list")) { // Read in a list of profiles // We need to try to guess whether the profiles are float or rational bool isFloat = false; for (TiXmlNode *profile = analysis->FirstChild("profile"); profile; profile = profile->NextSiblingElement()) { if (std::string(profile->FirstChild()->Value()).find('.') != (unsigned int) -1 || std::string(profile->FirstChild()->Value()).find('e') != (unsigned int) -1) { isFloat = true; break; } } if (isFloat) { gbtAnalysisProfileList *plist = new gbtAnalysisProfileList(this, false); plist->Load(analysis); m_profiles.Append(plist); } else { gbtAnalysisProfileList *plist = new gbtAnalysisProfileList(this, false); plist->Load(analysis); m_profiles.Append(plist); } } } m_currentProfileList = m_profiles.Length(); TiXmlNode *colors = docroot->FirstChild("colors"); if (colors) m_style.SetColorXML(colors); TiXmlNode *font = docroot->FirstChild("font"); if (font) m_style.SetFontXML(font); TiXmlNode *layout = docroot->FirstChild("autolayout"); if (layout) m_style.SetLayoutXML(layout); TiXmlNode *labels = docroot->FirstChild("labels"); if (labels) m_style.SetLabelXML(labels); TiXmlNode *numbers = docroot->FirstChild("numbers"); if (numbers) { int numDecimals = 4; numbers->ToElement()->QueryIntAttribute("decimals", &numDecimals); m_style.SetNumDecimals(numDecimals); } if (p_saveUndo) { std::ostringstream s; SaveDocument(s); m_undoList.Append(s.str()); } return true; } void gbtGameDocument::SaveDocument(std::ostream &p_file) const { p_file << "\n"; p_file << "\n"; p_file << m_style.GetColorXML(); p_file << m_style.GetFontXML(); if (m_game->IsTree()) { p_file << m_style.GetLayoutXML(); p_file << m_style.GetLabelXML(); } p_file << "\n"; p_file << "\n"; if (m_game->IsTree()) { p_file << "\n"; m_game->WriteEfgFile(p_file); p_file << "\n"; } else { p_file << "\n"; m_game->WriteNfgFile(p_file); p_file << "\n"; } for (int i = 1; i <= m_profiles.Length(); i++) { m_profiles[i]->Save(p_file); } p_file << "\n"; p_file << "\n"; } void gbtGameDocument::UpdateViews(gbtGameModificationType p_modifications) { if (p_modifications != GBT_DOC_MODIFIED_NONE) { m_modified = true; m_game->Canonicalize(); m_redoList = Gambit::List(); std::ostringstream s; SaveDocument(s); m_undoList.Append(s.str()); } if (p_modifications == GBT_DOC_MODIFIED_GAME || p_modifications == GBT_DOC_MODIFIED_PAYOFFS) { m_behavSupports.Reset(); m_stratSupports.Reset(); // Even though modifications only to payoffs doesn't make the // computed profiles invalid for the edited game, it does mean // that, in general, they won't be Nash. For now, to avoid confusion, // we will wipe them out. while (m_profiles.Length() > 0) { delete m_profiles.Remove(1); } m_currentProfileList = 0; } for (int i = 1; i <= m_views.Length(); m_views[i++]->OnUpdate()); } void gbtGameDocument::PostPendingChanges(void) { for (int i = 1; i <= m_views.Length(); m_views[i++]->PostPendingChanges()); } void gbtGameDocument::BuildNfg(void) { if (m_game->IsTree()) { m_game->BuildComputedValues(); m_stratSupports.Reset(); for (int i = 1; i <= m_profiles.Length(); m_profiles[i++]->BuildNfg()); } } // // A word about the undo and redo features: // We store a list of the textual representation of games. We don't // store other aspects of the state (e.g., profiles) as yet. // The "undo" list includes the representation of the current state // of the game (hence, CanUndo() only returns true when the list has // more than one element. // void gbtGameDocument::Undo(void) { // The current game is at the end of the undo list; move it to the redo list m_redoList.Append(m_undoList[m_undoList.Length()]); m_undoList.Remove(m_undoList.Length()); m_game = 0; while (m_profiles.Length() > 0) { delete m_profiles.Remove(1); } m_currentProfileList = 0; wxString tempfile = wxFileName::CreateTempFileName(wxT("gambit")); std::ofstream f((const char *) tempfile.mb_str()); f << m_undoList[m_undoList.Length()] << std::endl; f.close(); LoadDocument(tempfile, false); wxRemoveFile(tempfile); for (int i = 1; i <= m_views.Length(); m_views[i++]->OnUpdate()); } void gbtGameDocument::Redo(void) { m_undoList.Append(m_redoList[m_redoList.Length()]); m_redoList.Remove(m_redoList.Length()); m_game = 0; while (m_profiles.Length() > 0) { delete m_profiles.Remove(1); } m_currentProfileList = 0; wxString tempfile = wxFileName::CreateTempFileName(wxT("gambit")); std::ofstream f((const char *) tempfile.mb_str()); f << m_undoList[m_undoList.Length()] << std::endl; f.close(); LoadDocument(tempfile, false); wxRemoveFile(tempfile); for (int i = 1; i <= m_views.Length(); m_views[i++]->OnUpdate()); } void gbtGameDocument::SetCurrentProfile(int p_profile) { m_profiles[m_currentProfileList]->SetCurrent(p_profile); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } void gbtGameDocument::AddProfileList(gbtAnalysisOutput *p_profs) { m_profiles.Append(p_profs); m_currentProfileList = m_profiles.Length(); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } void gbtGameDocument::SetProfileList(int p_index) { m_currentProfileList = p_index; UpdateViews(GBT_DOC_MODIFIED_VIEWS); } /* void gbtGameDocument::AddProfiles(const Gambit::List > &p_profiles) { for (int i = 1; i <= p_profiles.Length(); i++) { m_profiles[m_currentProfileList].Append(p_profiles[i]); } m_profiles[m_currentProfileList].SetCurrent(m_profiles[m_currentProfileList].NumProfiles()); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } void gbtGameDocument::AddProfile(const Gambit::MixedBehavProfile &p_profile) { m_profiles[m_currentProfileList].Append(p_profile); m_profiles[m_currentProfileList].SetCurrent(m_profiles[m_currentProfileList].NumProfiles()); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } void gbtGameDocument::AddProfiles(const Gambit::List > &p_profiles) { for (int i = 1; i <= p_profiles.Length(); i++) { m_profiles[m_currentProfileList].Append(p_profiles[i]); } m_profiles[m_currentProfileList].SetCurrent(m_profiles[m_currentProfileList].NumProfiles()); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } void gbtGameDocument::AddProfile(const Gambit::MixedStrategyProfile &p_profile) { m_profiles[m_currentProfileList].Append(p_profile); m_profiles[m_currentProfileList].SetCurrent(m_profiles[m_currentProfileList].NumProfiles()); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } */ void gbtGameDocument::SetBehavElimStrength(bool p_strict) { m_behavSupports.SetStrict(p_strict); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } bool gbtGameDocument::NextBehavElimLevel(void) { bool ret = m_behavSupports.NextLevel(); UpdateViews(GBT_DOC_MODIFIED_VIEWS); return ret; } void gbtGameDocument::PreviousBehavElimLevel(void) { m_behavSupports.PreviousLevel(); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } void gbtGameDocument::TopBehavElimLevel(void) { m_behavSupports.TopLevel(); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } bool gbtGameDocument::CanBehavElim(void) const { return m_behavSupports.CanEliminate(); } int gbtGameDocument::GetBehavElimLevel(void) const { return m_behavSupports.GetLevel(); } void gbtGameDocument::SetStrategyElimStrength(bool p_strict) { m_stratSupports.SetStrict(p_strict); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } bool gbtGameDocument::GetStrategyElimStrength(void) const { return m_stratSupports.GetStrict(); } bool gbtGameDocument::NextStrategyElimLevel(void) { bool ret = m_stratSupports.NextLevel(); UpdateViews(GBT_DOC_MODIFIED_VIEWS); return ret; } void gbtGameDocument::PreviousStrategyElimLevel(void) { m_stratSupports.PreviousLevel(); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } void gbtGameDocument::TopStrategyElimLevel(void) { m_stratSupports.TopLevel(); UpdateViews(GBT_DOC_MODIFIED_VIEWS); } bool gbtGameDocument::CanStrategyElim(void) const { return m_stratSupports.CanEliminate(); } int gbtGameDocument::GetStrategyElimLevel(void) const { return m_stratSupports.GetLevel(); } void gbtGameDocument::SetSelectNode(Gambit::GameNode p_node) { m_selectNode = p_node; UpdateViews(GBT_DOC_MODIFIED_VIEWS); } gambit-0.2010.09.01/src/gui/gamedoc.h0000644000076500007650000002442311435216101013562 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/gamedoc.h // Declaration of game document class // // 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 GAMEDOC_H #define GAMEDOC_H #include "libgambit/libgambit.h" #include "style.h" #include "analysis.h" // This declaration essentially means the entire interface // can use the namespace unqualified using namespace Gambit; class gbtGameView; class gbtGameDocument; //! //! This class manages the "stack" of supports obtained by eliminating //! dominated actions from consideration. //! class gbtBehavDominanceStack { private: gbtGameDocument *m_doc; bool m_strict; Gambit::Array m_supports; int m_current; bool m_noFurther; public: gbtBehavDominanceStack(gbtGameDocument *p_doc, bool p_strict); ~gbtBehavDominanceStack(); //! //! Returns the number of supports in the stack //! int NumSupports(void) const { return m_supports.Length(); } //! //! Get the i'th support in the stack //! (where i=1 is always the "full" support) //! const Gambit::BehavSupport &GetSupport(int i) const { return *m_supports[i]; } //! //! Get the current support //! const Gambit::BehavSupport &GetCurrent(void) const { return *m_supports[m_current]; } //! //! Get the level of iteration (1 = no iteration) //! int GetLevel(void) const { return m_current; } //! //! Sets whether elimination is strict or weak. If this changes the //! internal setting, a Reset() is done //! void SetStrict(bool p_strict); //! //! Reset the stack by clearing out all supports //! void Reset(void); //! //! Go to the next level of iteration. Returns 'true' if successful, //! 'false' if no effect (i.e., no further actions could be eliminated) //! bool NextLevel(void); //! //! Go to the previous level of iteration. Returns 'true' if successful, //! 'false' if no effect (i.e., already at the full support) //! bool PreviousLevel(void); //! //! Go to the top level (the full support) //! void TopLevel(void) { m_current = 1; } //! //! Returns 'false' if it is known that no further eliminations can be done //! bool CanEliminate(void) const { return (m_current < m_supports.Length() || !m_noFurther); } }; //! //! This class manages the "stack" of supports obtained by eliminating //! dominated strategies from consideration. //! class gbtStrategyDominanceStack { private: gbtGameDocument *m_doc; bool m_strict; Gambit::Array m_supports; int m_current; bool m_noFurther; public: gbtStrategyDominanceStack(gbtGameDocument *p_doc, bool p_strict); ~gbtStrategyDominanceStack(); //! //! Returns the number of supports in the stack //! int NumSupports(void) const { return m_supports.Length(); } //! //! Get the i'th support in the stack //! (where i=1 is always the "full" support) //! const Gambit::StrategySupport &GetSupport(int i) const { return *m_supports[i]; } //! //! Get the current support //! const Gambit::StrategySupport &GetCurrent(void) const { return *m_supports[m_current]; } //! //! Get the level of iteration (1 = no iteration) //! int GetLevel(void) const { return m_current; } //! //! Sets whether elimination is strict or weak. If this changes the //! internal setting, a Reset() is done //! void SetStrict(bool p_strict); //! //! Gets whether elimination is strict or weak. //! bool GetStrict(void) const { return m_strict; } //! //! Reset the stack by clearing out all supports //! void Reset(void); //! //! Go to the next level of iteration. Returns 'true' if successful, //! 'false' if no effect (i.e., no further actions could be eliminated) //! bool NextLevel(void); //! //! Go to the previous level of iteration. Returns 'true' if successful, //! 'false' if no effect (i.e., already at the full support) //! bool PreviousLevel(void); //! //! Go to the top level (the full support) //! void TopLevel(void) { m_current = 1; } //! //! Returns 'false' if it is known that no further eliminations can be done //! bool CanEliminate(void) const { return (m_current < m_supports.Length() || !m_noFurther); } }; // // These are passed to gbtGameDocument::UpdateViews() to indicate which // types of modifications have occurred. // // GBT_DOC_MODIFIED_GAME: The game itself has been modified; that is, the // physical structure (number of players, number of strategies, game tree) // has changed. This requires all computed data to be deleted. // // GBT_DOC_MODIFIED_PAYOFFS: The payoffs of the game have changed, but not // the physical structure. This means that strategy profiles can, in // principle, be kept -- but they may no longer be Nash, etc. // // GBT_DOC_MODIFIED_LABELS: Labeling of players, strategies, etc. has // changed. These have no effect on the game mathematically, so computed // data may be kept; but, we want to track the label change for undo, etc. // // GBT_DOC_MODIFIED_VIEWS: Information about how the document is viewed // (e.g., player colors) has changed. We want to track this for undo, // but, again, this has no effect on the game mathematically. // typedef enum { GBT_DOC_MODIFIED_NONE = 0x00, GBT_DOC_MODIFIED_GAME = 0x01, GBT_DOC_MODIFIED_PAYOFFS = 0x02, GBT_DOC_MODIFIED_LABELS = 0x04, GBT_DOC_MODIFIED_VIEWS = 0x08 } gbtGameModificationType; class gbtGameDocument { friend class gbtGameView; private: Gambit::Array m_views; void AddView(gbtGameView *p_view) { m_views.Append(p_view); } void RemoveView(gbtGameView *p_view) { m_views.Remove(m_views.Find(p_view)); if (m_views.Length() == 0) delete this; } Gambit::Game m_game; wxString m_filename; gbtStyle m_style; Gambit::GameNode m_selectNode; bool m_modified; gbtBehavDominanceStack m_behavSupports; gbtStrategyDominanceStack m_stratSupports; Gambit::List m_profiles; int m_currentProfileList; Gambit::List m_undoList, m_redoList; public: gbtGameDocument(Gambit::Game p_game); ~gbtGameDocument(); //! //! @name Reading and writing .gbt savefiles //! //@{ /// Load document from the specified file (which should be a .gbt file) /// Returns true if successful, false if error bool LoadDocument(const wxString &p_filename, bool p_saveUndo = true); void SaveDocument(std::ostream &) const; //@} Gambit::Game GetGame(void) const { return m_game; } void BuildNfg(void); const wxString &GetFilename(void) const { return m_filename; } void SetFilename(const wxString &p_filename) { m_filename = p_filename; } bool IsModified(void) const { return m_modified; } void SetModified(bool p_modified) { m_modified = p_modified; } gbtStyle &GetStyle(void) { return m_style; } int NumPlayers(void) const { return m_game->NumPlayers(); } bool IsConstSum(void) const { return m_game->IsConstSum(); } bool IsTree(void) const { return m_game->IsTree(); } //! //! @name Handling of undo/redo features //! //@{ bool CanUndo(void) const { return (m_undoList.Length() > 1); } void Undo(void); bool CanRedo(void) const { return (m_redoList.Length() > 0); } void Redo(void); //@} //! //! @name Handling of list of computed profiles //! //@{ const gbtAnalysisOutput &GetProfiles(void) const { return *m_profiles[m_currentProfileList]; } const gbtAnalysisOutput &GetProfiles(int p_index) const { return *m_profiles[p_index]; } void AddProfileList(gbtAnalysisOutput *); void SetProfileList(int p_index); int NumProfileLists(void) const { return m_profiles.Length(); } int GetCurrentProfileList(void) const { return m_currentProfileList; } int GetCurrentProfile(void) const { return (m_profiles.Length() == 0) ? 0 : GetProfiles().GetCurrent(); } void SetCurrentProfile(int p_profile); /* void AddProfiles(const Gambit::List > &); void AddProfile(const Gambit::MixedBehavProfile &); void AddProfiles(const Gambit::List > &); void AddProfile(const Gambit::MixedStrategyProfile &); */ //@} //! //! @name Handling of behavior supports //! //@{ const Gambit::BehavSupport &GetEfgSupport(void) const { return m_behavSupports.GetCurrent(); } void SetBehavElimStrength(bool p_strict); bool NextBehavElimLevel(void); void PreviousBehavElimLevel(void); void TopBehavElimLevel(void); bool CanBehavElim(void) const; int GetBehavElimLevel(void) const; //@} //! //! @name Handling of strategy supports //! //@{ const Gambit::StrategySupport &GetNfgSupport(void) const { return m_stratSupports.GetCurrent(); } void SetStrategyElimStrength(bool p_strict); bool GetStrategyElimStrength(void) const; bool NextStrategyElimLevel(void); void PreviousStrategyElimLevel(void); void TopStrategyElimLevel(void); bool CanStrategyElim(void) const; int GetStrategyElimLevel(void) const; //@} Gambit::GameNode GetSelectNode(void) const { return m_selectNode; } void SetSelectNode(Gambit::GameNode); void UpdateViews(gbtGameModificationType p_modifications); /// Call to ask viewers to post any pending changes void PostPendingChanges(void); }; class gbtGameView { protected: gbtGameDocument *m_doc; public: gbtGameView(gbtGameDocument *p_doc) : m_doc(p_doc) { m_doc->AddView(this); } virtual ~gbtGameView() { m_doc->RemoveView(this); } virtual void OnUpdate(void) = 0; /// Post any pending changes in the viewer to the document virtual void PostPendingChanges(void) { } gbtGameDocument *GetDocument(void) const { return m_doc; } }; #endif // GAMEDOC_H gambit-0.2010.09.01/src/gui/gameframe.cc0000644000076500007650000013077111441446351014262 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/gameframe.cc // Implementation of frame containing views of a game // // 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 #include #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include #include #if !defined(__WXMSW__) || wxUSE_POSTSCRIPT #include #endif // !defined(__WXMSW__) || wxUSE_POSTSCRIPT #include #include "libgambit/libgambit.h" #include "gambit.h" // for wxGetApp() #include "gameframe.h" #include "menuconst.h" #include "efgpanel.h" #include "efgprofile.h" #include "nfgpanel.h" #include "nfgprofile.h" #include "dlgameprop.h" #include "dlnash.h" #include "dlnashmon.h" #include "dlefglogit.h" #include "dlabout.h" #include "dlinsertmove.h" #include "dlefgreveal.h" #include "dleditnode.h" #include "dleditmove.h" #include "dlefglayout.h" #include "dlefglegend.h" //===================================================================== // class gbtProfileListPanel //===================================================================== class gbtProfileListPanel : public wxPanel, public gbtGameView { private: wxWindow *m_behavProfiles, *m_mixedProfiles; void OnUpdate(void) { } public: gbtProfileListPanel(wxWindow *p_parent, gbtGameDocument *p_doc); void ShowMixed(bool p_show); }; gbtProfileListPanel::gbtProfileListPanel(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, -1), gbtGameView(p_doc) { wxBoxSizer *topSizer = new wxBoxSizer(wxHORIZONTAL); if (p_doc->IsTree()) { m_behavProfiles = new gbtBehavProfileList(this, p_doc); m_behavProfiles->Show(false); topSizer->Add(m_behavProfiles, 1, wxEXPAND, 0); } else { m_behavProfiles = 0; } m_mixedProfiles = new gbtMixedProfileList(this, p_doc); m_mixedProfiles->Show(false); topSizer->Add(m_mixedProfiles, 1, wxEXPAND, 0); SetSizer(topSizer); Layout(); } void gbtProfileListPanel::ShowMixed(bool p_show) { m_mixedProfiles->Show(p_show); GetSizer()->Show(m_mixedProfiles, p_show); if (m_behavProfiles) { m_behavProfiles->Show(!p_show); GetSizer()->Show(m_behavProfiles, !p_show); } Layout(); } //===================================================================== // class gbtAnalysisNotebook //===================================================================== class gbtAnalysisNotebook : public wxPanel, public gbtGameView { private: gbtProfileListPanel *m_profiles; wxChoice *m_choices; wxStaticText *m_description; void OnChoice(wxCommandEvent &); void OnUpdate(void); public: gbtAnalysisNotebook(wxWindow *p_parent, gbtGameDocument *p_doc); void ShowMixed(bool p_show); }; gbtAnalysisNotebook::gbtAnalysisNotebook(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, -1), gbtGameView(p_doc) { m_choices = new wxChoice(this, -1); m_choices->Append(wxT("Profiles")); m_choices->SetSelection(0); Connect(m_choices->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(gbtAnalysisNotebook::OnChoice)); m_description = new wxStaticText(this, wxID_STATIC, wxT("")); m_profiles = new gbtProfileListPanel(this, p_doc); wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *horizSizer = new wxBoxSizer(wxHORIZONTAL); horizSizer->Add(m_choices, 0, wxALL | wxALIGN_CENTER, 5); horizSizer->Add(m_description, 1, wxALL | wxALIGN_CENTER, 5); topSizer->Add(horizSizer, 0, wxEXPAND, 0); topSizer->Add(m_profiles, 1, wxEXPAND, 0); SetSizer(topSizer); Layout(); } void gbtAnalysisNotebook::ShowMixed(bool p_show) { m_profiles->ShowMixed(p_show); } void gbtAnalysisNotebook::OnChoice(wxCommandEvent &p_event) { m_doc->SetProfileList(p_event.GetSelection() + 1); } void gbtAnalysisNotebook::OnUpdate(void) { m_choices->Clear(); for (int i = 1; i <= m_doc->NumProfileLists(); i++) { m_choices->Append(wxString::Format(wxT("Profiles %d"), i)); } m_choices->SetSelection(m_doc->GetCurrentProfileList() - 1); if (m_doc->GetCurrentProfileList() > 0) { m_description->SetLabel(m_doc->GetProfiles().GetDescription()); } } //===================================================================== // Implementation of class gbtGameFrame //===================================================================== BEGIN_EVENT_TABLE(gbtGameFrame, wxFrame) EVT_MENU(GBT_MENU_FILE_NEW_EFG, gbtGameFrame::OnFileNewEfg) EVT_MENU(GBT_MENU_FILE_NEW_NFG, gbtGameFrame::OnFileNewNfg) EVT_MENU(wxID_OPEN, gbtGameFrame::OnFileOpen) EVT_MENU(wxID_CLOSE, gbtGameFrame::OnFileClose) EVT_MENU(wxID_SAVE, gbtGameFrame::OnFileSave) EVT_MENU(wxID_SAVEAS, gbtGameFrame::OnFileSave) EVT_MENU(GBT_MENU_FILE_EXPORT_EFG, gbtGameFrame::OnFileExportEfg) EVT_MENU(GBT_MENU_FILE_EXPORT_NFG, gbtGameFrame::OnFileExportNfg) EVT_MENU(GBT_MENU_FILE_EXPORT_BMP, gbtGameFrame::OnFileExportGraphic) EVT_MENU(GBT_MENU_FILE_EXPORT_JPEG, gbtGameFrame::OnFileExportGraphic) EVT_MENU(GBT_MENU_FILE_EXPORT_PNG, gbtGameFrame::OnFileExportGraphic) EVT_MENU(GBT_MENU_FILE_EXPORT_POSTSCRIPT, gbtGameFrame::OnFileExportPS) EVT_MENU(GBT_MENU_FILE_EXPORT_SVG, gbtGameFrame::OnFileExportSVG) EVT_MENU(wxID_PRINT_SETUP, gbtGameFrame::OnFilePageSetup) EVT_MENU(wxID_PREVIEW, gbtGameFrame::OnFilePrintPreview) EVT_MENU(wxID_PRINT, gbtGameFrame::OnFilePrint) EVT_MENU(wxID_EXIT, gbtGameFrame::OnFileExit) EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, gbtGameFrame::OnFileMRUFile) EVT_MENU(wxID_UNDO, gbtGameFrame::OnEditUndo) EVT_MENU(wxID_REDO, gbtGameFrame::OnEditRedo) EVT_MENU(GBT_MENU_EDIT_INSERT_MOVE, gbtGameFrame::OnEditInsertMove) EVT_MENU(GBT_MENU_EDIT_INSERT_ACTION, gbtGameFrame::OnEditInsertAction) EVT_MENU(GBT_MENU_EDIT_DELETE_TREE, gbtGameFrame::OnEditDeleteTree) EVT_MENU(GBT_MENU_EDIT_DELETE_PARENT, gbtGameFrame::OnEditDeleteParent) EVT_MENU(GBT_MENU_EDIT_REMOVE_OUTCOME, gbtGameFrame::OnEditRemoveOutcome) EVT_MENU(GBT_MENU_EDIT_REVEAL, gbtGameFrame::OnEditReveal) EVT_MENU(GBT_MENU_EDIT_NODE, gbtGameFrame::OnEditNode) EVT_MENU(GBT_MENU_EDIT_MOVE, gbtGameFrame::OnEditMove) EVT_MENU(GBT_MENU_EDIT_GAME, gbtGameFrame::OnEditGame) EVT_MENU(GBT_MENU_EDIT_NEWPLAYER, gbtGameFrame::OnEditNewPlayer) EVT_MENU(GBT_MENU_VIEW_PROFILES, gbtGameFrame::OnViewProfiles) EVT_MENU(GBT_MENU_VIEW_ZOOMIN, gbtGameFrame::OnViewZoom) EVT_MENU(GBT_MENU_VIEW_ZOOMOUT, gbtGameFrame::OnViewZoom) EVT_MENU(GBT_MENU_VIEW_ZOOMFIT, gbtGameFrame::OnViewZoom) EVT_MENU(GBT_MENU_VIEW_ZOOM100, gbtGameFrame::OnViewZoom) EVT_MENU(GBT_MENU_VIEW_STRATEGIC, gbtGameFrame::OnViewStrategic) EVT_MENU(GBT_MENU_FORMAT_FONTS, gbtGameFrame::OnFormatFonts) EVT_MENU(GBT_MENU_FORMAT_LAYOUT, gbtGameFrame::OnFormatLayout) EVT_MENU(GBT_MENU_FORMAT_LABELS, gbtGameFrame::OnFormatLabels) EVT_MENU(GBT_MENU_FORMAT_DECIMALS_ADD, gbtGameFrame::OnFormatDecimalsAdd) EVT_MENU(GBT_MENU_FORMAT_DECIMALS_DELETE, gbtGameFrame::OnFormatDecimalsDelete) EVT_MENU(GBT_MENU_TOOLS_DOMINANCE, gbtGameFrame::OnToolsDominance) EVT_MENU(GBT_MENU_TOOLS_EQUILIBRIUM, gbtGameFrame::OnToolsEquilibrium) EVT_MENU(GBT_MENU_TOOLS_QRE, gbtGameFrame::OnToolsQre) EVT_MENU(wxID_ABOUT, gbtGameFrame::OnHelpAbout) EVT_CLOSE(gbtGameFrame::OnCloseWindow) END_EVENT_TABLE() //--------------------------------------------------------------------- // gbtGameFrame: Constructor and destructor //--------------------------------------------------------------------- gbtGameFrame::gbtGameFrame(wxWindow *p_parent, gbtGameDocument *p_doc) : wxFrame(p_parent, -1, _T(""), wxDefaultPosition, wxSize(800, 600)), gbtGameView(p_doc) { #if defined( __WXMSW__) SetIcon(wxIcon(wxT("efg_icn"))); #else #include "bitmaps/gambit.xpm" SetIcon(wxIcon(gambit_xpm)); #endif CreateStatusBar(); MakeMenus(); MakeToolbar(); wxAcceleratorEntry entries[10]; entries[0].Set(wxACCEL_CTRL, (int) 'o', wxID_OPEN); entries[1].Set(wxACCEL_CTRL, (int) 's', wxID_SAVE); entries[2].Set(wxACCEL_CTRL | wxACCEL_SHIFT, (int) 's', wxID_SAVEAS); entries[3].Set(wxACCEL_CTRL, (int) 'p', wxID_PRINT); entries[4].Set(wxACCEL_CTRL, (int) 'w', wxID_CLOSE); entries[5].Set(wxACCEL_CTRL, (int) 'x', wxID_EXIT); entries[6].Set(wxACCEL_CTRL, (int) 'z', wxID_UNDO); entries[7].Set(wxACCEL_CTRL, (int) 'y', wxID_REDO); // entries[8].Set(wxACCEL_NORMAL, WXK_DELETE, GBT_MENU_EDIT_DELETE_TREE); //entries[9].Set(wxACCEL_NORMAL, WXK_BACK, GBT_MENU_EDIT_DELETE_PARENT); entries[8].Set(wxACCEL_CTRL, (int) '+', GBT_MENU_VIEW_ZOOMIN); entries[9].Set(wxACCEL_CTRL, (int) '-', GBT_MENU_VIEW_ZOOMOUT); wxAcceleratorTable accel(10, entries); SetAcceleratorTable(accel); m_splitter = new wxSplitterWindow(this, -1); if (p_doc->IsTree()) { m_efgPanel = new gbtEfgPanel(m_splitter, p_doc); } else { m_efgPanel = 0; } m_nfgPanel = new gbtNfgPanel(m_splitter, p_doc); if (p_doc->IsTree()) { m_nfgPanel->Show(false); } m_analysisPanel = new gbtAnalysisNotebook(m_splitter, p_doc); m_analysisPanel->Show(false); if (p_doc->IsTree()) { m_splitter->Initialize(m_efgPanel); } else { m_splitter->Initialize(m_nfgPanel); } m_splitter->SetSashGravity(0.5); m_splitter->SetMinimumPaneSize(200); Connect(m_splitter->GetId(), wxEVT_COMMAND_SPLITTER_UNSPLIT, wxSplitterEventHandler(gbtGameFrame::OnUnsplit)); wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); topSizer->Add(m_splitter, 1, wxEXPAND, 0); SetSizer(topSizer); Layout(); if (p_doc->IsTree()) { m_efgPanel->SetFocus(); } else { m_nfgPanel->SetFocus(); } Show(true); m_doc->UpdateViews(GBT_DOC_MODIFIED_NONE); } gbtGameFrame::~gbtGameFrame() { wxGetApp().RemoveMenu(GetMenuBar()->GetMenu(0)); } void gbtGameFrame::OnUpdate(void) { std::string gameTitle; gameTitle = m_doc->GetGame()->GetTitle(); if (m_doc->GetFilename() != wxT("")) { SetTitle(wxT("Gambit - [") + m_doc->GetFilename() + wxT("] ") + wxString(gameTitle.c_str(), *wxConvCurrent)); } else { SetTitle(wxT("Gambit - ") + wxString(gameTitle.c_str(), *wxConvCurrent)); } if (m_doc->IsModified()) { SetTitle(GetTitle() + wxT(" (unsaved changes)")); } Gambit::GameNode selectNode = m_doc->GetSelectNode(); wxMenuBar *menuBar = GetMenuBar(); menuBar->Enable(GBT_MENU_FILE_EXPORT_EFG, m_doc->IsTree()); menuBar->Enable(wxID_UNDO, m_doc->CanUndo()); GetToolBar()->EnableTool(wxID_UNDO, m_doc->CanUndo()); menuBar->Enable(wxID_REDO, m_doc->CanRedo()); GetToolBar()->EnableTool(wxID_REDO, m_doc->CanRedo()); menuBar->Enable(GBT_MENU_EDIT_INSERT_MOVE, selectNode); menuBar->Enable(GBT_MENU_EDIT_INSERT_ACTION, selectNode && selectNode->GetInfoset()); menuBar->Enable(GBT_MENU_EDIT_REVEAL, selectNode && selectNode->GetInfoset()); menuBar->Enable(GBT_MENU_EDIT_DELETE_TREE, selectNode && selectNode->NumChildren() > 0); menuBar->Enable(GBT_MENU_EDIT_DELETE_PARENT, selectNode && selectNode->GetParent()); menuBar->Enable(GBT_MENU_EDIT_REMOVE_OUTCOME, selectNode && selectNode->GetOutcome()); menuBar->Enable(GBT_MENU_EDIT_NODE, selectNode); menuBar->Enable(GBT_MENU_EDIT_MOVE, selectNode && selectNode->GetInfoset()); GetToolBar()->EnableTool(GBT_MENU_EDIT_NEWPLAYER, !m_efgPanel || m_efgPanel->IsShown()); menuBar->Enable(GBT_MENU_VIEW_PROFILES, m_doc->NumProfileLists() > 0); GetToolBar()->EnableTool(GBT_MENU_VIEW_PROFILES, m_doc->NumProfileLists() > 0); GetToolBar()->EnableTool(GBT_MENU_FORMAT_DECIMALS_DELETE, m_doc->GetStyle().NumDecimals() > 1); if (m_doc->NumProfileLists() == 0 && m_splitter->IsSplit()) { m_splitter->Unsplit(m_analysisPanel); } menuBar->Check(GBT_MENU_VIEW_PROFILES, m_splitter->IsSplit()); GetToolBar()->ToggleTool(GBT_MENU_VIEW_PROFILES, m_splitter->IsSplit()); menuBar->Enable(GBT_MENU_VIEW_ZOOMIN, m_efgPanel && m_efgPanel->IsShown()); menuBar->Enable(GBT_MENU_VIEW_ZOOMOUT, m_efgPanel && m_efgPanel->IsShown()); } //-------------------------------------------------------------------- // gbtGameFrame: Creating and updating menus and toolbar //-------------------------------------------------------------------- #include "bitmaps/about.xpm" #include "bitmaps/adddecimal.xpm" #include "bitmaps/calc.xpm" #include "bitmaps/close.xpm" #include "bitmaps/deldecimal.xpm" #include "bitmaps/exit.xpm" #include "bitmaps/font.xpm" #include "bitmaps/label.xpm" #include "bitmaps/layout.xpm" #include "bitmaps/newplayer.xpm" #include "bitmaps/newtable.xpm" #include "bitmaps/newtree.xpm" #include "bitmaps/open.xpm" #include "bitmaps/preview.xpm" #include "bitmaps/print.xpm" #include "bitmaps/profiles.xpm" #include "bitmaps/redo.xpm" #include "bitmaps/save.xpm" #include "bitmaps/saveas.xpm" #include "bitmaps/table.xpm" #include "bitmaps/undo.xpm" #include "bitmaps/zoomfit.xpm" #include "bitmaps/zoomin.xpm" #include "bitmaps/zoomout.xpm" #include "bitmaps/zoom1.xpm" // // wxWidgets does not appear to offer a method for easily creating // a menu item with a bitmap, so we write this convenience function // to simplify the process. // // The bitmaps have currently been disabled, since they really // don't look so great. // static void AppendBitmapItem(wxMenu *p_menu, int p_id, const wxString &p_label, const wxString &p_helpString, const wxBitmap &p_bitmap) { wxMenuItem *item = new wxMenuItem(p_menu, p_id, p_label, p_helpString); #ifdef UNUSED // wxMac does not (apparently) support adding bitmaps to menu items, // so we do not set the bitmap in this case. item->SetBitmap(p_bitmap); #endif // !__WXMAC__ p_menu->Append(item); } void gbtGameFrame::MakeMenus(void) { wxMenu *fileMenu = new wxMenu; wxMenu *fileNewMenu = new wxMenu; AppendBitmapItem(fileNewMenu, GBT_MENU_FILE_NEW_EFG, _("&Extensive game"), _("Create a new extensive (tree) game"), wxBitmap(newtree_xpm)); AppendBitmapItem(fileNewMenu, GBT_MENU_FILE_NEW_NFG, _("&Strategic game"), _("Create a new strategic (table) game"), wxBitmap(newtable_xpm)); fileMenu->Append(wxID_NEW, _("&New"), fileNewMenu, _("Create a new game")); AppendBitmapItem(fileMenu, wxID_OPEN, _("&Open\tCtrl-O"), _("Open a saved game"), wxBitmap(open_xpm)); fileMenu->AppendSeparator(); AppendBitmapItem(fileMenu, wxID_SAVE, _("&Save\tCtrl-S"), _("Save this game"), wxBitmap(save_xpm)); AppendBitmapItem(fileMenu, wxID_SAVEAS, _("Save &as\tShift-Ctrl-S"), _("Save game to a different file"), wxBitmap(saveas_xpm)); fileMenu->AppendSeparator(); wxMenu *fileExportMenu = new wxMenu; fileExportMenu->Append(GBT_MENU_FILE_EXPORT_EFG, _("Gambit .&efg format"), _("Save the extensive game in .efg format")); fileExportMenu->Append(GBT_MENU_FILE_EXPORT_NFG, _("Gambit .&nfg format"), _("Save the strategic game in .nfg format")); fileExportMenu->AppendSeparator(); fileExportMenu->Append(GBT_MENU_FILE_EXPORT_BMP, _("&BMP"), _("Save a rendering of the game as a Windows bitmap")); fileExportMenu->Append(GBT_MENU_FILE_EXPORT_JPEG, _("&JPEG"), _("Save a rendering of the game as a JPEG image")); fileExportMenu->Append(GBT_MENU_FILE_EXPORT_PNG, _("&PNG"), _("Save a rendering of the game as a PNG image")); fileExportMenu->Append(GBT_MENU_FILE_EXPORT_POSTSCRIPT, _("Post&Script"), _("Save a printout of the game in PostScript format")); fileExportMenu->Enable(GBT_MENU_FILE_EXPORT_POSTSCRIPT, wxUSE_POSTSCRIPT); fileExportMenu->Append(GBT_MENU_FILE_EXPORT_SVG, _("S&VG"), _("Save a rendering of the game in SVG format")); fileMenu->Append(GBT_MENU_FILE_EXPORT, _("&Export"), fileExportMenu, _("Export the game in various formats")); fileMenu->AppendSeparator(); fileMenu->Append(wxID_PRINT_SETUP, _("Page Se&tup"), _("Set up preferences for printing")); AppendBitmapItem(fileMenu, wxID_PREVIEW, _("Print Pre&view"), _("View a preview of the game printout"), wxBitmap(preview_xpm)); AppendBitmapItem(fileMenu, wxID_PRINT, _("&Print\tCtrl-P"), _("Print this game"), wxBitmap(print_xpm)); fileMenu->AppendSeparator(); AppendBitmapItem(fileMenu, wxID_CLOSE, _("&Close\tCtrl-W"), _("Close this window"), wxBitmap(close_xpm)); AppendBitmapItem(fileMenu, wxID_EXIT, _("E&xit\tCtrl-Q"), _("Exit Gambit"), wxBitmap(exit_xpm)); wxMenu *editMenu = new wxMenu; AppendBitmapItem(editMenu, wxID_UNDO, _("&Undo\tCtrl-Z"), _("Undo the last change"), wxBitmap(undo_xpm)); AppendBitmapItem(editMenu, wxID_REDO, _("&Redo\tCtrl-Y"), _("Redo the last undone change"), wxBitmap(redo_xpm)); editMenu->AppendSeparator(); AppendBitmapItem(editMenu, GBT_MENU_EDIT_NEWPLAYER, _("Add p&layer"), _("Add a new player to the game"), wxBitmap(newplayer_xpm)); editMenu->AppendSeparator(); editMenu->Append(GBT_MENU_EDIT_INSERT_MOVE, _("&Insert move"), _("Insert a move")); editMenu->Append(GBT_MENU_EDIT_INSERT_ACTION, _("Insert &action"), _("Insert an action at the current move")); editMenu->Append(GBT_MENU_EDIT_REVEAL, _("&Reveal"), _("Reveal choice at node")); editMenu->AppendSeparator(); editMenu->Append(GBT_MENU_EDIT_DELETE_TREE, _("&Delete subtree"), _("Delete the subtree starting at the selected node")); editMenu->Append(GBT_MENU_EDIT_DELETE_PARENT, _("Delete &parent"), _("Delete the node directly before the selected node")); editMenu->Append(GBT_MENU_EDIT_REMOVE_OUTCOME, _("Remove &outcome"), _("Remove the outcome from the selected node")); editMenu->AppendSeparator(); editMenu->Append(GBT_MENU_EDIT_NODE, _("&Node"), _("Edit properties of the node")); editMenu->Append(GBT_MENU_EDIT_MOVE, _("&Move"), _("Edit properties of the move")); editMenu->AppendSeparator(); editMenu->Append(GBT_MENU_EDIT_GAME, _("&Game"), _("Edit properties of the game")); wxMenu *viewMenu = new wxMenu; viewMenu->Append(GBT_MENU_VIEW_PROFILES, _("&Profiles"), _("Display/hide profiles window"), true); viewMenu->Check(GBT_MENU_VIEW_PROFILES, false); viewMenu->AppendSeparator(); AppendBitmapItem(viewMenu, GBT_MENU_VIEW_ZOOMIN, _("Zoom &in"), _("Increase display magnification"), wxBitmap(zoomin_xpm)); AppendBitmapItem(viewMenu, GBT_MENU_VIEW_ZOOMOUT, _("Zoom &out"), _("Decrease display magnification"), wxBitmap(zoomout_xpm)); AppendBitmapItem(viewMenu, GBT_MENU_VIEW_ZOOM100, _("&Zoom 1:1"), _("Set magnification to 1:1"), wxBitmap(zoom1_xpm)); AppendBitmapItem(viewMenu, GBT_MENU_VIEW_ZOOMFIT, _("&Fit tree to window"), _("Rescale to show entire tree in window"), wxBitmap(zoomfit_xpm)); viewMenu->AppendSeparator(); viewMenu->Append(GBT_MENU_VIEW_STRATEGIC, _("&Strategic game"), _("Display the reduced strategic representation " "of the game"), true); wxMenu *formatMenu = new wxMenu; AppendBitmapItem(formatMenu, GBT_MENU_FORMAT_LAYOUT, _("&Layout"), _("Set tree layout parameters"), wxBitmap(layout_xpm)); AppendBitmapItem(formatMenu, GBT_MENU_FORMAT_LABELS, _("La&bels"), _("Set labels for parts of trees"), wxBitmap(label_xpm)); AppendBitmapItem(formatMenu, GBT_MENU_FORMAT_FONTS, _("&Font"), _("Set the font for tree labels"), wxBitmap(font_xpm)); wxMenu *toolsMenu = new wxMenu; toolsMenu->Append(GBT_MENU_TOOLS_DOMINANCE, _("&Dominance"), _("Find undominated actions"), true); AppendBitmapItem(toolsMenu, GBT_MENU_TOOLS_EQUILIBRIUM, _("&Equilibrium"), _("Compute Nash equilibria and refinements"), wxBitmap(calc_xpm)); toolsMenu->Append(GBT_MENU_TOOLS_QRE, _("&Qre"), _("Compute quantal response equilibria")); wxMenu *helpMenu = new wxMenu; AppendBitmapItem(helpMenu, wxID_ABOUT, _("&About"), _("About Gambit"), wxBitmap(about_xpm)); wxMenuBar *menuBar = new wxMenuBar(); menuBar->Append(fileMenu, _("&File")); menuBar->Append(editMenu, _("&Edit")); menuBar->Append(viewMenu, _("&View")); menuBar->Append(formatMenu, _("&Format")); menuBar->Append(toolsMenu, _("&Tools")); menuBar->Append(helpMenu, _("&Help")); // Set the menu bar SetMenuBar(menuBar); wxGetApp().AddMenu(GetMenuBar()->GetMenu(0)); } void gbtGameFrame::MakeToolbar(void) { wxToolBar *toolBar = CreateToolBar(wxTB_HORIZONTAL | wxTB_FLAT); toolBar->SetMargins(4, 4); toolBar->SetToolBitmapSize(wxSize(24, 24)); toolBar->AddTool(GBT_MENU_FILE_NEW_EFG, wxBitmap(newtree_xpm), wxNullBitmap, false, -1, -1, 0, _("Create a new extensive (tree) game"), _("Create a new extensive (tree) game")); toolBar->AddTool(GBT_MENU_FILE_NEW_NFG, wxBitmap(newtable_xpm), wxNullBitmap, false, -1, -1, 0, _("Create a new strategic (table) game"), _("Create a new strategic (table) game")); toolBar->AddTool(wxID_OPEN, wxBitmap(open_xpm), wxNullBitmap, false, -1, -1, 0, _("Open a file"), _("Open a saved game")); toolBar->AddTool(wxID_SAVE, wxBitmap(save_xpm), wxNullBitmap, false, -1, -1, 0, _("Save this game"), _("Save this game")); toolBar->AddTool(wxID_SAVEAS, wxBitmap(saveas_xpm), wxNullBitmap, false, -1, -1, 0, _("Save to a different file"), _("Save this game to another file")); toolBar->AddSeparator(); toolBar->AddTool(wxID_PRINT, wxBitmap(print_xpm), wxNullBitmap, false, -1, -1, 0, _("Print this game"), _("Print this game")); toolBar->AddTool(wxID_PREVIEW, wxBitmap(preview_xpm), wxNullBitmap, false, -1, -1, 0, _("Print preview"), _("View a preview of the game printout")); toolBar->AddSeparator(); toolBar->AddTool(wxID_UNDO, wxBitmap(undo_xpm), wxNullBitmap, false, -1, -1, 0, _("Undo the last action"), _("Undo the last change to the game")); toolBar->AddTool(wxID_REDO, wxBitmap(redo_xpm), wxNullBitmap, false, -1, -1, 0, _("Redo the undone action"), _("Redo the last undone change")); toolBar->AddSeparator(); toolBar->AddTool(GBT_MENU_EDIT_NEWPLAYER, wxBitmap(newplayer_xpm), wxNullBitmap, false, -1, -1, 0, _("Add a new player"), _("Add a new player to the game")); if (m_doc->IsTree()) { toolBar->AddTool(GBT_MENU_VIEW_ZOOMIN, wxBitmap(zoomin_xpm), wxNullBitmap, false, -1, -1, 0, _("Zoom in"), _("Increase magnification")); toolBar->AddTool(GBT_MENU_VIEW_ZOOMOUT, wxBitmap(zoomout_xpm), wxNullBitmap, false, -1, -1, 0, _("Zoom out"), _("Decrease magnification")); toolBar->AddTool(GBT_MENU_VIEW_ZOOMFIT, wxBitmap(zoomfit_xpm), wxNullBitmap, false, -1, -1, 0, _("Fit to window"), _("Set magnification to see entire tree")); } toolBar->AddSeparator(); toolBar->AddTool(GBT_MENU_FORMAT_DECIMALS_ADD, wxBitmap(adddecimal_xpm), wxNullBitmap, false, -1, -1, 0, _("Increase the number of decimals displayed"), _("Increase the number of decimal places shown")); toolBar->AddTool(GBT_MENU_FORMAT_DECIMALS_DELETE, wxBitmap(deldecimal_xpm), wxNullBitmap, false, -1, -1, 0, _("Decrease the number of decimals displayed"), _("Decrease the number of decimal places shown")); toolBar->AddSeparator(); if (m_doc->IsTree()) { toolBar->AddTool(GBT_MENU_VIEW_STRATEGIC, wxBitmap(table_xpm), wxNullBitmap, true, -1, -1, 0, _("Display the reduced strategic representation " "of the game"), _("Display the reduced strategic representation " "of the game")); } toolBar->AddTool(GBT_MENU_VIEW_PROFILES, wxBitmap(profiles_xpm), wxNullBitmap, true, -1, -1, 0, _("View the list of computed strategy profiles"), _("Show or hide the list of computed strategy profiles")); toolBar->AddTool(GBT_MENU_TOOLS_EQUILIBRIUM, wxBitmap(calc_xpm), wxNullBitmap, false, -1, -1, 0, _("Compute Nash equilibria of this game"), _("Compute Nash equilibria of this game")); toolBar->AddSeparator(); toolBar->AddTool(wxID_ABOUT, wxBitmap(about_xpm), wxNullBitmap, false, -1, -1, 0, _("About Gambit"), _("About Gambit")); toolBar->Realize(); toolBar->SetRows(1); } //---------------------------------------------------------------------- // gbtGameFrame: Menu handlers - File menu //---------------------------------------------------------------------- void gbtGameFrame::OnFileNewEfg(wxCommandEvent &) { Gambit::Game efg = new Gambit::GameRep; efg->SetTitle("Untitled Extensive Game"); efg->NewPlayer()->SetLabel("Player 1"); efg->NewPlayer()->SetLabel("Player 2"); gbtGameDocument *doc = new gbtGameDocument(efg); (void) new gbtGameFrame(0, doc); } void gbtGameFrame::OnFileNewNfg(wxCommandEvent &) { Gambit::Array dim(2); dim[1] = 2; dim[2] = 2; Gambit::Game nfg = new Gambit::GameRep(dim); nfg->SetTitle("Untitled Strategic Game"); nfg->GetPlayer(1)->SetLabel("Player 1"); nfg->GetPlayer(2)->SetLabel("Player 2"); gbtGameDocument *doc = new gbtGameDocument(nfg); (void) new gbtGameFrame(0, doc); } void gbtGameFrame::OnFileOpen(wxCommandEvent &) { wxFileDialog dialog(this, _("Choose file to open"), wxGetApp().GetCurrentDir(), _T(""), _("Gambit workbooks (*.gbt)|*.gbt|" "Gambit extensive games (*.efg)|*.efg|" "Gambit strategic games (*.nfg)|*.nfg|" "All files (*.*)|*.*")); if (dialog.ShowModal() == wxID_OK) { wxString filename = dialog.GetPath(); wxGetApp().SetCurrentDir(wxPathOnly(filename)); wxConfig config(_T("Gambit")); config.Write(_T("/General/CurrentDirectory"), wxPathOnly(filename)); gbtAppLoadResult result = wxGetApp().LoadFile(filename); if (result == GBT_APP_OPEN_FAILED) { wxMessageDialog dialog(this, wxT("Gambit could not open file '") + filename + wxT("' for reading."), wxT("Unable to open file"), wxOK | wxICON_ERROR); dialog.ShowModal(); } else if (result == GBT_APP_PARSE_FAILED) { wxMessageDialog dialog(this, wxT("File '") + filename + wxT("' is not in a format Gambit recognizes."), wxT("Unable to read file"), wxOK | wxICON_ERROR); dialog.ShowModal(); } } } void gbtGameFrame::OnFileClose(wxCommandEvent &) { Close(); } void gbtGameFrame::OnFileSave(wxCommandEvent &p_event) { if (p_event.GetId() == wxID_SAVEAS || m_doc->GetFilename() == wxT("")) { wxFileDialog dialog(this, _("Choose file"), wxPathOnly(m_doc->GetFilename()), wxFileNameFromPath(m_doc->GetFilename()), wxT("Gambit workbooks (*.gbt)|*.gbt|" "All files (*.*)|*.*"), wxSAVE | wxOVERWRITE_PROMPT); if (dialog.ShowModal() == wxID_OK) { m_doc->SetFilename(dialog.GetPath()); } else { return; } } std::ofstream file((const char *) m_doc->GetFilename().mb_str()); m_doc->SaveDocument(file); m_doc->SetModified(false); m_doc->UpdateViews(GBT_DOC_MODIFIED_NONE); } void gbtGameFrame::OnFilePageSetup(wxCommandEvent &) { wxPageSetupDialog dialog(this, &m_pageSetupData); m_printData.SetOrientation(wxLANDSCAPE); if (dialog.ShowModal() == wxID_OK) { m_printData = dialog.GetPageSetupDialogData().GetPrintData(); m_pageSetupData = dialog.GetPageSetupDialogData(); } } void gbtGameFrame::OnFilePrintPreview(wxCommandEvent &) { wxPrintDialogData data(m_printData); wxPrintPreview *preview = 0; if (m_efgPanel && m_splitter->GetWindow1() == m_efgPanel) { preview = new wxPrintPreview(m_efgPanel->GetPrintout(), m_efgPanel->GetPrintout(), &data); } else { preview = new wxPrintPreview(m_nfgPanel->GetPrintout(), m_nfgPanel->GetPrintout(), &data); } if (!preview->Ok()) { delete preview; return; } wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _("Print Preview"), wxPoint(100, 100), wxSize(600, 650)); frame->Initialize(); frame->Show(true); } void gbtGameFrame::OnFilePrint(wxCommandEvent &) { wxPrintDialogData data(m_printData); wxPrinter printer(&data); wxPrintout *printout; if (m_efgPanel && m_splitter->GetWindow1() == m_efgPanel) { printout = m_efgPanel->GetPrintout(); } else { printout = m_nfgPanel->GetPrintout(); } if (!printer.Print(this, printout, true)) { if (wxPrinter::GetLastError() == wxPRINTER_ERROR) { wxMessageBox(_("There was an error in printing"), _("Error"), wxOK); } // Otherwise, user hit "cancel"; just be quiet and return. return; } else { m_printData = printer.GetPrintDialogData().GetPrintData(); } } void gbtGameFrame::OnFileExportEfg(wxCommandEvent &) { wxFileDialog dialog(this, _("Choose file"), wxGetApp().GetCurrentDir(), _T(""), _T("Gambit extensive games (*.efg)|*.efg|" "All files (*.*)|*.*"), wxSAVE | wxOVERWRITE_PROMPT); if (dialog.ShowModal() == wxID_OK) { std::ofstream file((const char *) dialog.GetPath().mb_str()); m_doc->GetGame()->WriteEfgFile(file); m_doc->UpdateViews(GBT_DOC_MODIFIED_NONE); } } void gbtGameFrame::OnFileExportNfg(wxCommandEvent &) { wxFileDialog dialog(this, _("Choose file"), wxGetApp().GetCurrentDir(), _T(""), _T("Gambit strategic games (*.nfg)|*.nfg|" "All files (*.*)|*.*"), wxSAVE | wxOVERWRITE_PROMPT); if (dialog.ShowModal() == wxID_OK) { std::ofstream file((const char *) dialog.GetPath().mb_str()); m_doc->BuildNfg(); m_doc->GetGame()->WriteNfgFile(file); m_doc->UpdateViews(GBT_DOC_MODIFIED_NONE); } } void gbtGameFrame::OnFileExportGraphic(wxCommandEvent &p_event) { wxBitmap bitmap = wxNullBitmap; bool bitmapOK = false; if (m_efgPanel && m_efgPanel->IsShown()) { bitmapOK = m_efgPanel->GetBitmap(bitmap, 50, 50); } else { bitmapOK = m_nfgPanel->GetBitmap(bitmap, 50, 50); } if (!bitmapOK) { wxMessageBox(_("Game image too large to export to graphics file"), _("Error"), wxOK, this); return; } wxString filter = wxT("|All files (*.*)|*.*"); switch (p_event.GetId()) { case GBT_MENU_FILE_EXPORT_BMP: filter = wxT("Windows bitmap files (*.bmp)|*.bmp") + filter; break; case GBT_MENU_FILE_EXPORT_JPEG: filter = wxT("JPEG files (*.jpeg)|*.jpeg|" "JPG files (*.jpg)|*.jpg") + filter; break; case GBT_MENU_FILE_EXPORT_PNG: filter = wxT("PNG files (*.png)|*.png") + filter; break; default: break; } wxFileDialog dialog(this, _("Choose output file"), wxGetApp().GetCurrentDir(), _T(""), filter, wxSAVE | wxOVERWRITE_PROMPT); if (dialog.ShowModal() == wxID_OK) { wxBitmapType code; switch (p_event.GetId()) { case GBT_MENU_FILE_EXPORT_BMP: code = wxBITMAP_TYPE_BMP; break; case GBT_MENU_FILE_EXPORT_JPEG: code = wxBITMAP_TYPE_JPEG; break; case GBT_MENU_FILE_EXPORT_PNG: code = wxBITMAP_TYPE_PNG; break; default: break; } if (!bitmap.SaveFile(dialog.GetPath(), code)) { wxMessageBox(_("An error occurred in writing ") + dialog.GetPath() + wxT("."), _("Error"), wxOK, this); } } } void gbtGameFrame::OnFileExportPS(wxCommandEvent &) { #if wxUSE_POSTSCRIPT wxPrintData printData(m_printData); wxFileDialog dialog(this, _("Choose output file"), wxGetApp().GetCurrentDir(), _T(""), _T("PostScript files (*.ps)|*.ps"), wxSAVE | wxOVERWRITE_PROMPT); if (dialog.ShowModal() == wxID_OK) { printData.SetFilename(dialog.GetPath()); } else { return; } printData.SetPrintMode(wxPRINT_MODE_FILE); wxPostScriptDC dc(printData); dc.SetBackgroundMode(wxTRANSPARENT); if (m_efgPanel && m_efgPanel->IsShown()) { dc.StartDoc(_T("Gambit extensive game")); } else { dc.StartDoc(_T("Gambit strategic game")); } dc.StartPage(); if (m_efgPanel && m_efgPanel->IsShown()) { m_efgPanel->RenderGame(dc, 50, 50); } else { m_nfgPanel->RenderGame(dc, 50, 50); } dc.EndPage(); dc.EndDoc(); #endif // wxUSE_POSTSCRIPT } void gbtGameFrame::OnFileExportSVG(wxCommandEvent &) { wxFileDialog dialog(this, _("Choose output file"), wxGetApp().GetCurrentDir(), _T(""), wxT("SVG files (*.svg)|*.svg|" "All files (*.*)|*.*"), wxSAVE | wxOVERWRITE_PROMPT); if (dialog.ShowModal() == wxID_OK) { if (m_efgPanel && m_efgPanel->IsShown()) { m_efgPanel->GetSVG(dialog.GetPath(), 50, 50); } else { m_nfgPanel->GetSVG(dialog.GetPath(), 50, 50); } } } void gbtGameFrame::OnFileExit(wxCommandEvent &p_event) { if (wxGetApp().AreDocumentsModified()) { if (wxMessageBox(_("There are modified games.\n" "Any unsaved changes will be lost!\n" "Close anyway?"), _("Warning"), wxOK | wxCANCEL) == wxCANCEL) { return; } } while (wxGetApp().GetTopWindow()) { delete wxGetApp().GetTopWindow(); } } void gbtGameFrame::OnFileMRUFile(wxCommandEvent &p_event) { wxString filename = wxGetApp().GetHistoryFile(p_event.GetId() - wxID_FILE1); gbtAppLoadResult result = wxGetApp().LoadFile(filename); if (result == GBT_APP_OPEN_FAILED) { wxMessageDialog dialog(this, wxT("Gambit could not open file '") + filename + wxT("' for reading."), wxT("Unable to open file"), wxOK | wxICON_ERROR); dialog.ShowModal(); } else if (result == GBT_APP_PARSE_FAILED) { wxMessageDialog dialog(this, wxT("File '") + filename + wxT("' is not in a format Gambit recognizes."), wxT("Unable to read file"), wxOK | wxICON_ERROR); dialog.ShowModal(); } } //---------------------------------------------------------------------- // gbtGameFrame: Menu handlers - Edit menu //---------------------------------------------------------------------- void gbtGameFrame::OnEditUndo(wxCommandEvent &) { if (m_doc->CanUndo()) m_doc->Undo(); } void gbtGameFrame::OnEditRedo(wxCommandEvent &) { if (m_doc->CanRedo()) m_doc->Redo(); } void gbtGameFrame::OnEditInsertMove(wxCommandEvent &) { gbtInsertMoveDialog dialog(this, m_doc); if (dialog.ShowModal() == wxID_OK) { try { if (!dialog.GetInfoset()) { Gambit::GameInfoset infoset = m_doc->GetSelectNode()->InsertMove(dialog.GetPlayer(), dialog.GetActions()); for (int act = 1; act <= infoset->NumActions(); act++) { infoset->GetAction(act)->SetLabel(Gambit::ToText(act)); } } else { m_doc->GetSelectNode()->InsertMove(dialog.GetInfoset()); } m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } catch (Gambit::Exception &ex) { gbtExceptionDialog(ex.GetDescription(), this); } } } void gbtGameFrame::OnEditInsertAction(wxCommandEvent &) { Gambit::GameNode node = m_doc->GetSelectNode(); if (!node || !node->GetInfoset()) return; Gambit::GameAction action = node->GetInfoset()->InsertAction(); action->SetLabel(Gambit::ToText(action->GetNumber())); m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } void gbtGameFrame::OnEditDeleteTree(wxCommandEvent &) { if (!m_doc->GetSelectNode()) return; m_doc->GetSelectNode()->DeleteTree(); m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } void gbtGameFrame::OnEditDeleteParent(wxCommandEvent &) { if (!m_doc->GetSelectNode() || !m_doc->GetSelectNode()->GetParent()) return; m_doc->GetSelectNode()->DeleteParent(); m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } void gbtGameFrame::OnEditRemoveOutcome(wxCommandEvent &) { if (!m_doc->GetSelectNode() || !m_doc->GetSelectNode()->GetOutcome()) return; m_doc->GetSelectNode()->SetOutcome(0); m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } void gbtGameFrame::OnEditReveal(wxCommandEvent &) { gbtRevealMoveDialog dialog(this, m_doc); if (dialog.ShowModal() == wxID_OK) { try { for (int pl = 1; pl <= dialog.GetPlayers().Length(); pl++) { m_doc->GetSelectNode()->GetInfoset()->Reveal(dialog.GetPlayers()[pl]); } m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } catch (Gambit::Exception &ex) { gbtExceptionDialog(ex.GetDescription(), this); } } } void gbtGameFrame::OnEditNode(wxCommandEvent &) { dialogEditNode dialog(this, m_doc->GetSelectNode()); if (dialog.ShowModal() == wxID_OK) { m_doc->GetSelectNode()->SetLabel((const char *) dialog.GetNodeName().mb_str()); if (dialog.GetOutcome() > 0) { m_doc->GetSelectNode()->SetOutcome(m_doc->GetGame()->GetOutcome(dialog.GetOutcome())); } else { m_doc->GetSelectNode()->SetOutcome(0); } if (m_doc->GetSelectNode()->NumChildren() > 0 && dialog.GetInfoset() != m_doc->GetSelectNode()->GetInfoset()) { if (dialog.GetInfoset() == 0) { m_doc->GetSelectNode()->LeaveInfoset(); } else { m_doc->GetSelectNode()->SetInfoset(dialog.GetInfoset()); } } m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } } void gbtGameFrame::OnEditMove(wxCommandEvent &) { Gambit::GameInfoset infoset = m_doc->GetSelectNode()->GetInfoset(); if (!infoset) return; gbtEditMoveDialog dialog(this, infoset); if (dialog.ShowModal() == wxID_OK) { infoset->SetLabel((const char *) dialog.GetInfosetName().mb_str()); if (!infoset->IsChanceInfoset() && dialog.GetPlayer() != infoset->GetPlayer()->GetNumber()) { infoset->SetPlayer(m_doc->GetGame()->GetPlayer(dialog.GetPlayer())); } for (int act = 1; act <= infoset->NumActions(); act++) { infoset->GetAction(act)->SetLabel(dialog.GetActionName(act)); if (infoset->IsChanceInfoset()) { infoset->SetActionProb(infoset->GetAction(act)->GetNumber(), dialog.GetActionProb(act)); } } m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } } void gbtGameFrame::OnEditGame(wxCommandEvent &) { gbtGamePropertiesDialog dialog(this, m_doc); if (dialog.ShowModal() == wxID_OK) { Gambit::Game game = m_doc->GetGame(); game->SetTitle((const char *) dialog.GetTitle().mb_str()); game->SetComment((const char *) dialog.GetComment().mb_str()); m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } } void gbtGameFrame::OnEditNewPlayer(wxCommandEvent &) { Gambit::GamePlayer player = m_doc->GetGame()->NewPlayer(); player->SetLabel("Player " + Gambit::ToText(player->GetNumber())); if (!m_doc->IsTree()) { player->GetStrategy(1)->SetLabel("1"); } m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } //---------------------------------------------------------------------- // gbtGameFrame: Menu handlers - View menu //---------------------------------------------------------------------- void gbtGameFrame::OnViewProfiles(wxCommandEvent &p_event) { if (m_splitter->IsSplit()) { m_splitter->Unsplit(m_analysisPanel); } else if (m_efgPanel && m_efgPanel->IsShown()) { m_analysisPanel->ShowMixed(false); m_splitter->SplitHorizontally(m_efgPanel, m_analysisPanel); } else { m_analysisPanel->ShowMixed(true); m_splitter->SplitHorizontally(m_nfgPanel, m_analysisPanel); } GetMenuBar()->Check(GBT_MENU_VIEW_PROFILES, p_event.IsChecked()); GetToolBar()->ToggleTool(GBT_MENU_VIEW_PROFILES, p_event.IsChecked()); } void gbtGameFrame::OnViewZoom(wxCommandEvent &p_event) { // All zoom events get passed along to the panel wxPostEvent(m_efgPanel, p_event); } void gbtGameFrame::OnViewStrategic(wxCommandEvent &p_event) { if (m_efgPanel->IsShown()) { // We are switching to strategic view if (!m_doc->GetGame()->IsPerfectRecall()) { if (wxMessageBox(_("This is not a game of perfect recall\n" "Do you wish to continue?"), _("Strategic game"), wxOK | wxCANCEL | wxALIGN_CENTER, this) != wxOK) { return; } } m_doc->BuildNfg(); m_splitter->ReplaceWindow(m_efgPanel, m_nfgPanel); m_efgPanel->Show(false); m_nfgPanel->Show(true); if (m_splitter->IsSplit()) { m_analysisPanel->ShowMixed(true); } m_nfgPanel->SetFocus(); } else { m_splitter->ReplaceWindow(m_nfgPanel, m_efgPanel); m_nfgPanel->Show(false); m_efgPanel->Show(true); if (m_splitter->IsSplit()) { m_analysisPanel->ShowMixed(false); } m_efgPanel->SetFocus(); } GetMenuBar()->Check(GBT_MENU_VIEW_STRATEGIC, m_nfgPanel->IsShown()); GetMenuBar()->Enable(GBT_MENU_VIEW_ZOOMIN, !p_event.IsChecked()); GetMenuBar()->Enable(GBT_MENU_VIEW_ZOOMOUT, !p_event.IsChecked()); GetToolBar()->ToggleTool(GBT_MENU_VIEW_STRATEGIC, p_event.IsChecked()); GetToolBar()->EnableTool(GBT_MENU_VIEW_ZOOMIN, !p_event.IsChecked()); GetToolBar()->EnableTool(GBT_MENU_VIEW_ZOOMOUT, !p_event.IsChecked()); GetToolBar()->EnableTool(GBT_MENU_VIEW_ZOOMFIT, !p_event.IsChecked()); m_doc->UpdateViews(GBT_DOC_MODIFIED_NONE); } //---------------------------------------------------------------------- // gbtGameFrame: Menu handlers - Format menu //---------------------------------------------------------------------- void gbtGameFrame::OnFormatLayout(wxCommandEvent &) { gbtStyle &settings = m_doc->GetStyle(); gbtLayoutDialog dialog(this, settings); if (dialog.ShowModal() == wxID_OK) { dialog.GetSettings(settings); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } } void gbtGameFrame::OnFormatLabels(wxCommandEvent &) { gbtLegendDialog dialog(this, m_doc->GetStyle()); if (dialog.ShowModal() == wxID_OK) { m_doc->GetStyle().SetNodeAboveLabel(dialog.GetNodeAbove()); m_doc->GetStyle().SetNodeBelowLabel(dialog.GetNodeBelow()); m_doc->GetStyle().SetBranchAboveLabel(dialog.GetBranchAbove()); m_doc->GetStyle().SetBranchBelowLabel(dialog.GetBranchBelow()); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } } void gbtGameFrame::OnFormatFonts(wxCommandEvent &) { wxFontData data; data.SetInitialFont(m_doc->GetStyle().GetFont()); wxFontDialog dialog(this, data); if (dialog.ShowModal() == wxID_OK) { m_doc->GetStyle().SetFont(dialog.GetFontData().GetChosenFont()); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } } void gbtGameFrame::OnFormatDecimalsAdd(wxCommandEvent &) { m_doc->GetStyle().SetNumDecimals(m_doc->GetStyle().NumDecimals()+1); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } void gbtGameFrame::OnFormatDecimalsDelete(wxCommandEvent &) { m_doc->GetStyle().SetNumDecimals(m_doc->GetStyle().NumDecimals()-1); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } //---------------------------------------------------------------------- // gbtGameFrame: Menu handlers - Tools menu //---------------------------------------------------------------------- void gbtGameFrame::OnToolsDominance(wxCommandEvent &p_event) { if (m_efgPanel) wxPostEvent(m_efgPanel, p_event); if (m_nfgPanel) wxPostEvent(m_nfgPanel, p_event); if (!p_event.IsChecked()) { m_doc->TopBehavElimLevel(); m_doc->TopStrategyElimLevel(); } } void gbtGameFrame::OnToolsEquilibrium(wxCommandEvent &) { gbtNashChoiceDialog dialog(this, m_doc); if (dialog.ShowModal() == wxID_OK) { gbtAnalysisOutput *command = dialog.GetCommand(); gbtNashMonitorDialog dialog(this, m_doc, command); dialog.ShowModal(); if (!m_splitter->IsSplit()) { if (m_efgPanel && m_efgPanel->IsShown()) { m_analysisPanel->ShowMixed(false); m_splitter->SplitHorizontally(m_efgPanel, m_analysisPanel); } else { m_analysisPanel->ShowMixed(true); m_splitter->SplitHorizontally(m_nfgPanel, m_analysisPanel); } } } m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } extern void LogitStrategic(wxWindow *, gbtGameDocument *); void gbtGameFrame::OnToolsQre(wxCommandEvent &) { if (m_efgPanel && m_splitter->GetWindow1() == m_efgPanel) { gbtLogitBehavDialog(this, m_doc).ShowModal(); } else { LogitStrategic(this, m_doc); } } //---------------------------------------------------------------------- // gbtGameFrame: Menu handlers - Help menu //---------------------------------------------------------------------- void gbtGameFrame::OnHelpAbout(wxCommandEvent &) { gbtAboutDialog(this).ShowModal(); } //---------------------------------------------------------------------- // gbtGameFrame: Non-menu event handlers //---------------------------------------------------------------------- void gbtGameFrame::OnUnsplit(wxSplitterEvent &) { GetMenuBar()->Check(GBT_MENU_VIEW_PROFILES, false); GetToolBar()->ToggleTool(GBT_MENU_VIEW_PROFILES, false); } void gbtGameFrame::OnCloseWindow(wxCloseEvent &p_event) { if (p_event.CanVeto() && m_doc->IsModified()) { if (wxMessageBox(_("Game has been modified.\n" "Unsaved changes will be lost!\n" "Close anyway?"), _("Warning"), wxOK | wxCANCEL) == wxCANCEL) { p_event.Veto(); return; } } p_event.Skip(); } bool gbtGameFrame::ProcessEvent(wxEvent &p_event) { if (p_event.GetEventType() == wxEVT_COMMAND_MENU_SELECTED) { m_doc->PostPendingChanges(); } return wxFrame::ProcessEvent(p_event); } gambit-0.2010.09.01/src/gui/gameframe.h0000644000076500007650000000674211435216101014113 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/gameframe.h // Interface to frame containing the views of a game // // 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 GAMEFRAME_H #define GAMEFRAME_H #include #include "gamedoc.h" class wxSplitterWindow; class wxSplitterEvent; class gbtAnalysisNotebook; class gbtEfgPanel; class gbtNfgPanel; class gbtGameFrame : public wxFrame, public gbtGameView { private: wxSplitterWindow *m_splitter; gbtEfgPanel *m_efgPanel; gbtNfgPanel *m_nfgPanel; gbtAnalysisNotebook *m_analysisPanel; wxPageSetupData m_pageSetupData; wxPrintData m_printData; void MakeMenus(void); void MakeToolbar(void); // Event handlers void OnCloseWindow(wxCloseEvent &); // Menu event handlers void OnFileNewEfg(wxCommandEvent &); void OnFileNewNfg(wxCommandEvent &); void OnFileOpen(wxCommandEvent &); void OnFileClose(wxCommandEvent &); void OnFileSave(wxCommandEvent &); void OnFileExportEfg(wxCommandEvent &); void OnFileExportNfg(wxCommandEvent &); void OnFileExportGraphic(wxCommandEvent &); void OnFileExportPS(wxCommandEvent &); void OnFileExportSVG(wxCommandEvent &); void OnFilePageSetup(wxCommandEvent &); void OnFilePrintPreview(wxCommandEvent &); void OnFilePrint(wxCommandEvent &); void OnFileExit(wxCommandEvent &); void OnFileMRUFile(wxCommandEvent &); void OnEditUndo(wxCommandEvent &); void OnEditRedo(wxCommandEvent &); void OnEditInsertMove(wxCommandEvent &); void OnEditInsertAction(wxCommandEvent &); void OnEditDeleteTree(wxCommandEvent &); void OnEditDeleteParent(wxCommandEvent &); void OnEditRemoveOutcome(wxCommandEvent &); void OnEditReveal(wxCommandEvent &); void OnEditNode(wxCommandEvent &); void OnEditMove(wxCommandEvent &); void OnEditGame(wxCommandEvent &); void OnEditNewPlayer(wxCommandEvent &); void OnViewProfiles(wxCommandEvent &); void OnViewZoom(wxCommandEvent &); void OnViewStrategic(wxCommandEvent &); void OnFormatLayout(wxCommandEvent &); void OnFormatLabels(wxCommandEvent &); void OnFormatDecimalsAdd(wxCommandEvent &); void OnFormatDecimalsDelete(wxCommandEvent &); void OnFormatFonts(wxCommandEvent &); void OnToolsDominance(wxCommandEvent &); void OnToolsEquilibrium(wxCommandEvent &); void OnToolsQre(wxCommandEvent &); void OnHelpAbout(wxCommandEvent &); void OnUnsplit(wxSplitterEvent &); /// @name Overriding wxWindow behavior //@{ /// Flush any pending changes in document before processing event bool ProcessEvent(wxEvent &); //@} // Overriding gbtGameView members void OnUpdate(void); public: // CONSTRUCTOR AND DESTRUCTOR gbtGameFrame(wxWindow *p_parent, gbtGameDocument *p_doc); virtual ~gbtGameFrame(); DECLARE_EVENT_TABLE() }; #endif // GAMEFRAME_H gambit-0.2010.09.01/src/gui/menuconst.h0000644000076500007650000000421111435216101014167 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/menuconst.h // Declaration of constants used for menu items // // 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 MENUCONST_H #define MENUCONST_H typedef enum { GBT_MENU_FILE_NEW_EFG = 1098, GBT_MENU_FILE_NEW_NFG = 1099, GBT_MENU_FILE_EXPORT = 1102, GBT_MENU_FILE_EXPORT_BMP = 1103, GBT_MENU_FILE_EXPORT_JPEG = 1104, GBT_MENU_FILE_EXPORT_PNG = 1105, GBT_MENU_FILE_EXPORT_POSTSCRIPT = 1106, GBT_MENU_FILE_EXPORT_SVG = 1109, GBT_MENU_FILE_EXPORT_EFG = 1107, GBT_MENU_FILE_EXPORT_NFG = 1108, GBT_MENU_EDIT_INSERT_MOVE = 1200, GBT_MENU_EDIT_INSERT_ACTION = 1201, GBT_MENU_EDIT_DELETE_TREE = 1202, GBT_MENU_EDIT_DELETE_PARENT = 1203, GBT_MENU_EDIT_REMOVE_OUTCOME = 1204, GBT_MENU_EDIT_REVEAL = 1407, GBT_MENU_EDIT_GAME = 1419, GBT_MENU_EDIT_NODE = 1420, GBT_MENU_EDIT_MOVE = 1421, GBT_MENU_EDIT_NEWPLAYER = 1500, GBT_MENU_VIEW_PROFILES = 1850, GBT_MENU_VIEW_ZOOMIN = 1601, GBT_MENU_VIEW_ZOOMOUT = 1602, GBT_MENU_VIEW_ZOOM100 = 1900, GBT_MENU_VIEW_ZOOMFIT = 1603, GBT_MENU_VIEW_STRATEGIC = 1851, GBT_MENU_FORMAT_LAYOUT = 1620, GBT_MENU_FORMAT_LABELS = 1604, GBT_MENU_FORMAT_FONTS = 1612, GBT_MENU_FORMAT_DECIMALS_ADD = 1622, GBT_MENU_FORMAT_DECIMALS_DELETE = 1623, GBT_MENU_TOOLS_DOMINANCE = 1800, GBT_MENU_TOOLS_EQUILIBRIUM = 1801, GBT_MENU_TOOLS_QRE = 1802, } gbtMenuItems; #endif // MENUCONST_H gambit-0.2010.09.01/src/gui/nfgpanel.cc0000644000076500007650000004021211435216101014105 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/nfgpanel.cc // Implementation of normal form panel // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include // for drag-and-drop features #include // for creating drag-and-drop cursor #include // for picking player colors #include "gamedoc.h" #include "nfgpanel.h" #include "nfgtable.h" #include "menuconst.h" #include "edittext.h" #include "bitmaps/color.xpm" #include "bitmaps/newrow.xpm" #include "bitmaps/person.xpm" //========================================================================= // class gbtTablePlayerIcon //========================================================================= class gbtTablePlayerIcon : public wxStaticBitmap { private: int m_player; // Event handlers void OnLeftClick(wxMouseEvent &); public: gbtTablePlayerIcon(wxWindow *p_parent, int p_player); DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(gbtTablePlayerIcon, wxStaticBitmap) EVT_LEFT_DOWN(gbtTablePlayerIcon::OnLeftClick) END_EVENT_TABLE() gbtTablePlayerIcon::gbtTablePlayerIcon(wxWindow *p_parent, int p_player) : wxStaticBitmap(p_parent, -1, wxBitmap(person_xpm)), m_player(p_player) { } void gbtTablePlayerIcon::OnLeftClick(wxMouseEvent &) { wxBitmap bitmap(person_xpm); #if defined( __WXMSW__) or defined(__WXMAC__) wxImage image = bitmap.ConvertToImage(); #else wxIcon image; image.CopyFromBitmap(bitmap); #endif // _WXMSW__ wxTextDataObject textData(wxString::Format(wxT("P%d"), m_player)); wxDropSource source(textData, this, image, image, image); source.DoDragDrop(wxDrag_DefaultMove); } class gbtTablePlayerPanel : public wxPanel { private: gbtNfgPanel *m_nfgPanel; gbtGameDocument *m_doc; int m_player; gbtEditableText *m_playerLabel; wxStaticText *m_payoff; /// @name Event handlers //@{ /// The add strategy icon is clicked void OnNewStrategy(wxCommandEvent &); /// The set color icon is clicked void OnSetColor(wxCommandEvent &); /// Start the editing of the player label void OnEditPlayerLabel(wxCommandEvent &); /// End the editing of the player label after enter is pressed void OnAcceptPlayerLabel(wxCommandEvent &); /// Process a keypress event void OnChar(wxKeyEvent &); //@} public: gbtTablePlayerPanel(wxWindow *, gbtNfgPanel *, gbtGameDocument *, int p_player); void OnUpdate(void); void PostPendingChanges(void); DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(gbtTablePlayerPanel, wxPanel) EVT_CHAR(gbtTablePlayerPanel::OnChar) END_EVENT_TABLE() gbtTablePlayerPanel::gbtTablePlayerPanel(wxWindow *p_parent, gbtNfgPanel *p_nfgPanel, gbtGameDocument *p_doc, int p_player) : wxPanel(p_parent, -1), m_nfgPanel(p_nfgPanel), m_doc(p_doc), m_player(p_player) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *labelSizer = new wxBoxSizer(wxHORIZONTAL); wxStaticBitmap *playerIcon = new gbtTablePlayerIcon(this, m_player); labelSizer->Add(playerIcon, 0, wxALL | wxALIGN_CENTER, 0); if (!m_doc->IsTree()) { wxBitmapButton *addStrategyIcon = new wxBitmapButton(this, -1, wxBitmap(newrow_xpm), wxDefaultPosition, wxDefaultSize, wxNO_BORDER); addStrategyIcon->SetToolTip(_("Add a strategy for this player")); labelSizer->Add(addStrategyIcon, 0, wxALL | wxALIGN_CENTER, 0); Connect(addStrategyIcon->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtTablePlayerPanel::OnNewStrategy)); } wxBitmapButton *setColorIcon = new wxBitmapButton(this, -1, wxBitmap(color_xpm), wxDefaultPosition, wxDefaultSize, wxNO_BORDER); setColorIcon->SetToolTip(_("Change the color for this player")); labelSizer->Add(setColorIcon, 0, wxALL | wxALIGN_CENTER, 0); Connect(setColorIcon->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtTablePlayerPanel::OnSetColor)); m_playerLabel = new gbtEditableText(this, -1, wxT(""), wxDefaultPosition, wxSize(125, -1)); m_playerLabel->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); labelSizer->Add(m_playerLabel, 1, wxLEFT | wxEXPAND, 5); Connect(m_playerLabel->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtTablePlayerPanel::OnEditPlayerLabel)); Connect(m_playerLabel->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(gbtTablePlayerPanel::OnAcceptPlayerLabel)); topSizer->Add(labelSizer, 0, wxALL, 0); m_payoff = new wxStaticText(this, wxID_STATIC, wxT("Payoff:"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER | wxST_NO_AUTORESIZE); m_payoff->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); topSizer->Add(m_payoff, 0, wxALL | wxEXPAND, 0); topSizer->Show(m_payoff, false); SetSizer(topSizer); topSizer->SetSizeHints(this); topSizer->Fit(this); Layout(); } void gbtTablePlayerPanel::OnUpdate(void) { wxColour color = m_doc->GetStyle().GetPlayerColor(m_player); m_playerLabel->SetForegroundColour(color); m_playerLabel->SetValue(wxString(m_doc->GetGame()->GetPlayer(m_player)->GetLabel().c_str(), *wxConvCurrent)); if (m_doc->GetCurrentProfile() > 0) { m_payoff->SetForegroundColour(color); std::string pay = m_doc->GetProfiles().GetPayoff(m_player); m_payoff->SetLabel(wxT("Payoff: ") + wxString(pay.c_str(), *wxConvCurrent)); GetSizer()->Show(m_payoff, true); } else { GetSizer()->Show(m_payoff, false); } GetSizer()->Layout(); GetSizer()->SetSizeHints(this); GetSizer()->Fit(this); } void gbtTablePlayerPanel::OnChar(wxKeyEvent &p_event) { if (p_event.GetKeyCode() == WXK_ESCAPE) { m_playerLabel->EndEdit(false); } else { p_event.Skip(); } } void gbtTablePlayerPanel::OnNewStrategy(wxCommandEvent &) { m_doc->PostPendingChanges(); Gambit::GameStrategy strategy = m_doc->GetGame()->GetPlayer(m_player)->NewStrategy(); strategy->SetLabel(Gambit::ToText(strategy->GetNumber())); m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } void gbtTablePlayerPanel::OnSetColor(wxCommandEvent &) { wxColourData data; data.SetColour(m_doc->GetStyle().GetPlayerColor(m_player)); wxColourDialog dialog(this, &data); dialog.SetTitle(wxString::Format(_("Choose color for player %d"), m_player)); if (dialog.ShowModal() == wxID_OK) { wxColour color = dialog.GetColourData().GetColour(); m_doc->GetStyle().SetPlayerColor(m_player, color); m_doc->UpdateViews(GBT_DOC_MODIFIED_VIEWS); } } void gbtTablePlayerPanel::OnEditPlayerLabel(wxCommandEvent &) { m_doc->PostPendingChanges(); m_playerLabel->BeginEdit(); } void gbtTablePlayerPanel::OnAcceptPlayerLabel(wxCommandEvent &) { m_doc->GetGame()->GetPlayer(m_player)->SetLabel((const char *) m_playerLabel->GetValue().mb_str()); m_doc->UpdateViews(GBT_DOC_MODIFIED_LABELS); } void gbtTablePlayerPanel::PostPendingChanges(void) { if (m_playerLabel->IsEditing()) { m_playerLabel->EndEdit(true); m_doc->GetGame()->GetPlayer(m_player)->SetLabel((const char *) m_playerLabel->GetValue().mb_str()); m_doc->UpdateViews(GBT_DOC_MODIFIED_LABELS); } } //===================================================================== // class gbtTablePlayerToolbar //===================================================================== class gbtTablePlayerToolbar : public wxPanel, public gbtGameView { private: gbtNfgPanel *m_nfgPanel; Gambit::Array m_playerPanels; /// @name Implementation of gbtGameView members //@{ void OnUpdate(void); void PostPendingChanges(void); //@} public: gbtTablePlayerToolbar(gbtNfgPanel *p_parent, gbtGameDocument *p_doc); }; gbtTablePlayerToolbar::gbtTablePlayerToolbar(gbtNfgPanel *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, -1, wxDefaultPosition, wxSize(110, -1)), gbtGameView(p_doc), m_nfgPanel(p_parent) { wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); for (int pl = 1; pl <= m_doc->NumPlayers(); pl++) { m_playerPanels.Append(new gbtTablePlayerPanel(this, p_parent, m_doc, pl)); topSizer->Add(m_playerPanels[pl], 0, wxALL | wxEXPAND, 5); } SetSizer(topSizer); Layout(); } void gbtTablePlayerToolbar::OnUpdate(void) { while (m_playerPanels.Length() < m_doc->NumPlayers()) { gbtTablePlayerPanel *panel = new gbtTablePlayerPanel(this, m_nfgPanel, m_doc, m_playerPanels.Length()+1); m_playerPanels.Append(panel); GetSizer()->Add(panel, 0, wxALL | wxEXPAND, 5); } while (m_playerPanels.Length() > m_doc->NumPlayers()) { gbtTablePlayerPanel *panel = m_playerPanels.Remove(m_playerPanels.Length()); GetSizer()->Remove(panel); panel->Destroy(); } for (int pl = 1; pl <= m_playerPanels.Length(); pl++) { m_playerPanels[pl]->OnUpdate(); } GetSizer()->Layout(); } void gbtTablePlayerToolbar::PostPendingChanges(void) { for (int pl = 1; pl <= m_playerPanels.Length(); pl++) { m_playerPanels[pl]->PostPendingChanges(); } } //===================================================================== // class gbtStrategyDominanceToolbar //===================================================================== class gbtStrategyDominanceToolbar : public wxPanel, public gbtGameView { private: wxButton *m_topButton, *m_prevButton, *m_nextButton, *m_allButton; wxStaticText *m_level; // Overriding gbtGameView members void OnUpdate(void); // Event handlers void OnStrength(wxCommandEvent &); void OnTopLevel(wxCommandEvent &); void OnPreviousLevel(wxCommandEvent &); void OnNextLevel(wxCommandEvent &); void OnLastLevel(wxCommandEvent &); public: gbtStrategyDominanceToolbar(wxWindow *p_parent, gbtGameDocument *p_doc); virtual ~gbtStrategyDominanceToolbar() { } }; #include "bitmaps/next.xpm" #include "bitmaps/prev.xpm" #include "bitmaps/tobegin.xpm" #include "bitmaps/toend.xpm" gbtStrategyDominanceToolbar::gbtStrategyDominanceToolbar(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, -1), gbtGameView(p_doc) { wxBoxSizer *topSizer = new wxBoxSizer(wxHORIZONTAL); topSizer->Add(new wxStaticText(this, wxID_STATIC, wxT("Hide strategies which are ")), 0, wxALL | wxALIGN_CENTER, 5); wxString domChoices[] = { wxT("strictly"), wxT("strictly or weakly") }; wxChoice *choice = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 2, domChoices); choice->SetSelection(0); Connect(choice->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(gbtStrategyDominanceToolbar::OnStrength)); topSizer->Add(choice, 0, wxALL | wxALIGN_CENTER, 5); topSizer->Add(new wxStaticText(this, wxID_STATIC, wxT("dominated:")), 0, wxALL | wxALIGN_CENTER, 5); m_topButton = new wxBitmapButton(this, -1, wxBitmap(tobegin_xpm)); m_topButton->SetToolTip(_("Show all strategies")); Connect(m_topButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtStrategyDominanceToolbar::OnTopLevel)); topSizer->Add(m_topButton, 0, wxALL | wxALIGN_CENTER, 5); m_prevButton = new wxBitmapButton(this, -1, wxBitmap(prev_xpm)); m_prevButton->SetToolTip(_("Previous round of elimination")); Connect(m_prevButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtStrategyDominanceToolbar::OnPreviousLevel)); topSizer->Add(m_prevButton, 0, wxALL | wxALIGN_CENTER, 5); m_level = new wxStaticText(this, wxID_STATIC, wxT("All strategies shown"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER | wxST_NO_AUTORESIZE); topSizer->Add(m_level, 0, wxALL | wxALIGN_CENTER, 5); m_nextButton = new wxBitmapButton(this, -1, wxBitmap(next_xpm)); m_nextButton->SetToolTip(_("Next round of elimination")); Connect(m_nextButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtStrategyDominanceToolbar::OnNextLevel)); topSizer->Add(m_nextButton, 0, wxALL | wxALIGN_CENTER, 5); m_allButton = new wxBitmapButton(this, -1, wxBitmap(toend_xpm)); m_allButton->SetToolTip(_("Eliminate iteratively")); Connect(m_allButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gbtStrategyDominanceToolbar::OnLastLevel)); topSizer->Add(m_allButton, 0, wxALL | wxALIGN_CENTER, 5); SetSizer(topSizer); Layout(); } void gbtStrategyDominanceToolbar::OnStrength(wxCommandEvent &p_event) { m_doc->SetStrategyElimStrength(p_event.GetSelection() == 0); } void gbtStrategyDominanceToolbar::OnTopLevel(wxCommandEvent &) { m_doc->TopStrategyElimLevel(); } void gbtStrategyDominanceToolbar::OnPreviousLevel(wxCommandEvent &) { m_doc->PreviousStrategyElimLevel(); } void gbtStrategyDominanceToolbar::OnNextLevel(wxCommandEvent &) { m_doc->NextStrategyElimLevel(); } void gbtStrategyDominanceToolbar::OnLastLevel(wxCommandEvent &) { while (m_doc->NextStrategyElimLevel()); } void gbtStrategyDominanceToolbar::OnUpdate(void) { m_topButton->Enable(m_doc->GetStrategyElimLevel() > 1); m_prevButton->Enable(m_doc->GetStrategyElimLevel() > 1); m_nextButton->Enable(m_doc->CanStrategyElim()); m_allButton->Enable(m_doc->CanStrategyElim()); if (m_doc->GetStrategyElimLevel() == 1) { m_level->SetLabel(wxT("All strategies shown")); } else if (m_doc->GetStrategyElimLevel() == 2) { m_level->SetLabel(wxT("Eliminated 1 level")); } else { m_level->SetLabel(wxString::Format(wxT("Eliminated %d levels"), m_doc->GetStrategyElimLevel()-1)); } GetSizer()->Layout(); } //====================================================================== // class gbtNfgPanel: Member functions //====================================================================== BEGIN_EVENT_TABLE(gbtNfgPanel, wxPanel) EVT_MENU(GBT_MENU_TOOLS_DOMINANCE, gbtNfgPanel::OnToolsDominance) END_EVENT_TABLE() gbtNfgPanel::gbtNfgPanel(wxWindow *p_parent, gbtGameDocument *p_doc) : wxPanel(p_parent, -1), gbtGameView(p_doc) { m_dominanceToolbar = new gbtStrategyDominanceToolbar(this, m_doc); m_tableWidget = new gbtTableWidget(this, -1, m_doc); m_playerToolbar = new gbtTablePlayerToolbar(this, m_doc); wxBoxSizer *playerSizer = new wxBoxSizer(wxHORIZONTAL); playerSizer->Add(m_playerToolbar, 0, wxEXPAND, 0); playerSizer->Add(m_tableWidget, 1, wxEXPAND, 0); wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL); topSizer->Add(m_dominanceToolbar, 0, wxEXPAND, 0); topSizer->Show(m_dominanceToolbar, false); topSizer->Add(playerSizer, 1, wxEXPAND, 0); SetSizer(topSizer); Layout(); } void gbtNfgPanel::OnToolsDominance(wxCommandEvent &p_event) { GetSizer()->Show(m_dominanceToolbar, p_event.IsChecked(), true); GetSizer()->Layout(); // Redraw the table with/without dominance markings m_tableWidget->OnUpdate(); // This call is necessary on MSW to clear out a ghost of the // dominance toolbar's strength control, under certain circumstances. // (I think it is because of the empty upper-left panel in the // table widget, but I'm not sure.) Refresh(); } void gbtNfgPanel::OnUpdate(void) { m_tableWidget->OnUpdate(); GetSizer()->Layout(); } void gbtNfgPanel::PostPendingChanges(void) { m_tableWidget->PostPendingChanges(); } wxPrintout *gbtNfgPanel::GetPrintout(void) { return m_tableWidget->GetPrintout(); } bool gbtNfgPanel::GetBitmap(wxBitmap &p_bitmap, int p_marginX, int p_marginY) { return m_tableWidget->GetBitmap(p_bitmap, p_marginX, p_marginY); } void gbtNfgPanel::GetSVG(const wxString &p_filename, int p_marginX, int p_marginY) { m_tableWidget->GetSVG(p_filename, p_marginX, p_marginY); } void gbtNfgPanel::RenderGame(wxDC &p_dc, int p_marginX, int p_marginY) { m_tableWidget->RenderGame(p_dc, p_marginX, p_marginY); } gambit-0.2010.09.01/src/gui/nfgpanel.h0000644000076500007650000000405311435216101013752 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/nfgpanel.h // Panel to display normal form games in tabular format // // 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 NFGPANEL_H #define NFGPANEL_H #include "wx/sheet/sheet.h" // for wxSheet class wxPrintout; class gbtTableWidget; class gbtNfgPanel : public wxPanel, public gbtGameView { private: wxWindow *m_dominanceToolbar, *m_playerToolbar; gbtTableWidget *m_tableWidget; void OnToolsDominance(wxCommandEvent &); // Overriding gbtGameView members void OnUpdate(void); void PostPendingChanges(void); public: gbtNfgPanel(wxWindow *p_parent, gbtGameDocument *p_doc); virtual ~gbtNfgPanel() { } bool IsDominanceShown(void) const { return m_dominanceToolbar->IsShown(); } /// @name Exporting/printing graphics //@{ /// Creates a printout object of the game as currently displayed wxPrintout *GetPrintout(void); /// Creates a bitmap of the game as currently displayed bool GetBitmap(wxBitmap &, int marginX, int marginY); /// Outputs the game as currently displayed to a SVG file void GetSVG(const wxString &p_filename, int marginX, int marginY); /// Prints the game as currently displayed, centered on the DC void RenderGame(wxDC &p_dc, int marginX, int marginY); //@} DECLARE_EVENT_TABLE() }; #endif // NFGPANEL_H gambit-0.2010.09.01/src/gui/nfgprofile.cc0000644000076500007650000001520611435216101014453 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/nfgprofile.cc // Normal form mixed profile window // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "nfgprofile.h" #include "menuconst.h" #include "renratio.h" // for rational number rendering //------------------------------------------------------------------------- // class gbtMixedProfileList: Member functions //------------------------------------------------------------------------- gbtMixedProfileList::gbtMixedProfileList(wxWindow *p_parent, gbtGameDocument *p_doc) : wxSheet(p_parent, -1), gbtGameView(p_doc), m_showProbs(1), m_showPayoff(0) { CreateGrid(0, 0); SetRowLabelWidth(40); SetColLabelHeight(25); Connect(GetId(), wxEVT_SHEET_LABEL_LEFT_DOWN, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtMixedProfileList::OnLabelClick))); Connect(GetId(), wxEVT_SHEET_CELL_LEFT_DOWN, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtMixedProfileList::OnCellClick))); } gbtMixedProfileList::~gbtMixedProfileList() { } void gbtMixedProfileList::OnLabelClick(wxSheetEvent &p_event) { if (p_event.GetCol() == -1) { m_doc->SetCurrentProfile(RowToProfile(p_event.GetRow())); } } void gbtMixedProfileList::OnCellClick(wxSheetEvent &p_event) { m_doc->SetCurrentProfile(RowToProfile(p_event.GetRow())); } #ifdef UNUSED static Gambit::GameStrategy GetStrategy(gbtGameDocument *p_doc, int p_index) { int index = 0; for (int pl = 1; pl <= p_doc->GetGame()->NumPlayers(); pl++) { Gambit::GamePlayer player = p_doc->GetGame()->GetPlayer(pl); for (int st = 1; st <= player->NumStrategies(); st++) { if (index++ == p_index) { return player->GetStrategy(st); } } } return 0; } #endif wxString gbtMixedProfileList::GetCellValue(const wxSheetCoords &p_coords) { if (IsRowLabelCell(p_coords)) { return wxString::Format(wxT("%d"), RowToProfile(p_coords.GetRow())); } else if (IsColLabelCell(p_coords)) { int index = 0; for (int pl = 1; pl <= m_doc->GetGame()->NumPlayers(); pl++) { Gambit::GamePlayer player = m_doc->GetGame()->GetPlayer(pl); for (int st = 1; st <= player->NumStrategies(); st++) { if (index++ == p_coords.GetCol()) { return (wxString::Format(wxT("%d: "), pl) + wxString(player->GetStrategy(st)->GetLabel().c_str(), *wxConvCurrent)); } } } return wxT(""); } else if (IsCornerLabelCell(p_coords)) { return wxT("#"); } int profile = RowToProfile(p_coords.GetRow()); if (IsProbabilityRow(p_coords.GetRow())) { return wxString(m_doc->GetProfiles().GetStrategyProb(p_coords.GetCol()+1, profile).c_str(), *wxConvCurrent); } else { return wxString(m_doc->GetProfiles().GetStrategyValue(p_coords.GetCol()+1, profile).c_str(), *wxConvCurrent); } } static wxColour GetPlayerColor(gbtGameDocument *p_doc, int p_index) { int index = 0; for (int pl = 1; pl <= p_doc->GetGame()->NumPlayers(); pl++) { Gambit::GamePlayer player = p_doc->GetGame()->GetPlayer(pl); for (int st = 1; st <= player->NumStrategies(); st++) { if (index++ == p_index) { return p_doc->GetStyle().GetPlayerColor(pl); } } } return *wxBLACK; } wxSheetCellAttr gbtMixedProfileList::GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const { int currentProfile = m_doc->GetCurrentProfile(); if (IsRowLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultRowLabelAttr); if (RowToProfile(p_coords.GetRow()) == currentProfile) { attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); } else { attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); } attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); return attr; } else if (IsColLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultColLabelAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetReadOnly(true); attr.SetForegroundColour(GetPlayerColor(m_doc, p_coords.GetCol())); return attr; } else if (IsCornerLabelCell(p_coords)) { return GetSheetRefData()->m_defaultCornerLabelAttr; } wxSheetCellAttr attr(GetSheetRefData()->m_defaultGridCellAttr); if (RowToProfile(p_coords.GetRow()) == currentProfile) { attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); } else { attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxNORMAL)); } attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); attr.SetRenderer(wxSheetCellRenderer(new gbtRationalRendererRefData())); attr.SetForegroundColour(GetPlayerColor(m_doc, p_coords.GetCol())); attr.SetReadOnly(true); return attr; } void gbtMixedProfileList::OnUpdate(void) { if (m_doc->NumProfileLists() == 0) { DeleteRows(0, GetNumberRows()); return; } const gbtAnalysisOutput &profiles = m_doc->GetProfiles(); BeginBatch(); int newRows = profiles.NumProfiles() * (m_showProbs + m_showPayoff); DeleteRows(0, GetNumberRows()); InsertRows(0, newRows); int profileLength = m_doc->GetGame()->MixedProfileLength(); int newCols = profileLength; DeleteCols(0, GetNumberCols()); InsertCols(0, newCols); for (int row = 0; row < GetNumberRows(); row += m_showProbs + m_showPayoff) { SetCellSpan(wxSheetCoords(row, -1), wxSheetCoords(m_showProbs + m_showPayoff, 1)); } AutoSizeRows(); AutoSizeCols(); int colSize = GetColWidth(0); for (int col = 1; col < GetNumberCols(); col++) { if (GetColWidth(col) > colSize) { colSize = GetColWidth(col); } } for (int col = 0; col < GetNumberCols(); SetColWidth(col++, colSize)); EndBatch(); } gambit-0.2010.09.01/src/gui/nfgprofile.h0000644000076500007650000000506211435216101014314 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/nfgprofile.h // Normal form mixed profile window // // 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 NFGPROFILE_H #define NFGPROFILE_H #include "wx/sheet/sheet.h" #include "gamedoc.h" class gbtMixedProfileList : public wxSheet, public gbtGameView { private: int m_showProbs, m_showPayoff; // Overriding wxSheet members for data access wxString GetCellValue(const wxSheetCoords &); wxSheetCellAttr GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const; // Overriding wxSheet members to disable selection behavior bool SelectRow(int, bool = false, bool = false) { return false; } bool SelectRows(int, int, bool = false, bool = false) { return false; } bool SelectCol(int, bool = false, bool = false) { return false; } bool SelectCols(int, int, bool = false, bool = false) { return false; } bool SelectCell(const wxSheetCoords&, bool = false, bool = false) { return false; } bool SelectBlock(const wxSheetBlock&, bool = false, bool = false) { return false; } bool SelectAll(bool = false) { return false; } // Overriding wxSheet member to suppress drawing of cursor void DrawCursorCellHighlight(wxDC&, const wxSheetCellAttr &) { } // Event handlers void OnLabelClick(wxSheetEvent &); void OnCellClick(wxSheetEvent &); // Overriding gbtGameView members void OnUpdate(void); // Which profile index corresponds to a sheet row int RowToProfile(int row) const { return row / (m_showProbs + m_showPayoff) + 1; } bool IsProbabilityRow(int row) const { return (m_showPayoff == 0 || row % 2 == 0); } bool IsPayoffRow(int row) const { return (m_showProbs == 0 || row % 2 == 1); } public: gbtMixedProfileList(wxWindow *p_parent, gbtGameDocument *p_doc); virtual ~gbtMixedProfileList(); }; #endif // NFGPROFILE_H gambit-0.2010.09.01/src/gui/nfgtable.cc0000644000076500007650000012001111435216101014071 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/nfgtable.cc // Implementation of strategic game matrix display/editor // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include // for drag-and-drop support #include // for printing support #include "dcsvg.h" // for SVG output #include "wx/sheet/sheet.h" #include "renratio.h" // special renderer for rational numbers #include "gamedoc.h" #include "nfgpanel.h" #include "nfgtable.h" //========================================================================= // class gbtTableWidgetBase //========================================================================= //! //! This class handles some common overriding of wxSheet behavior //! common to the sheets used in the strategic game display. //! class gbtTableWidgetBase : public wxSheet { protected: //! //! @name Overriding wxSheet members to disable selection behavior //! //@{ bool SelectRow(int, bool = false, bool = false) { return false; } bool SelectRows(int, int, bool = false, bool = false) { return false; } bool SelectCol(int, bool = false, bool = false) { return false; } bool SelectCols(int, int, bool = false, bool = false) { return false; } bool SelectCell(const wxSheetCoords&, bool = false, bool = false) { return false; } bool SelectBlock(const wxSheetBlock&, bool = false, bool = false) { return false; } bool SelectAll(bool = false) { return false; } bool HasSelection(bool = true) const { return false; } bool IsCellSelected(const wxSheetCoords &) const { return false; } bool IsRowSelected(int) const { return false; } bool IsColSelected(int) const { return false; } bool DeselectBlock(const wxSheetBlock &, bool = false) { return false; } bool ClearSelection(bool = false) { return false; } //@} /// Overriding wxSheet member to suppress drawing of cursor void DrawCursorCellHighlight(wxDC&, const wxSheetCellAttr &) { } /// Overriding wxSheet member to show editor on one click void OnCellLeftClick(wxSheetEvent &); public: /// @name Lifecycle //@{ /// Constructor gbtTableWidgetBase(wxWindow *p_parent, wxWindowID p_id, const wxPoint &p_pos = wxDefaultPosition, const wxSize &p_size = wxDefaultSize, long p_style = wxWANTS_CHARS, const wxString &p_name = wxT("wxSheet")) : wxSheet(p_parent, p_id, p_pos, p_size, p_style, p_name) { Connect(GetId(), wxEVT_SHEET_CELL_LEFT_DOWN, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidgetBase::OnCellLeftClick))); } //@} /// @name Drop target interaction //@{ /// Called when the drop target receives text. virtual bool DropText(int p_x, int p_y, const wxString &p_text) { return false; } //@} /// @name Access to scrollbars from underlying wxSheet //@{ /// Get the vertical scrollbar wxScrollBar *GetVerticalScrollBar(void) const { return m_vertScrollBar; } /// Get the horizontal scrollbar wxScrollBar *GetHorizontalScrollBar(void) const { return m_horizScrollBar; } //@} }; void gbtTableWidgetBase::OnCellLeftClick(wxSheetEvent &p_event) { SetGridCursorCell(p_event.GetCoords()); EnableCellEditControl(p_event.GetCoords()); } //========================================================================= // class gbtTableWidgetDropTarget //========================================================================= //! //! This simple class serves as a drop target for players; it simply //! communicates the location and text of the drop to its owner for //! further processing //! class gbtTableWidgetDropTarget : public wxTextDropTarget { private: gbtTableWidgetBase *m_owner; public: gbtTableWidgetDropTarget(gbtTableWidgetBase *p_owner) : m_owner(p_owner) { } bool OnDropText(wxCoord x, wxCoord y, const wxString &p_text) { return m_owner->DropText(x, y, p_text); } }; //========================================================================= // class gbtRowPlayerWidget //========================================================================= class gbtRowPlayerWidget : public gbtTableWidgetBase { private: gbtGameDocument *m_doc; gbtTableWidget *m_table; /// @name Overriding wxSheet members for data access //@{ /// Returns the value in the cell wxString GetCellValue(const wxSheetCoords &); /// Sets the value in the cell, by relabeling the strategy void SetCellValue(const wxSheetCoords &, const wxString &); /// Returns the attributes of the cell wxSheetCellAttr GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const; //@} /// @name Overriding wxSheet members to customize drawing //@{ /// Overrides to draw dominance indicators void DrawCell(wxDC &p_dc, const wxSheetCoords &p_coords); //@} void OnCellRightClick(wxSheetEvent &); public: /// @name Lifecycle //@{ /// Constructorw gbtRowPlayerWidget(gbtTableWidget *p_parent, gbtGameDocument *p_doc); //@} /// @name Synchronizing with document state //@{ void OnUpdate(void); //@} /// @name Drop target interaction //@{ /// Called when the drop target receives text. bool DropText(int p_x, int p_y, const wxString &p_text); //@} }; gbtRowPlayerWidget::gbtRowPlayerWidget(gbtTableWidget *p_parent, gbtGameDocument *p_doc) : gbtTableWidgetBase(p_parent, -1), m_doc(p_doc), m_table(p_parent) { CreateGrid(m_table->NumRowContingencies(), m_table->NumRowPlayers()); SetRowLabelWidth(1); SetColLabelHeight(1); SetScrollBarMode(SB_NEVER); SetGridLineColour(*wxBLACK); SetDropTarget(new gbtTableWidgetDropTarget(this)); Connect(GetId(), wxEVT_SHEET_CELL_RIGHT_DOWN, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtRowPlayerWidget::OnCellRightClick))); } void gbtRowPlayerWidget::OnCellRightClick(wxSheetEvent &p_event) { if (m_table->NumRowPlayers() == 0 || m_doc->GetGame()->IsTree()) { p_event.Skip(); return; } const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); wxSheetCoords coords = p_event.GetCoords(); int player = m_table->GetRowPlayer(coords.GetCol() + 1); int strat = m_table->RowToStrategy(coords.GetCol() + 1, coords.GetRow()); support.GetStrategy(player, strat)->DeleteStrategy(); m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } wxString gbtRowPlayerWidget::GetCellValue(const wxSheetCoords &p_coords) { if (IsLabelCell(p_coords)) return wxT(""); if (m_table->NumRowPlayers() == 0) return wxT("Payoffs"); const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); int player = m_table->GetRowPlayer(p_coords.GetCol() + 1); int strat = m_table->RowToStrategy(p_coords.GetCol() + 1, p_coords.GetRow()); return wxString(support.GetStrategy(player, strat)->GetLabel().c_str(), *wxConvCurrent); } void gbtRowPlayerWidget::SetCellValue(const wxSheetCoords &p_coords, const wxString &p_value) { const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); int player = m_table->GetRowPlayer(p_coords.GetCol() + 1); int strat = m_table->RowToStrategy(p_coords.GetCol() + 1, p_coords.GetRow()); support.GetStrategy(player, strat)->SetLabel((const char *) p_value.mb_str()); m_doc->UpdateViews(GBT_DOC_MODIFIED_LABELS); } wxSheetCellAttr gbtRowPlayerWidget::GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const { wxSheetCellAttr attr(GetSheetRefData()->m_defaultGridCellAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); if (m_table->NumRowPlayers() > 0) { attr.SetForegroundColour(m_doc->GetStyle().GetPlayerColor(m_table->GetRowPlayer(p_coords.GetCol()+1))); attr.SetReadOnly(m_doc->IsTree()); } else { attr.SetForegroundColour(*wxBLACK); attr.SetReadOnly(true); } attr.SetBackgroundColour(*wxLIGHT_GREY); return attr; } void gbtRowPlayerWidget::DrawCell(wxDC &p_dc, const wxSheetCoords &p_coords) { gbtTableWidgetBase::DrawCell(p_dc, p_coords); if (!m_table->ShowDominance() || IsLabelCell(p_coords) || m_table->NumRowPlayers() == 0) return; const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); int player = m_table->GetRowPlayer(p_coords.GetCol() + 1); int strat = m_table->RowToStrategy(p_coords.GetCol() + 1, p_coords.GetRow()); Gambit::GameStrategy strategy = support.GetStrategy(player, strat); if (support.IsDominated(strategy, false)) { wxRect rect = CellToRect(p_coords); if (support.IsDominated(strategy, true)) { p_dc.SetPen(wxPen(m_doc->GetStyle().GetPlayerColor(player), 2, wxSOLID)); } else { p_dc.SetPen(wxPen(m_doc->GetStyle().GetPlayerColor(player), 1, wxSHORT_DASH)); } p_dc.DrawLine(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); p_dc.DrawLine(rect.x + rect.width, rect.y, rect.x, rect.y + rect.height); } } void gbtRowPlayerWidget::OnUpdate(void) { int newRows = m_table->NumRowContingencies(); if (newRows > GetNumberRows()) InsertRows(0, newRows - GetNumberRows()); if (newRows < GetNumberRows()) DeleteRows(0, GetNumberRows() - newRows); int newCols = m_table->NumRowPlayers(); if (newCols > GetNumberCols()) InsertCols(0, newCols - GetNumberCols()); if (newCols < GetNumberCols()) DeleteCols(0, GetNumberCols() - newCols); if (newCols == 0) InsertCols(0, 1); for (int col = 0; col < GetNumberCols(); col++) { for (int row = 0; row < GetNumberRows(); SetCellSpan(wxSheetCoords(row++, col), wxSheetCoords(1, 1))); int span = m_table->NumRowsSpanned(col+1); int row = 0; while (row < GetNumberRows()) { SetCellSpan(wxSheetCoords(row, col), wxSheetCoords(span, 1)); row += span; } } Refresh(); } bool gbtRowPlayerWidget::DropText(wxCoord p_x, wxCoord p_y, const wxString &p_text) { if (p_text[0] == 'P') { long pl; p_text.Right(p_text.Length() - 1).ToLong(&pl); if (m_table->NumRowPlayers() == 0) { m_table->SetRowPlayer(1, pl); return true; } for (int col = 0; col < GetNumberCols(); col++) { wxRect rect = CellToRect(wxSheetCoords(0, col)); if (p_x >= rect.x && p_x < rect.x + rect.width/2) { m_table->SetRowPlayer(col+1, pl); return true; } else if (p_x >= rect.x + rect.width/2 && p_x < rect.x + rect.width) { m_table->SetRowPlayer(col+2, pl); return true; } } } return false; } //========================================================================= // class gbtColPlayerWidget //========================================================================= class gbtColPlayerWidget : public gbtTableWidgetBase { private: gbtGameDocument *m_doc; gbtTableWidget *m_table; /// @name Overriding wxSheet members for data access //@{ /// Returns the value in the cell wxString GetCellValue(const wxSheetCoords &); /// Sets the value in the cell, by relabeling the strategy void SetCellValue(const wxSheetCoords &, const wxString &); /// Returns the attributes of the cell wxSheetCellAttr GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const; //@} /// @name Overriding wxSheet members to customize drawing //@{ /// Overrides to draw dominance indicators void DrawCell(wxDC &p_dc, const wxSheetCoords &p_coords); //@} void OnCellRightClick(wxSheetEvent &); public: /// @name Lifecycle //@{ /// Constructor gbtColPlayerWidget(gbtTableWidget *p_parent, gbtGameDocument *p_doc); //@} /// @name Synchronizing with document state //@{ void OnUpdate(void); //@} /// @name Drop target interaction //@{ /// Called when the drop target receives text. bool DropText(int p_x, int p_y, const wxString &p_text); //@} }; gbtColPlayerWidget::gbtColPlayerWidget(gbtTableWidget *p_parent, gbtGameDocument *p_doc) : gbtTableWidgetBase(p_parent, -1), m_doc(p_doc), m_table(p_parent) { CreateGrid(m_table->NumColPlayers(), 0); SetRowLabelWidth(1); SetColLabelHeight(1); SetScrollBarMode(SB_NEVER); SetGridLineColour(*wxBLACK); SetBackgroundColour(*wxLIGHT_GREY); SetDropTarget(new gbtTableWidgetDropTarget(this)); Connect(GetId(), wxEVT_SHEET_CELL_RIGHT_DOWN, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtColPlayerWidget::OnCellRightClick))); } void gbtColPlayerWidget::OnCellRightClick(wxSheetEvent &p_event) { if (m_table->NumColPlayers() == 0 || m_doc->GetGame()->IsTree()) { p_event.Skip(); return; } const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); wxSheetCoords coords = p_event.GetCoords(); int player = m_table->GetColPlayer(coords.GetRow() + 1); int strat = m_table->RowToStrategy(coords.GetRow() + 1, coords.GetCol()); support.GetStrategy(player, strat)->DeleteStrategy(); m_doc->UpdateViews(GBT_DOC_MODIFIED_GAME); } void gbtColPlayerWidget::OnUpdate(void) { int newCols = m_table->NumColContingencies() * m_doc->NumPlayers(); if (newCols > GetNumberCols()) InsertCols(0, newCols - GetNumberCols()); if (newCols < GetNumberCols()) DeleteCols(0, GetNumberCols() - newCols); int newRows = m_table->NumColPlayers(); if (newRows > GetNumberRows()) InsertRows(0, newRows - GetNumberRows()); if (newRows < GetNumberRows()) DeleteRows(0, GetNumberRows() - newRows); if (newRows == 0) InsertRows(0, 1); for (int row = 0; row < GetNumberRows(); row++) { for (int col = 0; col < GetNumberCols(); SetCellSpan(wxSheetCoords(row, col++), wxSheetCoords(1, 1))); int span = m_table->NumColsSpanned(row+1) * m_doc->NumPlayers(); int col = 0; while (col < GetNumberCols()) { SetCellSpan(wxSheetCoords(row, col), wxSheetCoords(1, span)); col += span; } } Refresh(); } wxString gbtColPlayerWidget::GetCellValue(const wxSheetCoords &p_coords) { if (IsLabelCell(p_coords)) return wxT(""); if (m_table->NumColPlayers() == 0) return wxT("Payoffs"); const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); int player = m_table->GetColPlayer(p_coords.GetRow() + 1); int strat = m_table->ColToStrategy(p_coords.GetRow() + 1, p_coords.GetCol()); return wxString(support.GetStrategy(player, strat)->GetLabel().c_str(), *wxConvCurrent); } void gbtColPlayerWidget::SetCellValue(const wxSheetCoords &p_coords, const wxString &p_value) { const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); int player = m_table->GetColPlayer(p_coords.GetRow() + 1); int strat = m_table->ColToStrategy(p_coords.GetRow() + 1, p_coords.GetCol()); support.GetStrategy(player, strat)->SetLabel((const char *) p_value.mb_str()); m_doc->UpdateViews(GBT_DOC_MODIFIED_LABELS); } wxSheetCellAttr gbtColPlayerWidget::GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const { wxSheetCellAttr attr(GetSheetRefData()->m_defaultGridCellAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); if (m_table->NumColPlayers() > 0) { attr.SetForegroundColour(m_doc->GetStyle().GetPlayerColor(m_table->GetColPlayer(p_coords.GetRow()+1))); attr.SetReadOnly(m_doc->IsTree()); } else { attr.SetForegroundColour(*wxBLACK); attr.SetReadOnly(true); } attr.SetBackgroundColour(*wxLIGHT_GREY); return attr; } void gbtColPlayerWidget::DrawCell(wxDC &p_dc, const wxSheetCoords &p_coords) { gbtTableWidgetBase::DrawCell(p_dc, p_coords); if (!m_table->ShowDominance() || IsLabelCell(p_coords) || m_table->NumColPlayers() == 0) return; const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); int player = m_table->GetColPlayer(p_coords.GetRow() + 1); int strat = m_table->ColToStrategy(p_coords.GetRow() + 1, p_coords.GetCol()); Gambit::GameStrategy strategy = support.GetStrategy(player, strat); if (support.IsDominated(strategy, false)) { wxRect rect = CellToRect(p_coords); if (support.IsDominated(strategy, true)) { p_dc.SetPen(wxPen(m_doc->GetStyle().GetPlayerColor(player), 2, wxSOLID)); } else { p_dc.SetPen(wxPen(m_doc->GetStyle().GetPlayerColor(player), 1, wxSHORT_DASH)); } p_dc.DrawLine(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); p_dc.DrawLine(rect.x + rect.width, rect.y, rect.x, rect.y + rect.height); } } bool gbtColPlayerWidget::DropText(wxCoord p_x, wxCoord p_y, const wxString &p_text) { if (p_text[0] == 'P') { long pl; p_text.Right(p_text.Length() - 1).ToLong(&pl); if (m_table->NumColPlayers() == 0) { m_table->SetColPlayer(1, pl); return true; } for (int col = 0; col < GetNumberCols(); col++) { wxRect rect = CellToRect(wxSheetCoords(col, 0)); if (p_y >= rect.y && p_y < rect.y + rect.height/2) { m_table->SetColPlayer(col+1, pl); return true; } else if (p_y >= rect.y + rect.height/2 && p_y < rect.y + rect.height) { m_table->SetColPlayer(col+2, pl); return true; } } } return false; } //========================================================================= // class gbtPayoffsWidget //========================================================================= class gbtPayoffsWidget : public gbtTableWidgetBase { private: gbtGameDocument *m_doc; gbtTableWidget *m_table; /// @name Overriding wxSheet members for data access //@{ /// Returns the value in the cell wxString GetCellValue(const wxSheetCoords &); /// Sets the value in the cell, by editing the outcome void SetCellValue(const wxSheetCoords &, const wxString &); /// Returns the attributes of the cell wxSheetCellAttr GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const; //@} /// @name Overriding wxSheet members for drawing behavior //@{ /// Draws dark borders between contingencies void DrawCellBorder(wxDC &p_dc, const wxSheetCoords &p_coords); /// Overrides to draw dominance indicators void DrawCell(wxDC &p_dc, const wxSheetCoords &p_coords); //@} /// @name Overriding wxSheet members for event-handling behavior //@{ /// Implement custom tab-traversal behavior void OnKeyDown(wxKeyEvent &); //@} /// Maps columns to corresponding player int ColToPlayer(int p_col) const; public: gbtPayoffsWidget(gbtTableWidget *p_parent, gbtGameDocument *p_doc); /// @name Synchronizing with document state //@{ void OnUpdate(void); //@} DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(gbtPayoffsWidget, gbtTableWidgetBase) EVT_KEY_DOWN(gbtPayoffsWidget::OnKeyDown) END_EVENT_TABLE() gbtPayoffsWidget::gbtPayoffsWidget(gbtTableWidget *p_parent, gbtGameDocument *p_doc) : gbtTableWidgetBase(p_parent, -1), m_doc(p_doc), m_table(p_parent) { CreateGrid(0, 0); SetRowLabelWidth(1); SetColLabelHeight(1); } // // Payoffs are ordered first by row players (in hierarchical order), // followed by column players (in hierarchical order) // int gbtPayoffsWidget::ColToPlayer(int p_col) const { int index = p_col % m_doc->NumPlayers() + 1; if (index <= m_table->NumRowPlayers()) { return m_table->GetRowPlayer(index); } else { return m_table->GetColPlayer(index - m_table->NumRowPlayers()); } } void gbtPayoffsWidget::OnUpdate(void) { int newCols = m_table->NumColContingencies() * m_doc->NumPlayers(); if (newCols > GetNumberCols()) InsertCols(0, newCols - GetNumberCols()); if (newCols < GetNumberCols()) DeleteCols(0, GetNumberCols() - newCols); int newRows = m_table->NumRowContingencies(); if (newRows > GetNumberRows()) InsertRows(0, newRows - GetNumberRows()); if (newRows < GetNumberRows()) DeleteRows(0, GetNumberRows() - newRows); Refresh(); } wxString gbtPayoffsWidget::GetCellValue(const wxSheetCoords &p_coords) { if (IsLabelCell(p_coords)) return wxT(""); Gambit::PureStrategyProfile profile = m_table->CellToProfile(p_coords); int player = ColToPlayer(p_coords.GetCol()); return wxString(profile.GetPayoff(player).c_str(), *wxConvCurrent); } void gbtPayoffsWidget::SetCellValue(const wxSheetCoords &p_coords, const wxString &p_value) { Gambit::PureStrategyProfile profile = m_table->CellToProfile(p_coords); Gambit::GameOutcome outcome = profile.GetOutcome(); if (!outcome) { outcome = m_doc->GetGame()->NewOutcome(); profile.SetOutcome(outcome); } int player = ColToPlayer(p_coords.GetCol()); try { outcome->SetPayoff(player, (const char *) p_value.mb_str()); } catch (ValueException &) { // For the moment, we will just silently discard edits which // give payoffs that are not valid numbers return; } m_doc->UpdateViews(GBT_DOC_MODIFIED_PAYOFFS); } wxSheetCellAttr gbtPayoffsWidget::GetAttr(const wxSheetCoords &p_coords, wxSheetAttr_Type) const { if (IsLabelCell(p_coords)) { wxSheetCellAttr attr(GetSheetRefData()->m_defaultColLabelAttr); attr.SetBackgroundColour(*wxLIGHT_GREY); return attr; } wxSheetCellAttr attr(GetSheetRefData()->m_defaultGridCellAttr); attr.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)); attr.SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); attr.SetOrientation(wxHORIZONTAL); int player = ColToPlayer(p_coords.GetCol()); attr.SetForegroundColour(m_doc->GetStyle().GetPlayerColor(player)); attr.SetRenderer(wxSheetCellRenderer(new gbtRationalRendererRefData())); attr.SetEditor(wxSheetCellEditor(new gbtRationalEditorRefData())); attr.SetReadOnly(m_doc->IsTree()); return attr; } void gbtPayoffsWidget::DrawCellBorder(wxDC &p_dc, const wxSheetCoords &p_coords) { gbtTableWidgetBase::DrawCellBorder(p_dc, p_coords); wxRect rect(CellToRect(p_coords)); if (rect.width < 1 || rect.height < 1) return; p_dc.SetPen(wxPen(*wxBLACK, 1, wxSOLID)); // Draw the dark border to the right of the last column of a contingency if ((p_coords.GetCol() + 1) % m_doc->GetGame()->NumPlayers() == 0) { p_dc.DrawLine(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + rect.height + 1); } // Draw the bottom border -- currently always dark p_dc.DrawLine(rect.x - 1, rect.y + rect.height, rect.x + rect.width, rect.y + rect.height); // Draw the top border for the first row if (p_coords.GetRow() == 0) { p_dc.DrawLine(rect.x - 1, rect.y, rect.x + rect.width, rect.y); } } void gbtPayoffsWidget::DrawCell(wxDC &p_dc, const wxSheetCoords &p_coords) { gbtTableWidgetBase::DrawCell(p_dc, p_coords); if (!m_table->ShowDominance() || IsLabelCell(p_coords)) return; Gambit::PureStrategyProfile profile = m_table->CellToProfile(p_coords); int player = ColToPlayer(p_coords.GetCol()); const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); if (support.IsDominated(profile.GetStrategy(player), false)) { wxRect rect = CellToRect(p_coords); if (support.IsDominated(profile.GetStrategy(player), true)) { p_dc.SetPen(wxPen(m_doc->GetStyle().GetPlayerColor(player), 2, wxSOLID)); } else { p_dc.SetPen(wxPen(m_doc->GetStyle().GetPlayerColor(player), 1, wxSHORT_DASH)); } p_dc.DrawLine(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); p_dc.DrawLine(rect.x + rect.width, rect.y, rect.x, rect.y + rect.height); } } //! //! Overriding default wxSheet behavior: when editing, accepting the //! edited value via the TAB key automatically moves the cursor to //! the right *and* creates the editor in the next cell. In addition, //! tabbing off the rightmost cell entry automatically "wraps" to the //! next row. //! void gbtPayoffsWidget::OnKeyDown(wxKeyEvent &p_event) { if (GetNumberRows() && GetNumberCols()) { switch (p_event.GetKeyCode()) { case WXK_TAB: { if (IsCellEditControlCreated()) { DisableCellEditControl(true); int newRow = GetGridCursorRow(), newCol = GetGridCursorCol(); if (p_event.ShiftDown()) { newCol--; if (newCol < 0) { newCol = GetNumberCols() - 1; newRow--; if (newRow < 0) { newRow = GetNumberRows() - 1; } } } else { newCol++; if (newCol >= GetNumberCols()) { newCol = 0; newRow++; if (newRow >= GetNumberRows()) { newRow = 0; } } } SetGridCursorCell(wxSheetCoords(newRow, newCol)); MakeCellVisible(GetGridCursorCell()); EnableCellEditControl(GetGridCursorCell()); } break; } default: p_event.Skip(); } } } //========================================================================= // gbtTableWidget: Lifecycle //========================================================================= gbtTableWidget::gbtTableWidget(gbtNfgPanel *p_parent, wxWindowID p_id, gbtGameDocument *p_doc) : wxPanel(p_parent, p_id), m_doc(p_doc), m_nfgPanel(p_parent) { m_rowPlayers.Append(1); m_colPlayers.Append(2); m_payoffSheet = new gbtPayoffsWidget(this, p_doc); m_payoffSheet->SetGridLineColour(*wxWHITE); m_rowSheet = new gbtRowPlayerWidget(this, p_doc); m_colSheet = new gbtColPlayerWidget(this, p_doc); wxFlexGridSizer *topSizer = new wxFlexGridSizer(2, 2); topSizer->AddGrowableRow(1); topSizer->AddGrowableCol(1); topSizer->Add(new wxPanel(this, -1)); topSizer->Add(m_colSheet, 1, wxEXPAND, 0); topSizer->Add(m_rowSheet, 1, wxEXPAND, 0); topSizer->Add(m_payoffSheet, 1, wxEXPAND, 0); SetSizer(topSizer); Layout(); Connect(m_colSheet->GetId(), wxEVT_SHEET_VIEW_CHANGED, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnRowSheetScroll))); Connect(m_colSheet->GetId(), wxEVT_SHEET_VIEW_CHANGED, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnColSheetScroll))); Connect(m_payoffSheet->GetId(), wxEVT_SHEET_VIEW_CHANGED, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnPayoffScroll))); Connect(m_rowSheet->GetId(), wxEVT_SHEET_ROW_SIZE, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnRowSheetRow))); Connect(m_payoffSheet->GetId(), wxEVT_SHEET_ROW_SIZE, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnPayoffRow))); Connect(m_colSheet->GetId(), wxEVT_SHEET_COL_SIZE, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnColSheetColumn))); Connect(m_payoffSheet->GetId(), wxEVT_SHEET_COL_SIZE, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnPayoffColumn))); Connect(m_rowSheet->GetId(), wxEVT_SHEET_COL_SIZE, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnRowSheetColumn))); Connect(m_colSheet->GetId(), wxEVT_SHEET_ROW_SIZE, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnColSheetRow))); Connect(m_rowSheet->GetId(), wxEVT_SHEET_EDITOR_ENABLED, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnBeginEdit))); Connect(m_colSheet->GetId(), wxEVT_SHEET_EDITOR_ENABLED, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnBeginEdit))); Connect(m_payoffSheet->GetId(), wxEVT_SHEET_EDITOR_ENABLED, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, wxSheetEventFunction(&gbtTableWidget::OnBeginEdit))); } //! //! Scroll row and column label sheets to match payoff sheet origin. //! Note that wxSheet uses coordinates of -1 to indicate no scroll. //! //@{ void gbtTableWidget::OnRowSheetScroll(wxSheetEvent &) { m_payoffSheet->SetGridOrigin(-1, m_rowSheet->GetGridOrigin().y); } void gbtTableWidget::OnColSheetScroll(wxSheetEvent &) { m_payoffSheet->SetGridOrigin(m_colSheet->GetGridOrigin().x, -1); } void gbtTableWidget::OnPayoffScroll(wxSheetEvent &) { m_colSheet->SetGridOrigin(m_payoffSheet->GetGridOrigin().x, 0); m_rowSheet->SetGridOrigin(0, m_payoffSheet->GetGridOrigin().y); } //@} //! //! These keep the row heights synchronized //! //@{ void gbtTableWidget::OnRowSheetRow(wxSheetEvent &p_event) { int height = m_rowSheet->GetRowHeight(p_event.GetRow()); m_payoffSheet->SetDefaultRowHeight(height, true); m_payoffSheet->AdjustScrollbars(); m_payoffSheet->Refresh(); m_rowSheet->SetDefaultRowHeight(height, true); m_rowSheet->Refresh(); } void gbtTableWidget::OnPayoffRow(wxSheetEvent &p_event) { int height = m_payoffSheet->GetRowHeight(p_event.GetRow()); m_payoffSheet->SetDefaultRowHeight(height, true); m_payoffSheet->AdjustScrollbars(); m_payoffSheet->Refresh(); m_rowSheet->SetDefaultRowHeight(height, true); m_rowSheet->Refresh(); } //@} //! //! These keep the column widths synchronized //! //@{ void gbtTableWidget::OnColSheetColumn(wxSheetEvent &p_event) { int width = m_colSheet->GetColWidth(p_event.GetCol()); m_payoffSheet->SetDefaultColWidth(width, true); m_payoffSheet->AdjustScrollbars(); m_payoffSheet->Refresh(); m_colSheet->SetDefaultColWidth(width, true); m_colSheet->Refresh(); } void gbtTableWidget::OnPayoffColumn(wxSheetEvent &p_event) { int width = m_payoffSheet->GetColWidth(p_event.GetCol()); m_payoffSheet->SetDefaultColWidth(width, true); m_payoffSheet->AdjustScrollbars(); m_payoffSheet->Refresh(); m_colSheet->SetDefaultColWidth(width, true); m_colSheet->Refresh(); } //@} //! //! These handle correctly sizing the label windows //! //@{ void gbtTableWidget::OnRowSheetColumn(wxSheetEvent &p_event) { m_rowSheet->SetDefaultColWidth(m_rowSheet->GetColWidth(p_event.GetCol()), true); GetSizer()->Layout(); } void gbtTableWidget::OnColSheetRow(wxSheetEvent &p_event) { m_colSheet->SetDefaultRowHeight(m_colSheet->GetRowHeight(p_event.GetRow()), true); GetSizer()->Layout(); } //@} //! //! This alerts the document to have any other windows post their pending //! edits. //! void gbtTableWidget::OnBeginEdit(wxSheetEvent &) { m_doc->PostPendingChanges(); } void gbtTableWidget::OnUpdate(void) { if (m_doc->NumPlayers() > m_rowPlayers.Length() + m_colPlayers.Length()) { for (int pl = 1; pl <= m_doc->NumPlayers(); pl++) { if (!m_rowPlayers.Contains(pl) && !m_colPlayers.Contains(pl)) { m_rowPlayers.Append(pl); } } } else if (m_doc->NumPlayers() < m_rowPlayers.Length() + m_colPlayers.Length()) { for (int i = 1; i <= m_rowPlayers.Length(); i++) { if (m_rowPlayers[i] > m_doc->NumPlayers()) { m_rowPlayers.Remove(i--); } } for (int i = 1; i <= m_colPlayers.Length(); i++) { if (m_colPlayers[i] > m_doc->NumPlayers()) { m_colPlayers.Remove(i--); } } } dynamic_cast(m_payoffSheet)->OnUpdate(); // We add margins to the player labels to match the scrollbars, // so scrolling matches up m_colSheet->SetMargins(dynamic_cast(m_payoffSheet)->GetVerticalScrollBar()->GetSize().GetWidth(), -1); m_rowSheet->SetMargins(-1, dynamic_cast(m_payoffSheet)->GetHorizontalScrollBar()->GetSize().GetHeight()); dynamic_cast(m_rowSheet)->OnUpdate(); dynamic_cast(m_colSheet)->OnUpdate(); GetSizer()->Layout(); } void gbtTableWidget::PostPendingChanges(void) { if (m_payoffSheet->IsCellEditControlShown()) { m_payoffSheet->DisableCellEditControl(true); } if (m_rowSheet->IsCellEditControlShown()) { m_rowSheet->DisableCellEditControl(true); } if (m_colSheet->IsCellEditControlShown()) { m_colSheet->DisableCellEditControl(true); } } bool gbtTableWidget::ShowDominance(void) const { return m_nfgPanel->IsDominanceShown(); } //========================================================================= // gbtTableWidget: View state //========================================================================= void gbtTableWidget::SetRowPlayer(int index, int pl) { if (m_rowPlayers.Contains(pl)) { int oldIndex = m_rowPlayers.Find(pl); m_rowPlayers.Remove(oldIndex); if (index > oldIndex) { m_rowPlayers.Insert(pl, index-1); } else { m_rowPlayers.Insert(pl, index); } } else { m_colPlayers.Remove(m_colPlayers.Find(pl)); m_rowPlayers.Insert(pl, index); } OnUpdate(); } int gbtTableWidget::NumRowContingencies(void) const { if (!m_doc->GetGame()->IsTree() || (m_doc->GetGame()->IsTree() && m_doc->GetGame()->HasComputedValues())) { int ncont = 1; const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); for (int i = 1; i <= NumRowPlayers(); ncont *= support.NumStrategies(GetRowPlayer(i++))); return ncont; } else { return 0; } } int gbtTableWidget::NumRowsSpanned(int index) const { if (!m_doc->GetGame()->IsTree() || (m_doc->GetGame()->IsTree() && m_doc->GetGame()->HasComputedValues())) { int ncont = 1; const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); for (int i = index + 1; i <= NumRowPlayers(); ncont *= support.NumStrategies(GetRowPlayer(i++))); return ncont; } else { return 1; } } int gbtTableWidget::RowToStrategy(int player, int row) const { int strat = row / NumRowsSpanned(player); return (strat % m_doc->GetNfgSupport().NumStrategies(GetRowPlayer(player)) + 1); } void gbtTableWidget::SetColPlayer(int index, int pl) { if (m_colPlayers.Contains(pl)) { int oldIndex = m_colPlayers.Find(pl); m_colPlayers.Remove(oldIndex); if (index > oldIndex) { m_colPlayers.Insert(pl, index-1); } else { m_colPlayers.Insert(pl, index); } } else { m_rowPlayers.Remove(m_rowPlayers.Find(pl)); m_colPlayers.Insert(pl, index); } OnUpdate(); } int gbtTableWidget::NumColContingencies(void) const { if (!m_doc->GetGame()->IsTree() || (m_doc->GetGame()->IsTree() && m_doc->GetGame()->HasComputedValues())) { int ncont = 1; const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); for (int i = 1; i <= NumColPlayers(); ncont *= support.NumStrategies(GetColPlayer(i++))); return ncont; } else { return 0; } } int gbtTableWidget::NumColsSpanned(int index) const { if (!m_doc->GetGame()->IsTree() || (m_doc->GetGame()->IsTree() && m_doc->GetGame()->HasComputedValues())) { int ncont = 1; const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); for (int i = index + 1; i <= NumColPlayers(); ncont *= support.NumStrategies(GetColPlayer(i++))); return ncont; } else { return 1; } } int gbtTableWidget::ColToStrategy(int player, int col) const { int strat = col / m_doc->NumPlayers() / NumColsSpanned(player); return (strat % m_doc->GetNfgSupport().NumStrategies(GetColPlayer(player)) + 1); } Gambit::PureStrategyProfile gbtTableWidget::CellToProfile(const wxSheetCoords &p_coords) const { const Gambit::StrategySupport &support = m_doc->GetNfgSupport(); Gambit::PureStrategyProfile profile(m_doc->GetGame()); for (int i = 1; i <= NumRowPlayers(); i++) { int player = GetRowPlayer(i); profile.SetStrategy(support.GetStrategy(player, RowToStrategy(i, p_coords.GetRow()))); } for (int i = 1; i <= NumColPlayers(); i++) { int player = GetColPlayer(i); profile.SetStrategy(support.GetStrategy(player, ColToStrategy(i, p_coords.GetCol()))); } return profile; } class gbtNfgPrintout : public wxPrintout { private: gbtTableWidget *m_table; public: gbtNfgPrintout(gbtTableWidget *p_table, const wxString &p_label) : wxPrintout(p_label), m_table(p_table) { } virtual ~gbtNfgPrintout() { } bool OnPrintPage(int) { m_table->RenderGame(*GetDC(), 50, 50); return true; } bool HasPage(int page) { return (page <= 1); } void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) { *minPage = 1; *maxPage = 1; *selPageFrom = 1; *selPageTo = 1; } }; wxPrintout *gbtTableWidget::GetPrintout(void) { return new gbtNfgPrintout(this, wxString(m_doc->GetGame()->GetTitle().c_str(), *wxConvCurrent)); } bool gbtTableWidget::GetBitmap(wxBitmap &p_bitmap, int p_marginX, int p_marginY) { int width = (m_rowSheet->CellToRect(wxSheetCoords(0, m_rowSheet->GetNumberCols() - 1)).GetRight() + m_colSheet->CellToRect(wxSheetCoords(0, m_colSheet->GetNumberCols() - 1)).GetRight() + 2 * p_marginX); int height = (m_rowSheet->CellToRect(wxSheetCoords(m_rowSheet->GetNumberRows() - 1, 0)).GetBottom() + m_colSheet->CellToRect(wxSheetCoords(m_colSheet->GetNumberRows() - 1, 0)).GetBottom() + 2 * p_marginY); if (width > 65000 || height > 65000) { // This is just too huge to export to graphics return false; } wxMemoryDC dc; p_bitmap = wxBitmap(width, height); dc.SelectObject(p_bitmap); dc.Clear(); RenderGame(dc, p_marginX, p_marginY); return true; } void gbtTableWidget::GetSVG(const wxString &p_filename, int p_marginX, int p_marginY) { int width = (m_rowSheet->CellToRect(wxSheetCoords(0, m_rowSheet->GetNumberCols() - 1)).GetRight() + m_colSheet->CellToRect(wxSheetCoords(0, m_colSheet->GetNumberCols() - 1)).GetRight() + 2 * p_marginX); int height = (m_rowSheet->CellToRect(wxSheetCoords(m_rowSheet->GetNumberRows() - 1, 0)).GetBottom() + m_colSheet->CellToRect(wxSheetCoords(m_colSheet->GetNumberRows() - 1, 0)).GetBottom() + 2 * p_marginY); wxSVGFileDC dc(p_filename, width, height); // For some reason, this needs to be initialized dc.SetLogicalScale(1.0, 1.0); RenderGame(dc, p_marginX, p_marginY); } void gbtTableWidget::RenderGame(wxDC &p_dc, int p_marginX, int p_marginY) { // The size of the image to be drawn int maxX = (m_rowSheet->CellToRect(wxSheetCoords(0, m_rowSheet->GetNumberCols() - 1)).GetRight() + m_colSheet->CellToRect(wxSheetCoords(0, m_colSheet->GetNumberCols() - 1)).GetRight()); int maxY = (m_rowSheet->CellToRect(wxSheetCoords(m_rowSheet->GetNumberRows() - 1, 0)).GetBottom() + m_colSheet->CellToRect(wxSheetCoords(m_colSheet->GetNumberRows() - 1, 0)).GetBottom()); // Get the size of the DC in pixels wxCoord w, h; p_dc.GetSize(&w, &h); // Calculate a scaling factor double scaleX = (double) w / (double) (maxX + 2*p_marginX); double scaleY = (double) h / (double) (maxY + 2*p_marginY); double scale = (scaleX < scaleY) ? scaleX : scaleY; // Here, zooming in is often a good idea, since the number of pixels // on a page is generally quite large p_dc.SetUserScale(scale, scale); // Calculate the position on the DC to center the tree double posX = (double) ((w - (maxX * scale)) / 2.0); double posY = (double) ((h - (maxY * scale)) / 2.0); // The X and Y coordinates of the upper left of the payoff table int payoffX = (int) (m_rowSheet->CellToRect(wxSheetCoords(0, m_rowSheet->GetNumberCols() - 1)).GetRight() * scale); int payoffY = (int) (m_colSheet->CellToRect(wxSheetCoords(m_colSheet->GetNumberRows() - 1, 0)).GetBottom() * scale); p_dc.SetDeviceOrigin((int) posX, payoffY + (int) posY); m_rowSheet->DrawGridCells(p_dc, wxSheetBlock(0, 0, m_rowSheet->GetNumberRows(), m_rowSheet->GetNumberCols())); p_dc.SetDeviceOrigin(payoffX + (int) posX, (int) posY); m_colSheet->DrawGridCells(p_dc, wxSheetBlock(0, 0, m_colSheet->GetNumberRows(), m_colSheet->GetNumberCols())); p_dc.SetDeviceOrigin(payoffX + (int) posX, payoffY + (int) posY); m_payoffSheet->DrawGridCells(p_dc, wxSheetBlock(0, 0, m_payoffSheet->GetNumberRows(), m_payoffSheet->GetNumberCols())); } gambit-0.2010.09.01/src/gui/nfgtable.h0000644000076500007650000001156111435216101013744 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/nfgtable.h // Declaration of control to display/edit strategic game tables // // 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 NFGTABLE_H #define NFGTABLE_H class gbtGameDocument; class gbtNfgPanel; //! //! This is a panel which manages three wxSheet instances: one which //! contains the payoffs of the strategic form, and two which handle //! the display of row and column labels //! class gbtTableWidget : public wxPanel { private: gbtGameDocument *m_doc; gbtNfgPanel *m_nfgPanel; wxSheet *m_payoffSheet, *m_rowSheet, *m_colSheet; Gambit::Array m_rowPlayers, m_colPlayers; /// @name Event handlers //@{ /// Called when row label sheet is scrolled void OnRowSheetScroll(wxSheetEvent &); /// Called when column label sheet is scrolled void OnColSheetScroll(wxSheetEvent &); /// Called when payoff sheet is scrolled void OnPayoffScroll(wxSheetEvent &); /// Called when row label sheet row is resized void OnRowSheetRow(wxSheetEvent &); /// Called when payoff sheet row is resized void OnPayoffRow(wxSheetEvent &); /// Called when col label sheet column is resized void OnColSheetColumn(wxSheetEvent &); /// Called when payoff sheet column is resized void OnPayoffColumn(wxSheetEvent &); /// Called when row label sheet column is resized void OnRowSheetColumn(wxSheetEvent &); /// Called when column label sheet row is resized void OnColSheetRow(wxSheetEvent &); /// Called when editing begins in any cell void OnBeginEdit(wxSheetEvent &); //@} public: gbtTableWidget(gbtNfgPanel *p_parent, wxWindowID p_id, gbtGameDocument *p_doc); /// @name Coordination of sheets //@{ /// Scroll row and column label sheets void SetGridOrigin(int x, int y); /// Synchronize with document state void OnUpdate(void); /// Post any pending edits void PostPendingChanges(void); /// Are we showing dominance indicators or not? bool ShowDominance(void) const; //@} /// @name View state //@{ /// Returns the number of players assigned to the rows int NumRowPlayers(void) const { return m_rowPlayers.Length(); } /// Returns the index'th player assigned to the rows (1=slowest incrementing) int GetRowPlayer(int index) const { return m_rowPlayers[index]; } /// Sets the index'th row player (1=slowest, n+1=fastest) void SetRowPlayer(int index, int pl); /// Returns the number of row contingencies (i.e., rows in the table) int NumRowContingencies(void) const; /// Returns the number of rows spanned by strategy of row player index int NumRowsSpanned(int index) const; /// Returns the strategy index for row player 'player' corresponding to 'row' int RowToStrategy(int player, int row) const; /// Returns the number of players assigned to the columns int NumColPlayers(void) const { return m_colPlayers.Length(); } /// Returns the index'th player assigned to the columns (1=slowest) int GetColPlayer(int index) const { return m_colPlayers[index]; } /// Sets the index'th column player (1=slowest, n+1=fastest) void SetColPlayer(int index, int pl); /// Returns the number of column contingencies /// (Note that each column contingency corresponds to #players cols!) int NumColContingencies(void) const; /// Returns the number of columns spanned by strategy of column player index int NumColsSpanned(int index) const; /// Returns the strategy index for row player 'player' corresponding to 'row' int ColToStrategy(int player, int row) const; /// Returns the strategy profile corresponding to a cell Gambit::PureStrategyProfile CellToProfile(const wxSheetCoords &) const; //@} /// @name Exporting/printing graphics //@{ /// Creates a printout object of the game as currently displayed wxPrintout *GetPrintout(void); /// Creates a bitmap of the game as currently displayed bool GetBitmap(wxBitmap &, int marginX, int marginY); /// Outputs the game as currently displayed to a SVG file void GetSVG(const wxString &p_filename, int marginX, int marginY); /// Prints the game as currently displayed, centered on the DC void RenderGame(wxDC &p_dc, int marginX, int marginY); //@} }; #endif // NFGTABLE_H gambit-0.2010.09.01/src/gui/renratio.cc0000644000076500007650000001657711435216101014157 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/renratio.cc // Implementation of wxSheet renderer for rational numbers // // 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "renratio.h" #include "wx/sheet/sheet.h" // the wxSheet widget //---------------------------------------------------------------------------- // class gbtRationalRendererRefData //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(gbtRationalRendererRefData, wxSheetCellRendererRefData) void gbtRationalRendererRefData::SetTextColoursAndFont(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, bool isSelected) { dc.SetBackgroundMode(wxTRANSPARENT); if (grid.IsEnabled()) { if (isSelected) { dc.SetTextBackground(grid.GetSelectionBackground()); dc.SetTextForeground(grid.GetSelectionForeground()); } else { dc.SetTextBackground(attr.GetBackgroundColour()); dc.SetTextForeground(attr.GetForegroundColour()); } } else { dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); } dc.SetFont(attr.GetFont()); } static wxSize GetFractionExtent(wxDC &p_dc, const wxString &p_value) { p_dc.SetFont(wxFont(7, wxSWISS, wxNORMAL, wxBOLD)); wxString num; int i = 0; while (p_value[i] != '/') num += p_value[i++]; i++; wxString den; while (p_value[i] != '\0') den += p_value[i++]; int numWidth, numHeight; p_dc.GetTextExtent(num, &numWidth, &numHeight); int denWidth, denHeight; p_dc.GetTextExtent(den, &denWidth, &denHeight); int width = ((numWidth > denWidth) ? numWidth : denWidth); return wxSize(width + 4, numHeight + denHeight); } wxSize gbtRationalRendererRefData::DoGetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxString& text) { if (text.Find('/') != -1) { return GetFractionExtent(dc, text); } wxArrayString lines; long w=0, h=0; if (grid.StringToLines(text, lines) > 0) { dc.SetFont(attr.GetFont()); grid.GetTextBoxSize(dc, lines, &w, &h); } return wxSize(w, h); } wxSize gbtRationalRendererRefData::GetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords) { return DoGetBestSize(grid, attr, dc, grid.GetCellValue(coords)); } void gbtRationalRendererRefData::Draw(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected) { wxRect rect = rectCell; rect.Inflate(-1); // erase only this cells background, overflow cells should have been erased wxSheetCellRendererRefData::Draw(grid, attr, dc, rectCell, coords, isSelected); DoDraw(grid, attr, dc, rectCell, coords, isSelected); } static void DrawFraction(wxDC &p_dc, wxRect p_rect, const wxString &p_value) { p_dc.SetFont(wxFont(7, wxSWISS, wxNORMAL, wxBOLD)); wxString num; int i = 0; while (p_value[i] != '/') num += p_value[i++]; i++; wxString den; while (p_value[i] != '\0') den += p_value[i++]; int numWidth, numHeight; p_dc.GetTextExtent(num, &numWidth, &numHeight); int denWidth, denHeight; p_dc.GetTextExtent(den, &denWidth, &denHeight); int width = ((numWidth > denWidth) ? numWidth : denWidth); wxPoint point(p_rect.x, p_rect.y + p_rect.height/2); p_dc.SetPen(wxPen(p_dc.GetTextForeground(), 1, wxSOLID)); p_dc.DrawText(num, point.x + (p_rect.width-numWidth)/2, point.y - numHeight); p_dc.DrawText(den, point.x + (p_rect.width-denWidth)/2, point.y); p_dc.DrawLine(point.x + (p_rect.width-width)/2 - 2, point.y, point.x + (p_rect.width-width)/2 + width + 2, point.y); } void gbtRationalRendererRefData::DoDraw(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected) { wxRect rect = rectCell; rect.Inflate(-1); int align = attr.GetAlignment(); wxString value = grid.GetCellValue(coords); //int best_width = DoGetBestSize(grid, attr, dc, value).GetWidth(); wxSheetCoords cellSpan(grid.GetCellSpan(coords)); // shouldn't get here if <=0 //int cell_rows = cellSpan.m_row; //int cell_cols = cellSpan.m_col; //bool is_grid_cell = wxSheet::IsGridCell(coords); // no overflow for row/col/corner labels //int num_cols = grid.GetNumberCols(); // Draw the text if (value.Find('/') != -1) { SetTextColoursAndFont(grid, attr, dc, isSelected); DrawFraction(dc, rect, value); } else { SetTextColoursAndFont(grid, attr, dc, isSelected); grid.DrawTextRectangle(dc, value, rect, align); } } //---------------------------------------------------------------------------- // class gbtRationalEditorRefData //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(gbtRationalEditorRefData, wxSheetCellTextEditorRefData) #include "valnumber.h" void gbtRationalEditorRefData::CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet) { wxSheetCellTextEditorRefData::CreateEditor(parent, id, evtHandler, sheet); GetTextCtrl()->SetValidator(gbtNumberValidator(0)); } bool gbtRationalEditorRefData::Copy(const gbtRationalEditorRefData &p_other) { return wxSheetCellTextEditorRefData::Copy(p_other); } void gbtRationalEditorRefData::StartingKey(wxKeyEvent &event) { int keycode = event.GetKeyCode(); char tmpbuf[2]; tmpbuf[0] = (char) keycode; tmpbuf[1] = '\0'; wxString strbuf(tmpbuf, *wxConvCurrent); #if wxUSE_INTL bool is_decimal_point = (strbuf == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER)); #else bool is_decimal_point = ( strbuf == _T(".") ); #endif if (wxIsdigit(keycode) || keycode == '-' || is_decimal_point) { wxSheetCellTextEditorRefData::StartingKey(event); return; } event.Skip(); } bool gbtRationalEditorRefData::IsAcceptedKey(wxKeyEvent &p_event) { if (wxSheetCellEditorRefData::IsAcceptedKey(p_event)) { int keycode = p_event.GetKeyCode(); char tmpbuf[2]; tmpbuf[0] = (char) keycode; tmpbuf[1] = '\0'; wxString strbuf(tmpbuf, *wxConvCurrent); #if wxUSE_INTL bool is_decimal_point = (strbuf == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER)); #else bool is_decimal_point = ( strbuf == _T(".") ); #endif if ((keycode < 128) && (wxIsdigit(keycode) || is_decimal_point || keycode == '-') ) return true; } return false; } gambit-0.2010.09.01/src/gui/renratio.h0000644000076500007650000000525611435216101014011 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/renratio.h // Declaration of wxSheet renderer for rational numbers // // 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 RENRATIO_H #define RENRATIO_H #include "wx/sheet/sheet.h" // the wxSheet widget // // This class is based on the wxSheetCellStringRendererRefData implementation // class gbtRationalRendererRefData : public wxSheetCellRendererRefData { public: gbtRationalRendererRefData(void) { } // draw the string virtual void Draw(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // return the string extent virtual wxSize GetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords); void DoDraw(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // set the text colours before drawing void SetTextColoursAndFont(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, bool isSelected); // calc the string extent for given string/font wxSize DoGetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxString& text); bool Copy(const gbtRationalRendererRefData& other) { return wxSheetCellRendererRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(gbtRationalRendererRefData, wxSheetCellRendererRefData) }; class gbtRationalEditorRefData : public wxSheetCellTextEditorRefData { public: gbtRationalEditorRefData(void) { } void CreateEditor(wxWindow *, wxWindowID, wxEvtHandler *, wxSheet *); /// Override basic text editor behavior to restrict input bool IsAcceptedKey(wxKeyEvent &); void StartingKey(wxKeyEvent &); bool Copy(const gbtRationalEditorRefData &other); DECLARE_SHEETOBJREFDATA_COPY_CLASS(gbtRationalEditorRefData, wxSheetCellTextEditorRefData) }; #endif // RENRATIO_H gambit-0.2010.09.01/src/gui/style.cc0000644000076500007650000003055411435216101013463 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/style.cc // Display configuration class for the extensive form // // 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 // aint with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // #include #include #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include #include "style.h" //=========================================================================== // class gbtStyle: Implementation //=========================================================================== gbtStyle::gbtStyle(void) : m_font(wxFont(10, wxSWISS, wxNORMAL, wxBOLD)) { SetDefaults(); } static wxColour s_defaultColors[8] = { wxColour(255, 0, 0), wxColour(0, 0, 255), wxColour(0, 128, 0), wxColour(255, 128, 0), wxColour(0, 0, 64), wxColour(128, 0, 255), wxColour(64, 0, 0), wxColour(255, 128, 255) }; //! //! Gets the player color assigned to player number 'pl'. //! If this is the first request for that player's color, create the //! default one. //! const wxColour &gbtStyle::GetPlayerColor(int pl) const { while (pl > m_playerColors.Length()) { m_playerColors.Append(s_defaultColors[m_playerColors.Length() % 8]); } return m_playerColors[pl]; } void gbtStyle::SetDefaults(void) { m_nodeSize = 10; m_terminalSpacing = 50; m_chanceToken = GBT_NODE_TOKEN_DOT; m_playerToken = GBT_NODE_TOKEN_DOT; m_terminalToken = GBT_NODE_TOKEN_DOT; m_rootReachable = 0; m_branchLength = 60; m_tineLength = 20; m_branchStyle = GBT_BRANCH_STYLE_FORKTINE; m_branchLabels = GBT_BRANCH_LABEL_HORIZONTAL; m_infosetConnect = GBT_INFOSET_CONNECT_ALL; m_infosetJoin = GBT_INFOSET_JOIN_CIRCLES; m_nodeAboveLabel = GBT_NODE_LABEL_LABEL; m_nodeBelowLabel = GBT_NODE_LABEL_ISETID; m_branchAboveLabel = GBT_BRANCH_LABEL_LABEL; m_branchBelowLabel = GBT_BRANCH_LABEL_PROBS; m_numDecimals = 4; m_font = wxFont(10, wxSWISS, wxNORMAL, wxBOLD); m_chanceColor = wxColour(154, 205, 50); m_terminalColor = *wxBLACK; for (int pl = 1; pl <= m_playerColors.Length(); pl++) { m_playerColors[pl] = s_defaultColors[(pl-1)%8]; } } std::string gbtStyle::GetColorXML(void) const { std::ostringstream s; s <<"\n"; s <<"\n"; s <<"\n"; for (int pl = 1; pl <= m_playerColors.Length(); pl++) { s <<"\n"; } s <<"\n"; return s.str(); } void gbtStyle::SetColorXML(TiXmlNode *p_colors) { for (TiXmlNode *node = p_colors->FirstChild(); node; node = node->NextSiblingElement()) { int id = -2; node->ToElement()->QueryIntAttribute("id", &id); int red = 0, green = 0, blue = 0; node->ToElement()->QueryIntAttribute("red", &red); node->ToElement()->QueryIntAttribute("green", &green); node->ToElement()->QueryIntAttribute("blue", &blue); if (id > 0) { // This call ensures that the player appears in the color table GetPlayerColor(id); SetPlayerColor(id, wxColour(red, green, blue)); } else if (id == 0) { SetChanceColor(wxColour(red, green, blue)); } else if (id == -1) { SetTerminalColor(wxColour(red, green, blue)); } } } std::string gbtStyle::GetFontXML(void) const { std::ostringstream s; s << "\n"; return s.str(); } void gbtStyle::SetFontXML(TiXmlNode *p_font) { int size, family, style, weight; p_font->ToElement()->QueryIntAttribute("size", &size); p_font->ToElement()->QueryIntAttribute("family", &family); p_font->ToElement()->QueryIntAttribute("style", &style); p_font->ToElement()->QueryIntAttribute("weight", &weight); SetFont(wxFont(size, family, style, weight, false, wxString(p_font->ToElement()->Attribute("face"), *wxConvCurrent))); } std::string gbtStyle::GetLayoutXML(void) const { std::ostringstream s; s << "\n"; s << "\n"; s << "\n"; std::string infosetConnect[] = { "none", "same", "all" }; s << "\n"; s << "\n"; return s.str(); } void gbtStyle::SetLayoutXML(TiXmlNode *p_node) { TiXmlNode *nodes = p_node->FirstChild("nodes"); if (nodes) { nodes->ToElement()->QueryIntAttribute("size", &m_nodeSize); nodes->ToElement()->QueryIntAttribute("spacing", &m_terminalSpacing); const char *chance = nodes->ToElement()->Attribute("chance"); if (chance) { std::string s = chance; if (s == "line") m_chanceToken = GBT_NODE_TOKEN_LINE; else if (s == "box") m_chanceToken = GBT_NODE_TOKEN_BOX; else if (s == "circle") m_chanceToken = GBT_NODE_TOKEN_CIRCLE; else if (s == "diamond") m_chanceToken = GBT_NODE_TOKEN_DIAMOND; else if (s == "dot") m_chanceToken = GBT_NODE_TOKEN_DOT; } const char *player = nodes->ToElement()->Attribute("player"); if (player) { std::string s = player; if (s == "line") m_playerToken = GBT_NODE_TOKEN_LINE; else if (s == "box") m_playerToken = GBT_NODE_TOKEN_BOX; else if (s == "circle") m_playerToken = GBT_NODE_TOKEN_CIRCLE; else if (s == "diamond") m_playerToken = GBT_NODE_TOKEN_DIAMOND; else if (s == "dot") m_playerToken = GBT_NODE_TOKEN_DOT; } const char *terminal = nodes->ToElement()->Attribute("terminal"); if (terminal) { std::string s = terminal; if (s == "line") m_terminalToken = GBT_NODE_TOKEN_LINE; else if (s == "box") m_terminalToken = GBT_NODE_TOKEN_BOX; else if (s == "circle") m_terminalToken = GBT_NODE_TOKEN_CIRCLE; else if (s == "diamond") m_terminalToken = GBT_NODE_TOKEN_DIAMOND; else if (s == "dot") m_terminalToken = GBT_NODE_TOKEN_DOT; } } TiXmlNode *branches = p_node->FirstChild("branches"); if (branches) { branches->ToElement()->QueryIntAttribute("size", &m_branchLength); branches->ToElement()->QueryIntAttribute("tine", &m_tineLength); const char *branch = branches->ToElement()->Attribute("branch"); if (branch) { std::string s = branch; if (s == "line") m_branchStyle = GBT_BRANCH_STYLE_LINE; else if (s == "forktine") m_branchStyle = GBT_BRANCH_STYLE_FORKTINE; } const char *labels = branches->ToElement()->Attribute("labels"); if (labels) { std::string s = labels; if (s == "horizontal") m_branchLabels = GBT_BRANCH_LABEL_HORIZONTAL; else if (s == "rotated") m_branchLabels = GBT_BRANCH_LABEL_ROTATED; } } TiXmlNode *infosets = p_node->FirstChild("infosets"); if (infosets) { const char *connect = infosets->ToElement()->Attribute("connect"); if (connect) { std::string s = connect; if (s == "none") m_infosetConnect = GBT_INFOSET_CONNECT_NONE; else if (s == "same") m_infosetConnect = GBT_INFOSET_CONNECT_SAMELEVEL; else if (s == "all") m_infosetConnect = GBT_INFOSET_CONNECT_ALL; } const char *style = infosets->ToElement()->Attribute("style"); if (style) { std::string s = style; if (s == "lines") m_infosetJoin = GBT_INFOSET_JOIN_LINES; else if (s == "circles") m_infosetJoin = GBT_INFOSET_JOIN_CIRCLES; } } } std::string gbtStyle::GetLabelXML(void) const { std::ostringstream s; s << "\n"; return s.str(); } void gbtStyle::SetLabelXML(TiXmlNode *p_node) { const char *abovenode = p_node->ToElement()->Attribute("abovenode"); if (abovenode) { std::string s = abovenode; if (s == "none") m_nodeAboveLabel = GBT_NODE_LABEL_NOTHING; else if (s == "label") m_nodeAboveLabel = GBT_NODE_LABEL_LABEL; else if (s == "player") m_nodeAboveLabel = GBT_NODE_LABEL_PLAYER; else if (s == "isetlabel") m_nodeAboveLabel = GBT_NODE_LABEL_ISETLABEL; else if (s == "isetid") m_nodeAboveLabel = GBT_NODE_LABEL_ISETID; else if (s == "realizprob") m_nodeAboveLabel = GBT_NODE_LABEL_REALIZPROB; else if (s == "beliefprob") m_nodeAboveLabel = GBT_NODE_LABEL_BELIEFPROB; else if (s == "value") m_nodeAboveLabel = GBT_NODE_LABEL_VALUE; } const char *belownode = p_node->ToElement()->Attribute("belownode"); if (belownode) { std::string s = belownode; if (s == "none") m_nodeBelowLabel = GBT_NODE_LABEL_NOTHING; else if (s == "label") m_nodeBelowLabel = GBT_NODE_LABEL_LABEL; else if (s == "player") m_nodeBelowLabel = GBT_NODE_LABEL_PLAYER; else if (s == "isetlabel") m_nodeBelowLabel = GBT_NODE_LABEL_ISETLABEL; else if (s == "isetid") m_nodeBelowLabel = GBT_NODE_LABEL_ISETID; else if (s == "realizprob") m_nodeBelowLabel = GBT_NODE_LABEL_REALIZPROB; else if (s == "beliefprob") m_nodeBelowLabel = GBT_NODE_LABEL_BELIEFPROB; else if (s == "value") m_nodeBelowLabel = GBT_NODE_LABEL_VALUE; } const char *abovebranch = p_node->ToElement()->Attribute("abovebranch"); if (abovebranch) { std::string s = abovebranch; if (s == "none") m_branchAboveLabel = GBT_BRANCH_LABEL_NOTHING; else if (s == "label") m_branchAboveLabel = GBT_BRANCH_LABEL_LABEL; else if (s == "probs") m_branchAboveLabel = GBT_BRANCH_LABEL_PROBS; else if (s == "value") m_branchAboveLabel = GBT_BRANCH_LABEL_VALUE; } const char *belowbranch = p_node->ToElement()->Attribute("belowbranch"); if (belowbranch) { std::string s = belowbranch; if (s == "none") m_branchBelowLabel = GBT_BRANCH_LABEL_NOTHING; else if (s == "label") m_branchBelowLabel = GBT_BRANCH_LABEL_LABEL; else if (s == "probs") m_branchBelowLabel = GBT_BRANCH_LABEL_PROBS; else if (s == "value") m_branchBelowLabel = GBT_BRANCH_LABEL_VALUE; } } gambit-0.2010.09.01/src/gui/style.h0000644000076500007650000001443211435216101013322 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/style.h // Class to store settings related to graphical interface styling // // 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 STYLE_H #define STYLE_H #include "libgambit/libgambit.h" #include "tinyxml.h" const int GBT_NODE_TOKEN_LINE = 0; const int GBT_NODE_TOKEN_BOX = 1; const int GBT_NODE_TOKEN_CIRCLE = 2; const int GBT_NODE_TOKEN_DIAMOND = 3; const int GBT_NODE_TOKEN_DOT = 4; const int GBT_BRANCH_STYLE_LINE = 0; const int GBT_BRANCH_STYLE_FORKTINE = 1; const int GBT_BRANCH_LABEL_HORIZONTAL = 0; const int GBT_BRANCH_LABEL_ROTATED = 1; const int GBT_INFOSET_JOIN_LINES = 0; const int GBT_INFOSET_JOIN_CIRCLES = 1; const int GBT_INFOSET_CONNECT_NONE = 0; const int GBT_INFOSET_CONNECT_SAMELEVEL = 1; const int GBT_INFOSET_CONNECT_ALL = 2; const int GBT_NODE_LABEL_NOTHING = 0; const int GBT_NODE_LABEL_LABEL = 1; const int GBT_NODE_LABEL_PLAYER = 2; const int GBT_NODE_LABEL_ISETLABEL = 3; const int GBT_NODE_LABEL_ISETID = 4; const int GBT_NODE_LABEL_REALIZPROB = 5; const int GBT_NODE_LABEL_BELIEFPROB = 6; const int GBT_NODE_LABEL_VALUE = 7; const int GBT_BRANCH_LABEL_NOTHING = 0; const int GBT_BRANCH_LABEL_LABEL = 1; const int GBT_BRANCH_LABEL_PROBS = 2; const int GBT_BRANCH_LABEL_VALUE = 3; class wxConfig; class wxFont; class gbtStyle { private: // Node styling int m_nodeSize, m_terminalSpacing; int m_chanceToken, m_playerToken, m_terminalToken; bool m_rootReachable; // Branch styling int m_branchLength, m_tineLength; int m_branchStyle, m_branchLabels; // Information set styling int m_infosetConnect, m_infosetJoin; // Legend styling int m_nodeAboveLabel, m_nodeBelowLabel; int m_branchAboveLabel, m_branchBelowLabel; // Fonts for legends wxFont m_font; // Colors for nodes wxColour m_chanceColor, m_terminalColor; mutable Gambit::Array m_playerColors; // Decimal places to display int m_numDecimals; public: // Lifecycle gbtStyle(void); // Node styling int NodeSize(void) const { return m_nodeSize; } void SetNodeSize(int p_nodeSize) { m_nodeSize = p_nodeSize; } int TerminalSpacing(void) const { return m_terminalSpacing; } void SetTerminalSpacing(int p_spacing) { m_terminalSpacing = p_spacing; } int ChanceToken(void) const { return m_chanceToken; } void SetChanceToken(int p_token) { m_chanceToken = p_token; } int PlayerToken(void) const { return m_playerToken; } void SetPlayerToken(int p_token) { m_playerToken = p_token; } int TerminalToken(void) const { return m_terminalToken; } void SetTerminalToken(int p_token) { m_terminalToken = p_token; } bool RootReachable(void) const { return m_rootReachable; } void SetRootReachable(bool p_reachable) { m_rootReachable = p_reachable; } // Branch styling int BranchLength(void) const { return m_branchLength; } void SetBranchLength(int p_length) { m_branchLength = p_length; } int TineLength(void) const { return m_tineLength; } void SetTineLength(int p_length) { m_tineLength = p_length; } int BranchStyle(void) const { return m_branchStyle; } void SetBranchStyle(int p_style) { m_branchStyle = p_style; } int BranchLabels(void) const { return m_branchLabels; } void SetBranchLabels(int p_labels) { m_branchLabels = p_labels; } // Information set styling int InfosetConnect(void) const { return m_infosetConnect; } void SetInfosetConnect(int p_connect) { m_infosetConnect = p_connect; } int InfosetJoin(void) const { return m_infosetJoin; } void SetInfosetJoin(int p_join) { m_infosetJoin = p_join; } // Legends int NodeAboveLabel(void) const { return m_nodeAboveLabel; } void SetNodeAboveLabel(int p_label) { m_nodeAboveLabel = p_label; } int NodeBelowLabel(void) const { return m_nodeBelowLabel; } void SetNodeBelowLabel(int p_label) { m_nodeBelowLabel = p_label; } int BranchAboveLabel(void) const { return m_branchAboveLabel; } void SetBranchAboveLabel(int p_label) { m_branchAboveLabel = p_label; } int BranchBelowLabel(void) const { return m_branchBelowLabel; } void SetBranchBelowLabel(int p_label) { m_branchBelowLabel = p_label; } // Fonts const wxFont &GetFont(void) const { return m_font; } void SetFont(const wxFont &p_font) { m_font = p_font; } // Colors const wxColour &ChanceColor(void) const { return m_chanceColor; } void SetChanceColor(const wxColour &p_color) { m_chanceColor = p_color; } const wxColour &TerminalColor(void) const { return m_terminalColor; } void SetTerminalColor(const wxColour &p_color) { m_terminalColor = p_color; } const wxColour &GetPlayerColor(int pl) const; void SetPlayerColor(int pl, const wxColour &p_color) { m_playerColors[pl] = p_color; } // Decimals int NumDecimals(void) const { return m_numDecimals; } void SetNumDecimals(int p_decimals) { m_numDecimals = p_decimals; } // Reset to the "factory" defaults void SetDefaults(void); /// @name Reading and writing XML //@{ /// Get the color settings as an XML entry std::string GetColorXML(void) const; /// Set the color settings from an XML entry void SetColorXML(TiXmlNode *p_node); /// Get the font settings as an XML entry std::string GetFontXML(void) const; /// Set the font settings from an XML entry void SetFontXML(TiXmlNode *p_node); /// Get the layout settings as an XML entry std::string GetLayoutXML(void) const; /// Set the layout settings from an XML entry void SetLayoutXML(TiXmlNode *p_node); /// Get the label settings as an XML entry std::string GetLabelXML(void) const; /// Set the label settings from an XML entry void SetLabelXML(TiXmlNode *p_node); //@} }; #endif // STYLE_H gambit-0.2010.09.01/src/gui/tinyxml.cc0000644000076500007650000010175411350032206014026 00000000000000/* www.sourceforge.net/projects/tinyxml Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #include #include "tinyxml.h" #ifdef TIXML_USE_STL #include #endif bool TiXmlBase::condenseWhiteSpace = true; void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream ) { TIXML_STRING buffer; PutString( str, &buffer ); (*stream) << buffer; } void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString ) { int i=0; while( i<(int)str.length() ) { unsigned char c = (unsigned char) str[i]; if ( c == '&' && i < ( (int)str.length() - 2 ) && str[i+1] == '#' && str[i+2] == 'x' ) { // Hexadecimal character reference. // Pass through unchanged. // © -- copyright symbol, for example. // // The -1 is a bug fix from Rob Laveaux. It keeps // an overflow from happening if there is no ';'. // There are actually 2 ways to exit this loop - // while fails (error case) and break (semicolon found). // However, there is no mechanism (currently) for // this function to return an error. while ( i<(int)str.length()-1 ) { outString->append( str.c_str() + i, 1 ); ++i; if ( str[i] == ';' ) break; } } else if ( c == '&' ) { outString->append( entity[0].str, entity[0].strLength ); ++i; } else if ( c == '<' ) { outString->append( entity[1].str, entity[1].strLength ); ++i; } else if ( c == '>' ) { outString->append( entity[2].str, entity[2].strLength ); ++i; } else if ( c == '\"' ) { outString->append( entity[3].str, entity[3].strLength ); ++i; } else if ( c == '\'' ) { outString->append( entity[4].str, entity[4].strLength ); ++i; } else if ( c < 32 ) { // Easy pass at non-alpha/numeric/symbol // Below 32 is symbolic. char buf[ 32 ]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); #else sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); #endif //*ME: warning C4267: convert 'size_t' to 'int' //*ME: Int-Cast to make compiler happy ... outString->append( buf, (int)strlen( buf ) ); ++i; } else { //char realc = (char) c; //outString->append( &realc, 1 ); *outString += (char) c; // somewhat more efficient function call. ++i; } } } // <-- Strange class for a bug fix. Search for STL_STRING_BUG TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str ) { buffer = new char[ str.length()+1 ]; if ( buffer ) { strcpy( buffer, str.c_str() ); } } TiXmlBase::StringToBuffer::~StringToBuffer() { delete [] buffer; } // End strange bug fix. --> TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() { parent = 0; type = _type; firstChild = 0; lastChild = 0; prev = 0; next = 0; } TiXmlNode::~TiXmlNode() { TiXmlNode* node = firstChild; TiXmlNode* temp = 0; while ( node ) { temp = node; node = node->next; delete temp; } } void TiXmlNode::CopyTo( TiXmlNode* target ) const { target->SetValue (value.c_str() ); target->userData = userData; } void TiXmlNode::Clear() { TiXmlNode* node = firstChild; TiXmlNode* temp = 0; while ( node ) { temp = node; node = node->next; delete temp; } firstChild = 0; lastChild = 0; } TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) { node->parent = this; node->prev = lastChild; node->next = 0; if ( lastChild ) lastChild->next = node; else firstChild = node; // it was an empty list. lastChild = node; return node; } TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) { TiXmlNode* node = addThis.Clone(); if ( !node ) return 0; return LinkEndChild( node ); } TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) { if ( !beforeThis || beforeThis->parent != this ) return 0; TiXmlNode* node = addThis.Clone(); if ( !node ) return 0; node->parent = this; node->next = beforeThis; node->prev = beforeThis->prev; if ( beforeThis->prev ) { beforeThis->prev->next = node; } else { assert( firstChild == beforeThis ); firstChild = node; } beforeThis->prev = node; return node; } TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) { if ( !afterThis || afterThis->parent != this ) return 0; TiXmlNode* node = addThis.Clone(); if ( !node ) return 0; node->parent = this; node->prev = afterThis; node->next = afterThis->next; if ( afterThis->next ) { afterThis->next->prev = node; } else { assert( lastChild == afterThis ); lastChild = node; } afterThis->next = node; return node; } TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) { if ( replaceThis->parent != this ) return 0; TiXmlNode* node = withThis.Clone(); if ( !node ) return 0; node->next = replaceThis->next; node->prev = replaceThis->prev; if ( replaceThis->next ) replaceThis->next->prev = node; else lastChild = node; if ( replaceThis->prev ) replaceThis->prev->next = node; else firstChild = node; delete replaceThis; node->parent = this; return node; } bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) { if ( removeThis->parent != this ) { assert( 0 ); return false; } if ( removeThis->next ) removeThis->next->prev = removeThis->prev; else lastChild = removeThis->prev; if ( removeThis->prev ) removeThis->prev->next = removeThis->next; else firstChild = removeThis->next; delete removeThis; return true; } const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const { const TiXmlNode* node; for ( node = firstChild; node; node = node->next ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } TiXmlNode* TiXmlNode::FirstChild( const char * _value ) { TiXmlNode* node; for ( node = firstChild; node; node = node->next ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const { const TiXmlNode* node; for ( node = lastChild; node; node = node->prev ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } TiXmlNode* TiXmlNode::LastChild( const char * _value ) { TiXmlNode* node; for ( node = lastChild; node; node = node->prev ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const { if ( !previous ) { return FirstChild(); } else { assert( previous->parent == this ); return previous->NextSibling(); } } TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) { if ( !previous ) { return FirstChild(); } else { assert( previous->parent == this ); return previous->NextSibling(); } } const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const { if ( !previous ) { return FirstChild( val ); } else { assert( previous->parent == this ); return previous->NextSibling( val ); } } TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) { if ( !previous ) { return FirstChild( val ); } else { assert( previous->parent == this ); return previous->NextSibling( val ); } } const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const { const TiXmlNode* node; for ( node = next; node; node = node->next ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } TiXmlNode* TiXmlNode::NextSibling( const char * _value ) { TiXmlNode* node; for ( node = next; node; node = node->next ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const { const TiXmlNode* node; for ( node = prev; node; node = node->prev ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) { TiXmlNode* node; for ( node = prev; node; node = node->prev ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } void TiXmlElement::RemoveAttribute( const char * name ) { TiXmlAttribute* node = attributeSet.Find( name ); if ( node ) { attributeSet.Remove( node ); delete node; } } const TiXmlElement* TiXmlNode::FirstChildElement() const { const TiXmlNode* node; for ( node = FirstChild(); node; node = node->NextSibling() ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } TiXmlElement* TiXmlNode::FirstChildElement() { TiXmlNode* node; for ( node = FirstChild(); node; node = node->NextSibling() ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const { const TiXmlNode* node; for ( node = FirstChild( _value ); node; node = node->NextSibling( _value ) ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) { TiXmlNode* node; for ( node = FirstChild( _value ); node; node = node->NextSibling( _value ) ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } const TiXmlElement* TiXmlNode::NextSiblingElement() const { const TiXmlNode* node; for ( node = NextSibling(); node; node = node->NextSibling() ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } TiXmlElement* TiXmlNode::NextSiblingElement() { TiXmlNode* node; for ( node = NextSibling(); node; node = node->NextSibling() ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const { const TiXmlNode* node; for ( node = NextSibling( _value ); node; node = node->NextSibling( _value ) ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) { TiXmlNode* node; for ( node = NextSibling( _value ); node; node = node->NextSibling( _value ) ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } const TiXmlDocument* TiXmlNode::GetDocument() const { const TiXmlNode* node; for( node = this; node; node = node->parent ) { if ( node->ToDocument() ) return node->ToDocument(); } return 0; } TiXmlDocument* TiXmlNode::GetDocument() { TiXmlNode* node; for( node = this; node; node = node->parent ) { if ( node->ToDocument() ) return node->ToDocument(); } return 0; } TiXmlElement::TiXmlElement (const char * _value) : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; value = _value; } #ifdef TIXML_USE_STL TiXmlElement::TiXmlElement( const std::string& _value ) : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; value = _value; } #endif TiXmlElement::TiXmlElement( const TiXmlElement& copy) : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; copy.CopyTo( this ); } void TiXmlElement::operator=( const TiXmlElement& base ) { ClearThis(); base.CopyTo( this ); } TiXmlElement::~TiXmlElement() { ClearThis(); } void TiXmlElement::ClearThis() { Clear(); while( attributeSet.First() ) { TiXmlAttribute* node = attributeSet.First(); attributeSet.Remove( node ); delete node; } } const char * TiXmlElement::Attribute( const char * name ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( node ) return node->Value(); return 0; } const char * TiXmlElement::Attribute( const char * name, int* i ) const { const char * s = Attribute( name ); if ( i ) { if ( s ) *i = atoi( s ); else *i = 0; } return s; } const char * TiXmlElement::Attribute( const char * name, double* d ) const { const char * s = Attribute( name ); if ( d ) { if ( s ) *d = atof( s ); else *d = 0; } return s; } int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) return TIXML_NO_ATTRIBUTE; return node->QueryIntValue( ival ); } int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) return TIXML_NO_ATTRIBUTE; return node->QueryDoubleValue( dval ); } void TiXmlElement::SetAttribute( const char * name, int val ) { char buf[64]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); #else sprintf( buf, "%d", val ); #endif SetAttribute( name, buf ); } void TiXmlElement::SetDoubleAttribute( const char * name, double val ) { char buf[256]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); #else sprintf( buf, "%f", val ); #endif SetAttribute( name, buf ); } void TiXmlElement::SetAttribute( const char * name, const char * _value ) { TiXmlAttribute* node = attributeSet.Find( name ); if ( node ) { node->SetValue( _value ); return; } TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); if ( attrib ) { attributeSet.Add( attrib ); } else { TiXmlDocument* document = GetDocument(); if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); } } void TiXmlElement::Print( FILE* cfile, int depth ) const { int i; for ( i=0; iNext() ) { fprintf( cfile, " " ); attrib->Print( cfile, depth ); } // There are 3 different formatting approaches: // 1) An element without children is printed as a node // 2) An element with only a text child is printed as text // 3) An element with children is printed on multiple lines. TiXmlNode* node; if ( !firstChild ) { fprintf( cfile, " />" ); } else if ( firstChild == lastChild && firstChild->ToText() ) { fprintf( cfile, ">" ); firstChild->Print( cfile, depth + 1 ); fprintf( cfile, "", value.c_str() ); } else { fprintf( cfile, ">" ); for ( node = firstChild; node; node=node->NextSibling() ) { if ( !node->ToText() ) { fprintf( cfile, "\n" ); } node->Print( cfile, depth+1 ); } fprintf( cfile, "\n" ); for( i=0; i", value.c_str() ); } } void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const { (*stream) << "<" << value; const TiXmlAttribute* attrib; for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) { (*stream) << " "; attrib->StreamOut( stream ); } // If this node has children, give it a closing tag. Else // make it an empty tag. TiXmlNode* node; if ( firstChild ) { (*stream) << ">"; for ( node = firstChild; node; node=node->NextSibling() ) { node->StreamOut( stream ); } (*stream) << ""; } else { (*stream) << " />"; } } void TiXmlElement::CopyTo( TiXmlElement* target ) const { // superclass: TiXmlNode::CopyTo( target ); // Element class: // Clone the attributes, then clone the children. const TiXmlAttribute* attribute = 0; for( attribute = attributeSet.First(); attribute; attribute = attribute->Next() ) { target->SetAttribute( attribute->Name(), attribute->Value() ); } TiXmlNode* node = 0; for ( node = firstChild; node; node = node->NextSibling() ) { target->LinkEndChild( node->Clone() ); } } TiXmlNode* TiXmlElement::Clone() const { TiXmlElement* clone = new TiXmlElement( Value() ); if ( !clone ) return 0; CopyTo( clone ); return clone; } const char* TiXmlElement::GetText() const { const TiXmlNode* child = this->FirstChild(); if ( child ) { const TiXmlText* childText = child->ToText(); if ( childText ) { return childText->Value(); } } return 0; } TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; ClearError(); } TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; value = documentName; ClearError(); } #ifdef TIXML_USE_STL TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; value = documentName; ClearError(); } #endif TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) { copy.CopyTo( this ); } void TiXmlDocument::operator=( const TiXmlDocument& copy ) { Clear(); copy.CopyTo( this ); } bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) { // See STL_STRING_BUG below. StringToBuffer buf( value ); if ( buf.buffer && LoadFile( buf.buffer, encoding ) ) return true; return false; } bool TiXmlDocument::SaveFile() const { // See STL_STRING_BUG below. StringToBuffer buf( value ); if ( buf.buffer && SaveFile( buf.buffer ) ) return true; return false; } bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding ) { // Delete the existing data: Clear(); location.Clear(); // There was a really terrifying little bug here. The code: // value = filename // in the STL case, cause the assignment method of the std::string to // be called. What is strange, is that the std::string had the same // address as it's c_str() method, and so bad things happen. Looks // like a bug in the Microsoft STL implementation. // See STL_STRING_BUG above. // Fixed with the StringToBuffer class. value = filename; // reading in binary mode so that tinyxml can normalize the EOL FILE* file = fopen( value.c_str (), "rb" ); if ( file ) { // Get the file size, so we can pre-allocate the string. HUGE speed impact. long length = 0; fseek( file, 0, SEEK_END ); length = ftell( file ); fseek( file, 0, SEEK_SET ); // Strange case, but good to handle up front. if ( length == 0 ) { fclose( file ); return false; } // If we have a file, assume it is all one big XML file, and read it in. // The document parser may decide the document ends sooner than the entire file, however. TIXML_STRING data; data.reserve( length ); // Subtle bug here. TinyXml did use fgets. But from the XML spec: // 2.11 End-of-Line Handling // // // ...the XML processor MUST behave as if it normalized all line breaks in external // parsed entities (including the document entity) on input, before parsing, by translating // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to // a single #xA character. // // // It is not clear fgets does that, and certainly isn't clear it works cross platform. // Generally, you expect fgets to translate from the convention of the OS to the c/unix // convention, and not work generally. /* while( fgets( buf, sizeof(buf), file ) ) { data += buf; } */ char* buf = new char[ length+1 ]; buf[0] = 0; if ( fread( buf, length, 1, file ) != 1 ) { //if ( fread( buf, 1, length, file ) != (size_t)length ) { SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); fclose( file ); return false; } fclose( file ); const char* lastPos = buf; const char* p = buf; buf[length] = 0; while( *p ) { assert( p < (buf+length) ); if ( *p == 0xa ) { // Newline character. No special rules for this. Append all the characters // since the last string, and include the newline. data.append( lastPos, p-lastPos+1 ); // append, include the newline ++p; // move past the newline lastPos = p; // and point to the new buffer (may be 0) assert( p <= (buf+length) ); } else if ( *p == 0xd ) { // Carriage return. Append what we have so far, then // handle moving forward in the buffer. if ( (p-lastPos) > 0 ) { data.append( lastPos, p-lastPos ); // do not add the CR } data += (char)0xa; // a proper newline if ( *(p+1) == 0xa ) { // Carriage return - new line sequence p += 2; lastPos = p; assert( p <= (buf+length) ); } else { // it was followed by something else...that is presumably characters again. ++p; lastPos = p; assert( p <= (buf+length) ); } } else { ++p; } } // Handle any left over characters. if ( p-lastPos ) { data.append( lastPos, p-lastPos ); } delete [] buf; buf = 0; Parse( data.c_str(), 0, encoding ); if ( Error() ) return false; else return true; } SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); return false; } bool TiXmlDocument::SaveFile( const char * filename ) const { // The old c stuff lives on... FILE* fp = fopen( filename, "w" ); if ( fp ) { if ( useMicrosoftBOM ) { const unsigned char TIXML_UTF_LEAD_0 = 0xefU; const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; fputc( TIXML_UTF_LEAD_0, fp ); fputc( TIXML_UTF_LEAD_1, fp ); fputc( TIXML_UTF_LEAD_2, fp ); } Print( fp, 0 ); fclose( fp ); return true; } return false; } void TiXmlDocument::CopyTo( TiXmlDocument* target ) const { TiXmlNode::CopyTo( target ); target->error = error; target->errorDesc = errorDesc.c_str (); TiXmlNode* node = 0; for ( node = firstChild; node; node = node->NextSibling() ) { target->LinkEndChild( node->Clone() ); } } TiXmlNode* TiXmlDocument::Clone() const { TiXmlDocument* clone = new TiXmlDocument(); if ( !clone ) return 0; CopyTo( clone ); return clone; } void TiXmlDocument::Print( FILE* cfile, int depth ) const { const TiXmlNode* node; for ( node=FirstChild(); node; node=node->NextSibling() ) { node->Print( cfile, depth ); fprintf( cfile, "\n" ); } } void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const { const TiXmlNode* node; for ( node=FirstChild(); node; node=node->NextSibling() ) { node->StreamOut( out ); // Special rule for streams: stop after the root element. // The stream in code will only read one element, so don't // write more than one. if ( node->ToElement() ) break; } } const TiXmlAttribute* TiXmlAttribute::Next() const { // We are using knowledge of the sentinel. The sentinel // have a value or name. if ( next->value.empty() && next->name.empty() ) return 0; return next; } TiXmlAttribute* TiXmlAttribute::Next() { // We are using knowledge of the sentinel. The sentinel // have a value or name. if ( next->value.empty() && next->name.empty() ) return 0; return next; } const TiXmlAttribute* TiXmlAttribute::Previous() const { // We are using knowledge of the sentinel. The sentinel // have a value or name. if ( prev->value.empty() && prev->name.empty() ) return 0; return prev; } TiXmlAttribute* TiXmlAttribute::Previous() { // We are using knowledge of the sentinel. The sentinel // have a value or name. if ( prev->value.empty() && prev->name.empty() ) return 0; return prev; } void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const { TIXML_STRING n, v; PutString( name, &n ); PutString( value, &v ); if (value.find ('\"') == TIXML_STRING::npos) fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); else fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); } void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const { if (value.find( '\"' ) != TIXML_STRING::npos) { PutString( name, stream ); (*stream) << "=" << "'"; PutString( value, stream ); (*stream) << "'"; } else { PutString( name, stream ); (*stream) << "=" << "\""; PutString( value, stream ); (*stream) << "\""; } } int TiXmlAttribute::QueryIntValue( int* ival ) const { if ( sscanf( value.c_str(), "%d", ival ) == 1 ) return TIXML_SUCCESS; return TIXML_WRONG_TYPE; } int TiXmlAttribute::QueryDoubleValue( double* dval ) const { if ( sscanf( value.c_str(), "%lf", dval ) == 1 ) return TIXML_SUCCESS; return TIXML_WRONG_TYPE; } void TiXmlAttribute::SetIntValue( int _value ) { char buf [64]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); #else sprintf (buf, "%d", _value); #endif SetValue (buf); } void TiXmlAttribute::SetDoubleValue( double _value ) { char buf [256]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); #else sprintf (buf, "%lf", _value); #endif SetValue (buf); } int TiXmlAttribute::IntValue() const { return atoi (value.c_str ()); } double TiXmlAttribute::DoubleValue() const { return atof (value.c_str ()); } TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) { copy.CopyTo( this ); } void TiXmlComment::operator=( const TiXmlComment& base ) { Clear(); base.CopyTo( this ); } void TiXmlComment::Print( FILE* cfile, int depth ) const { for ( int i=0; i", value.c_str() ); } void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const { (*stream) << ""; } void TiXmlComment::CopyTo( TiXmlComment* target ) const { TiXmlNode::CopyTo( target ); } TiXmlNode* TiXmlComment::Clone() const { TiXmlComment* clone = new TiXmlComment(); if ( !clone ) return 0; CopyTo( clone ); return clone; } void TiXmlText::Print( FILE* cfile, int depth ) const { if ( cdata ) { int i; fprintf( cfile, "\n" ); for ( i=0; i\n" ); } else { TIXML_STRING buffer; PutString( value, &buffer ); fprintf( cfile, "%s", buffer.c_str() ); } } void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const { if ( cdata ) { (*stream) << ""; } else { PutString( value, stream ); } } void TiXmlText::CopyTo( TiXmlText* target ) const { TiXmlNode::CopyTo( target ); target->cdata = cdata; } TiXmlNode* TiXmlText::Clone() const { TiXmlText* clone = 0; clone = new TiXmlText( "" ); if ( !clone ) return 0; CopyTo( clone ); return clone; } TiXmlDeclaration::TiXmlDeclaration( const char * _version, const char * _encoding, const char * _standalone ) : TiXmlNode( TiXmlNode::DECLARATION ) { version = _version; encoding = _encoding; standalone = _standalone; } #ifdef TIXML_USE_STL TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, const std::string& _encoding, const std::string& _standalone ) : TiXmlNode( TiXmlNode::DECLARATION ) { version = _version; encoding = _encoding; standalone = _standalone; } #endif TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) : TiXmlNode( TiXmlNode::DECLARATION ) { copy.CopyTo( this ); } void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) { Clear(); copy.CopyTo( this ); } void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const { fprintf (cfile, ""); } void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const { (*stream) << ""; } void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const { TiXmlNode::CopyTo( target ); target->version = version; target->encoding = encoding; target->standalone = standalone; } TiXmlNode* TiXmlDeclaration::Clone() const { TiXmlDeclaration* clone = new TiXmlDeclaration(); if ( !clone ) return 0; CopyTo( clone ); return clone; } void TiXmlUnknown::Print( FILE* cfile, int depth ) const { for ( int i=0; i", value.c_str() ); } void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const { (*stream) << "<" << value << ">"; // Don't use entities here! It is unknown. } void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const { TiXmlNode::CopyTo( target ); } TiXmlNode* TiXmlUnknown::Clone() const { TiXmlUnknown* clone = new TiXmlUnknown(); if ( !clone ) return 0; CopyTo( clone ); return clone; } TiXmlAttributeSet::TiXmlAttributeSet() { sentinel.next = &sentinel; sentinel.prev = &sentinel; } TiXmlAttributeSet::~TiXmlAttributeSet() { assert( sentinel.next == &sentinel ); assert( sentinel.prev == &sentinel ); } void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) { assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. addMe->next = &sentinel; addMe->prev = sentinel.prev; sentinel.prev->next = addMe; sentinel.prev = addMe; } void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) { TiXmlAttribute* node; for( node = sentinel.next; node != &sentinel; node = node->next ) { if ( node == removeMe ) { node->prev->next = node->next; node->next->prev = node->prev; node->next = 0; node->prev = 0; return; } } assert( 0 ); // we tried to remove a non-linked attribute. } const TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) const { const TiXmlAttribute* node; for( node = sentinel.next; node != &sentinel; node = node->next ) { if ( node->name == name ) return node; } return 0; } TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) { TiXmlAttribute* node; for( node = sentinel.next; node != &sentinel; node = node->next ) { if ( node->name == name ) return node; } return 0; } #ifdef TIXML_USE_STL TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base) { TIXML_STRING tag; tag.reserve( 8 * 1000 ); base.StreamIn( &in, &tag ); base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); return in; } #endif TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base) { base.StreamOut (& out); return out; } #ifdef TIXML_USE_STL std::string & operator<< (std::string& out, const TiXmlNode& base ) { std::ostringstream os_stream( std::ostringstream::out ); base.StreamOut( &os_stream ); out.append( os_stream.str() ); return out; } #endif TiXmlHandle TiXmlHandle::FirstChild() const { if ( node ) { TiXmlNode* child = node->FirstChild(); if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const { if ( node ) { TiXmlNode* child = node->FirstChild( value ); if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::FirstChildElement() const { if ( node ) { TiXmlElement* child = node->FirstChildElement(); if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const { if ( node ) { TiXmlElement* child = node->FirstChildElement( value ); if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::Child( int count ) const { if ( node ) { int i; TiXmlNode* child = node->FirstChild(); for ( i=0; child && iNextSibling(), ++i ) { // nothing } if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const { if ( node ) { int i; TiXmlNode* child = node->FirstChild( value ); for ( i=0; child && iNextSibling( value ), ++i ) { // nothing } if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::ChildElement( int count ) const { if ( node ) { int i; TiXmlElement* child = node->FirstChildElement(); for ( i=0; child && iNextSiblingElement(), ++i ) { // nothing } if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const { if ( node ) { int i; TiXmlElement* child = node->FirstChildElement( value ); for ( i=0; child && iNextSiblingElement( value ), ++i ) { // nothing } if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } gambit-0.2010.09.01/src/gui/tinyxml.h0000644000076500007650000014730011350032206013665 00000000000000/* www.sourceforge.net/projects/tinyxml Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #ifndef TINYXML_INCLUDED #define TINYXML_INCLUDED #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4530 ) #pragma warning( disable : 4786 ) #endif #include #include #include #include #include // Help out windows: #if defined( _DEBUG ) && !defined( DEBUG ) #define DEBUG #endif #if defined( DEBUG ) && defined( _MSC_VER ) #include #define TIXML_LOG OutputDebugString #else #define TIXML_LOG printf #endif // Gambit change: we use STL, so we define this here. #define TIXML_USE_STL 1 #ifdef TIXML_USE_STL #include #include #define TIXML_STRING std::string #define TIXML_ISTREAM std::istream #define TIXML_OSTREAM std::ostream #else #include "tinystr.h" #define TIXML_STRING TiXmlString #define TIXML_OSTREAM TiXmlOutStream #endif // Deprecated library function hell. Compilers want to use the // new safe versions. This probably doesn't fully address the problem, // but it gets closer. There are too many compilers for me to fully // test. If you get compilation troubles, undefine TIXML_SAFE #define TIXML_SAFE // TinyXml isn't fully buffer overrun protected, safe code. This is work in progress. #ifdef TIXML_SAFE #if defined(_MSC_VER) && (_MSC_VER >= 1200 ) // Microsoft visual studio, version 6 and higher. //#pragma message( "Using _sn* functions." ) #define TIXML_SNPRINTF _snprintf #define TIXML_SNSCANF _snscanf #elif defined(__GNUC__) && (__GNUC__ >= 3 ) // GCC version 3 and higher.s //#warning( "Using sn* functions." ) #define TIXML_SNPRINTF snprintf #define TIXML_SNSCANF snscanf #endif #endif class TiXmlDocument; class TiXmlElement; class TiXmlComment; class TiXmlUnknown; class TiXmlAttribute; class TiXmlText; class TiXmlDeclaration; class TiXmlParsingData; const int TIXML_MAJOR_VERSION = 2; const int TIXML_MINOR_VERSION = 4; const int TIXML_PATCH_VERSION = 2; /* Internal structure for tracking location of items in the XML file. */ struct TiXmlCursor { TiXmlCursor() { Clear(); } void Clear() { row = col = -1; } int row; // 0 based. int col; // 0 based. }; // Only used by Attribute::Query functions enum { TIXML_SUCCESS, TIXML_NO_ATTRIBUTE, TIXML_WRONG_TYPE }; // Used by the parsing routines. enum TiXmlEncoding { TIXML_ENCODING_UNKNOWN, TIXML_ENCODING_UTF8, TIXML_ENCODING_LEGACY }; const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; /** TiXmlBase is a base class for every class in TinyXml. It does little except to establish that TinyXml classes can be printed and provide some utility functions. In XML, the document and elements can contain other elements and other types of nodes. @verbatim A Document can contain: Element (container or leaf) Comment (leaf) Unknown (leaf) Declaration( leaf ) An Element can contain: Element (container or leaf) Text (leaf) Attributes (not on tree) Comment (leaf) Unknown (leaf) A Decleration contains: Attributes (not on tree) @endverbatim */ class TiXmlBase { friend class TiXmlNode; friend class TiXmlElement; friend class TiXmlDocument; public: TiXmlBase() : userData(0) {} virtual ~TiXmlBase() {} /** All TinyXml classes can print themselves to a filestream. This is a formatted print, and will insert tabs and newlines. (For an unformatted stream, use the << operator.) */ virtual void Print( FILE* cfile, int depth ) const = 0; /** The world does not agree on whether white space should be kept or not. In order to make everyone happy, these global, static functions are provided to set whether or not TinyXml will condense all white space into a single space or not. The default is to condense. Note changing this values is not thread safe. */ static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } /// Return the current white space setting. static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } /** Return the position, in the original source file, of this node or attribute. The row and column are 1-based. (That is the first row and first column is 1,1). If the returns values are 0 or less, then the parser does not have a row and column value. Generally, the row and column value will be set when the TiXmlDocument::Load(), TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set when the DOM was created from operator>>. The values reflect the initial load. Once the DOM is modified programmatically (by adding or changing nodes and attributes) the new values will NOT update to reflect changes in the document. There is a minor performance cost to computing the row and column. Computation can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. @sa TiXmlDocument::SetTabSize() */ int Row() const { return location.row + 1; } int Column() const { return location.col + 1; } ///< See Row() void SetUserData( void* user ) { userData = user; } void* GetUserData() { return userData; } // Table that returs, for a given lead byte, the total number of bytes // in the UTF-8 sequence. static const int utf8ByteTable[256]; virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; enum { TIXML_NO_ERROR = 0, TIXML_ERROR, TIXML_ERROR_OPENING_FILE, TIXML_ERROR_OUT_OF_MEMORY, TIXML_ERROR_PARSING_ELEMENT, TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, TIXML_ERROR_READING_ELEMENT_VALUE, TIXML_ERROR_READING_ATTRIBUTES, TIXML_ERROR_PARSING_EMPTY, TIXML_ERROR_READING_END_TAG, TIXML_ERROR_PARSING_UNKNOWN, TIXML_ERROR_PARSING_COMMENT, TIXML_ERROR_PARSING_DECLARATION, TIXML_ERROR_DOCUMENT_EMPTY, TIXML_ERROR_EMBEDDED_NULL, TIXML_ERROR_PARSING_CDATA, TIXML_ERROR_STRING_COUNT }; protected: // See STL_STRING_BUG // Utility class to overcome a bug. class StringToBuffer { public: StringToBuffer( const TIXML_STRING& str ); ~StringToBuffer(); char* buffer; }; static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); inline static bool IsWhiteSpace( char c ) { return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); } virtual void StreamOut (TIXML_OSTREAM *) const = 0; #ifdef TIXML_USE_STL static bool StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag ); static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag ); #endif /* Reads an XML name into the string provided. Returns a pointer just past the last character of the name, or 0 if the function has an error. */ static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); /* Reads text. Returns a pointer past the given end tag. Wickedly complex options, but it keeps the (sensitive) code in one place. */ static const char* ReadText( const char* in, // where to start TIXML_STRING* text, // the string read bool ignoreWhiteSpace, // whether to keep the white space const char* endTag, // what ends this text bool ignoreCase, // whether to ignore case in the end tag TiXmlEncoding encoding ); // the current encoding // If an entity has been found, transform it into a character. static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); // Get a character, while interpreting entities. // The length can be from 0 to 4 bytes. inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) { assert( p ); if ( encoding == TIXML_ENCODING_UTF8 ) { *length = utf8ByteTable[ *((unsigned char*)p) ]; assert( *length >= 0 && *length < 5 ); } else { *length = 1; } if ( *length == 1 ) { if ( *p == '&' ) return GetEntity( p, _value, length, encoding ); *_value = *p; return p+1; } else if ( *length ) { //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), // and the null terminator isn't needed for( int i=0; p[i] && i<*length; ++i ) { _value[i] = p[i]; } return p + (*length); } else { // Not valid text. return 0; } } // Puts a string to a stream, expanding entities as it goes. // Note this should not contian the '<', '>', etc, or they will be transformed into entities! static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out ); static void PutString( const TIXML_STRING& str, TIXML_STRING* out ); // Return true if the next characters in the stream are any of the endTag sequences. // Ignore case only works for english, and should only be relied on when comparing // to English words: StringEqual( p, "version", true ) is fine. static bool StringEqual( const char* p, const char* endTag, bool ignoreCase, TiXmlEncoding encoding ); static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; TiXmlCursor location; /// Field containing a generic user pointer void* userData; // None of these methods are reliable for any language except English. // Good for approximation, not great for accuracy. static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); inline static int ToLower( int v, TiXmlEncoding encoding ) { if ( encoding == TIXML_ENCODING_UTF8 ) { if ( v < 128 ) return tolower( v ); return v; } else { return tolower( v ); } } static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); private: TiXmlBase( const TiXmlBase& ); // not implemented. void operator=( const TiXmlBase& base ); // not allowed. struct Entity { const char* str; unsigned int strLength; char chr; }; enum { NUM_ENTITY = 5, MAX_ENTITY_LENGTH = 6 }; static Entity entity[ NUM_ENTITY ]; static bool condenseWhiteSpace; }; /** The parent class for everything in the Document Object Model. (Except for attributes). Nodes have siblings, a parent, and children. A node can be in a document, or stand on its own. The type of a TiXmlNode can be queried, and it can be cast to its more defined type. */ class TiXmlNode : public TiXmlBase { friend class TiXmlDocument; friend class TiXmlElement; public: #ifdef TIXML_USE_STL /** An input stream operator, for every class. Tolerant of newlines and formatting, but doesn't expect them. */ friend std::istream& operator >> (std::istream& in, TiXmlNode& base); /** An output stream operator, for every class. Note that this outputs without any newlines or formatting, as opposed to Print(), which includes tabs and new lines. The operator<< and operator>> are not completely symmetric. Writing a node to a stream is very well defined. You'll get a nice stream of output, without any extra whitespace or newlines. But reading is not as well defined. (As it always is.) If you create a TiXmlElement (for example) and read that from an input stream, the text needs to define an element or junk will result. This is true of all input streams, but it's worth keeping in mind. A TiXmlDocument will read nodes until it reads a root element, and all the children of that root element. */ friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); /// Appends the XML node or attribute to a std::string. friend std::string& operator<< (std::string& out, const TiXmlNode& base ); #else // Used internally, not part of the public API. friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base); #endif /** The types of XML nodes supported by TinyXml. (All the unsupported types are picked up by UNKNOWN.) */ enum NodeType { DOCUMENT, ELEMENT, COMMENT, UNKNOWN, TEXT, DECLARATION, TYPECOUNT }; virtual ~TiXmlNode(); /** The meaning of 'value' changes for the specific type of TiXmlNode. @verbatim Document: filename of the xml file Element: name of the element Comment: the comment text Unknown: the tag contents Text: the text string @endverbatim The subclasses will wrap this function. */ const char *Value() const { return value.c_str (); } #ifdef TIXML_USE_STL /** Return Value() as a std::string. If you only use STL, this is more efficient than calling Value(). Only available in STL mode. */ const std::string& ValueStr() const { return value; } #endif /** Changes the value of the node. Defined as: @verbatim Document: filename of the xml file Element: name of the element Comment: the comment text Unknown: the tag contents Text: the text string @endverbatim */ void SetValue(const char * _value) { value = _value;} #ifdef TIXML_USE_STL /// STL std::string form. void SetValue( const std::string& _value ) { StringToBuffer buf( _value ); SetValue( buf.buffer ? buf.buffer : "" ); } #endif /// Delete all the children of this node. Does not affect 'this'. void Clear(); /// One step up the DOM. TiXmlNode* Parent() { return parent; } const TiXmlNode* Parent() const { return parent; } const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. TiXmlNode* FirstChild() { return firstChild; } const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. TiXmlNode* FirstChild( const char * value ); ///< The first child of this node with the matching 'value'. Will be null if none found. const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. TiXmlNode* LastChild() { return lastChild; } const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. TiXmlNode* LastChild( const char * value ); #ifdef TIXML_USE_STL const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. #endif /** An alternate way to walk the children of a node. One way to iterate over nodes is: @verbatim for( child = parent->FirstChild(); child; child = child->NextSibling() ) @endverbatim IterateChildren does the same thing with the syntax: @verbatim child = 0; while( child = parent->IterateChildren( child ) ) @endverbatim IterateChildren takes the previous child as input and finds the next one. If the previous child is null, it returns the first. IterateChildren will return null when done. */ const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; TiXmlNode* IterateChildren( TiXmlNode* previous ); /// This flavor of IterateChildren searches for children with a particular 'value' const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous ); #ifdef TIXML_USE_STL const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. #endif /** Add a new node related to this. Adds a child past the LastChild. Returns a pointer to the new object or NULL if an error occured. */ TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); /** Add a new node related to this. Adds a child past the LastChild. NOTE: the node to be added is passed by pointer, and will be henceforth owned (and deleted) by tinyXml. This method is efficient and avoids an extra copy, but should be used with care as it uses a different memory model than the other insert functions. @sa InsertEndChild */ TiXmlNode* LinkEndChild( TiXmlNode* addThis ); /** Add a new node related to this. Adds a child before the specified child. Returns a pointer to the new object or NULL if an error occured. */ TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); /** Add a new node related to this. Adds a child after the specified child. Returns a pointer to the new object or NULL if an error occured. */ TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); /** Replace a child of this node. Returns a pointer to the new object or NULL if an error occured. */ TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); /// Delete a child of this node. bool RemoveChild( TiXmlNode* removeThis ); /// Navigate to a sibling node. const TiXmlNode* PreviousSibling() const { return prev; } TiXmlNode* PreviousSibling() { return prev; } /// Navigate to a sibling node. const TiXmlNode* PreviousSibling( const char * ) const; TiXmlNode* PreviousSibling( const char * ); #ifdef TIXML_USE_STL const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. #endif /// Navigate to a sibling node. const TiXmlNode* NextSibling() const { return next; } TiXmlNode* NextSibling() { return next; } /// Navigate to a sibling node with the given 'value'. const TiXmlNode* NextSibling( const char * ) const; TiXmlNode* NextSibling( const char * ); /** Convenience function to get through elements. Calls NextSibling and ToElement. Will skip all non-Element nodes. Returns 0 if there is not another element. */ const TiXmlElement* NextSiblingElement() const; TiXmlElement* NextSiblingElement(); /** Convenience function to get through elements. Calls NextSibling and ToElement. Will skip all non-Element nodes. Returns 0 if there is not another element. */ const TiXmlElement* NextSiblingElement( const char * ) const; TiXmlElement* NextSiblingElement( const char * ); #ifdef TIXML_USE_STL const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. #endif /// Convenience function to get through elements. const TiXmlElement* FirstChildElement() const; TiXmlElement* FirstChildElement(); /// Convenience function to get through elements. const TiXmlElement* FirstChildElement( const char * value ) const; TiXmlElement* FirstChildElement( const char * value ); #ifdef TIXML_USE_STL const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. #endif /** Query the type (as an enumerated value, above) of this node. The possible types are: DOCUMENT, ELEMENT, COMMENT, UNKNOWN, TEXT, and DECLARATION. */ int Type() const { return type; } /** Return a pointer to the Document this node lives in. Returns null if not in a document. */ const TiXmlDocument* GetDocument() const; TiXmlDocument* GetDocument(); /// Returns true if this node has no children. bool NoChildren() const { return !firstChild; } const TiXmlDocument* ToDocument() const { return ( this && type == DOCUMENT ) ? (const TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. const TiXmlElement* ToElement() const { return ( this && type == ELEMENT ) ? (const TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. const TiXmlComment* ToComment() const { return ( this && type == COMMENT ) ? (const TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. const TiXmlUnknown* ToUnknown() const { return ( this && type == UNKNOWN ) ? (const TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. const TiXmlText* ToText() const { return ( this && type == TEXT ) ? (const TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. const TiXmlDeclaration* ToDeclaration() const { return ( this && type == DECLARATION ) ? (const TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. TiXmlDocument* ToDocument() { return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. TiXmlElement* ToElement() { return ( this && type == ELEMENT ) ? (TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. TiXmlComment* ToComment() { return ( this && type == COMMENT ) ? (TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. TiXmlUnknown* ToUnknown() { return ( this && type == UNKNOWN ) ? (TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. TiXmlText* ToText() { return ( this && type == TEXT ) ? (TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. TiXmlDeclaration* ToDeclaration() { return ( this && type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. /** Create an exact duplicate of this node and return it. The memory must be deleted by the caller. */ virtual TiXmlNode* Clone() const = 0; protected: TiXmlNode( NodeType _type ); // Copy to the allocated object. Shared functionality between Clone, Copy constructor, // and the assignment operator. void CopyTo( TiXmlNode* target ) const; #ifdef TIXML_USE_STL // The real work of the input operator. virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0; #endif // Figure out what is at *p, and parse it. Returns null if it is not an xml node. TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); TiXmlNode* parent; NodeType type; TiXmlNode* firstChild; TiXmlNode* lastChild; TIXML_STRING value; TiXmlNode* prev; TiXmlNode* next; private: TiXmlNode( const TiXmlNode& ); // not implemented. void operator=( const TiXmlNode& base ); // not allowed. }; /** An attribute is a name-value pair. Elements have an arbitrary number of attributes, each with a unique name. @note The attributes are not TiXmlNodes, since they are not part of the tinyXML document object model. There are other suggested ways to look at this problem. */ class TiXmlAttribute : public TiXmlBase { friend class TiXmlAttributeSet; public: /// Construct an empty attribute. TiXmlAttribute() : TiXmlBase() { document = 0; prev = next = 0; } #ifdef TIXML_USE_STL /// std::string constructor. TiXmlAttribute( const std::string& _name, const std::string& _value ) { name = _name; value = _value; document = 0; prev = next = 0; } #endif /// Construct an attribute with a name and value. TiXmlAttribute( const char * _name, const char * _value ) { name = _name; value = _value; document = 0; prev = next = 0; } const char* Name() const { return name.c_str (); } ///< Return the name of this attribute. const char* Value() const { return value.c_str (); } ///< Return the value of this attribute. int IntValue() const; ///< Return the value of this attribute, converted to an integer. double DoubleValue() const; ///< Return the value of this attribute, converted to a double. /** QueryIntValue examines the value string. It is an alternative to the IntValue() method with richer error checking. If the value is an integer, it is stored in 'value' and the call returns TIXML_SUCCESS. If it is not an integer, it returns TIXML_WRONG_TYPE. A specialized but useful call. Note that for success it returns 0, which is the opposite of almost all other TinyXml calls. */ int QueryIntValue( int* _value ) const; /// QueryDoubleValue examines the value string. See QueryIntValue(). int QueryDoubleValue( double* _value ) const; void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. void SetValue( const char* _value ) { value = _value; } ///< Set the value. void SetIntValue( int _value ); ///< Set the value from an integer. void SetDoubleValue( double _value ); ///< Set the value from a double. #ifdef TIXML_USE_STL /// STL std::string form. void SetName( const std::string& _name ) { StringToBuffer buf( _name ); SetName ( buf.buffer ? buf.buffer : "error" ); } /// STL std::string form. void SetValue( const std::string& _value ) { StringToBuffer buf( _value ); SetValue( buf.buffer ? buf.buffer : "error" ); } #endif /// Get the next sibling attribute in the DOM. Returns null at end. const TiXmlAttribute* Next() const; TiXmlAttribute* Next(); /// Get the previous sibling attribute in the DOM. Returns null at beginning. const TiXmlAttribute* Previous() const; TiXmlAttribute* Previous(); bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } /* Attribute parsing starts: first letter of the name returns: the next char after the value end quote */ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); // Prints this Attribute to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; virtual void StreamOut( TIXML_OSTREAM * out ) const; // [internal use] // Set the document pointer so the attribute can report errors. void SetDocument( TiXmlDocument* doc ) { document = doc; } private: TiXmlAttribute( const TiXmlAttribute& ); // not implemented. void operator=( const TiXmlAttribute& base ); // not allowed. TiXmlDocument* document; // A pointer back to a document, for error reporting. TIXML_STRING name; TIXML_STRING value; TiXmlAttribute* prev; TiXmlAttribute* next; }; /* A class used to manage a group of attributes. It is only used internally, both by the ELEMENT and the DECLARATION. The set can be changed transparent to the Element and Declaration classes that use it, but NOT transparent to the Attribute which has to implement a next() and previous() method. Which makes it a bit problematic and prevents the use of STL. This version is implemented with circular lists because: - I like circular lists - it demonstrates some independence from the (typical) doubly linked list. */ class TiXmlAttributeSet { public: TiXmlAttributeSet(); ~TiXmlAttributeSet(); void Add( TiXmlAttribute* attribute ); void Remove( TiXmlAttribute* attribute ); const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } const TiXmlAttribute* Find( const char * name ) const; TiXmlAttribute* Find( const char * name ); private: //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), //*ME: this class must be also use a hidden/disabled copy-constructor !!! TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) TiXmlAttribute sentinel; }; /** The element is a container class. It has a value, the element name, and can contain other elements, text, comments, and unknowns. Elements also contain an arbitrary number of attributes. */ class TiXmlElement : public TiXmlNode { public: /// Construct an element. TiXmlElement (const char * in_value); #ifdef TIXML_USE_STL /// std::string constructor. TiXmlElement( const std::string& _value ); #endif TiXmlElement( const TiXmlElement& ); void operator=( const TiXmlElement& base ); virtual ~TiXmlElement(); /** Given an attribute name, Attribute() returns the value for the attribute of that name, or null if none exists. */ const char* Attribute( const char* name ) const; /** Given an attribute name, Attribute() returns the value for the attribute of that name, or null if none exists. If the attribute exists and can be converted to an integer, the integer value will be put in the return 'i', if 'i' is non-null. */ const char* Attribute( const char* name, int* i ) const; /** Given an attribute name, Attribute() returns the value for the attribute of that name, or null if none exists. If the attribute exists and can be converted to an double, the double value will be put in the return 'd', if 'd' is non-null. */ const char* Attribute( const char* name, double* d ) const; /** QueryIntAttribute examines the attribute - it is an alternative to the Attribute() method with richer error checking. If the attribute is an integer, it is stored in 'value' and the call returns TIXML_SUCCESS. If it is not an integer, it returns TIXML_WRONG_TYPE. If the attribute does not exist, then TIXML_NO_ATTRIBUTE is returned. */ int QueryIntAttribute( const char* name, int* _value ) const; /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). int QueryDoubleAttribute( const char* name, double* _value ) const; /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). int QueryFloatAttribute( const char* name, float* _value ) const { double d; int result = QueryDoubleAttribute( name, &d ); if ( result == TIXML_SUCCESS ) { *_value = (float)d; } return result; } /** Sets an attribute of name to a given value. The attribute will be created if it does not exist, or changed if it does. */ void SetAttribute( const char* name, const char * _value ); #ifdef TIXML_USE_STL const char* Attribute( const std::string& name ) const { return Attribute( name.c_str() ); } const char* Attribute( const std::string& name, int* i ) const { return Attribute( name.c_str(), i ); } const char* Attribute( const std::string& name, double* d ) const { return Attribute( name.c_str(), d ); } int QueryIntAttribute( const std::string& name, int* _value ) const { return QueryIntAttribute( name.c_str(), _value ); } int QueryDoubleAttribute( const std::string& name, double* _value ) const { return QueryDoubleAttribute( name.c_str(), _value ); } /// STL std::string form. void SetAttribute( const std::string& name, const std::string& _value ) { StringToBuffer n( name ); StringToBuffer v( _value ); if ( n.buffer && v.buffer ) SetAttribute (n.buffer, v.buffer ); } ///< STL std::string form. void SetAttribute( const std::string& name, int _value ) { StringToBuffer n( name ); if ( n.buffer ) SetAttribute (n.buffer, _value); } #endif /** Sets an attribute of name to a given value. The attribute will be created if it does not exist, or changed if it does. */ void SetAttribute( const char * name, int value ); /** Sets an attribute of name to a given value. The attribute will be created if it does not exist, or changed if it does. */ void SetDoubleAttribute( const char * name, double value ); /** Deletes an attribute with the given name. */ void RemoveAttribute( const char * name ); #ifdef TIXML_USE_STL void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. #endif const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } /** Convenience function for easy access to the text inside an element. Although easy and concise, GetText() is limited compared to getting the TiXmlText child and accessing it directly. If the first child of 'this' is a TiXmlText, the GetText() returns the character string of the Text node, else null is returned. This is a convenient method for getting the text of simple contained text: @verbatim This is text const char* str = fooElement->GetText(); @endverbatim 'str' will be a pointer to "This is text". Note that this function can be misleading. If the element foo was created from this XML: @verbatim This is text @endverbatim then the value of str would be null. The first child node isn't a text node, it is another element. From this XML: @verbatim This is text @endverbatim GetText() will return "This is ". WARNING: GetText() accesses a child node - don't become confused with the similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are safe type casts on the referenced node. */ const char* GetText() const; /// Creates a new Element and returns it - the returned element is a copy. virtual TiXmlNode* Clone() const; // Print the Element to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; /* Attribtue parsing starts: next char past '<' returns: next char past '>' */ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); protected: void CopyTo( TiXmlElement* target ) const; void ClearThis(); // like clear, but initializes 'this' object as well // Used to be public [internal use] #ifdef TIXML_USE_STL virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ); #endif virtual void StreamOut( TIXML_OSTREAM * out ) const; /* [internal use] Reads the "value" of the element -- another element, or text. This should terminate with the current end tag. */ const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); private: TiXmlAttributeSet attributeSet; }; /** An XML comment. */ class TiXmlComment : public TiXmlNode { public: /// Constructs an empty comment. TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} TiXmlComment( const TiXmlComment& ); void operator=( const TiXmlComment& base ); virtual ~TiXmlComment() {} /// Returns a copy of this Comment. virtual TiXmlNode* Clone() const; /// Write this Comment to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; /* Attribtue parsing starts: at the ! of the !-- returns: next char past '>' */ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); protected: void CopyTo( TiXmlComment* target ) const; // used to be public #ifdef TIXML_USE_STL virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ); #endif virtual void StreamOut( TIXML_OSTREAM * out ) const; private: }; /** XML text. A text node can have 2 ways to output the next. "normal" output and CDATA. It will default to the mode it was parsed from the XML file and you generally want to leave it alone, but you can change the output mode with SetCDATA() and query it with CDATA(). */ class TiXmlText : public TiXmlNode { friend class TiXmlElement; public: /** Constructor for text element. By default, it is treated as normal, encoded text. If you want it be output as a CDATA text element, set the parameter _cdata to 'true' */ TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) { SetValue( initValue ); cdata = false; } virtual ~TiXmlText() {} #ifdef TIXML_USE_STL /// Constructor. TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) { SetValue( initValue ); cdata = false; } #endif TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } void operator=( const TiXmlText& base ) { base.CopyTo( this ); } /// Write this text object to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; /// Queries whether this represents text using a CDATA section. bool CDATA() { return cdata; } /// Turns on or off a CDATA representation of text. void SetCDATA( bool _cdata ) { cdata = _cdata; } virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); protected : /// [internal use] Creates a new Element and returns it. virtual TiXmlNode* Clone() const; void CopyTo( TiXmlText* target ) const; virtual void StreamOut ( TIXML_OSTREAM * out ) const; bool Blank() const; // returns true if all white space and new lines // [internal use] #ifdef TIXML_USE_STL virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ); #endif private: bool cdata; // true if this should be input and output as a CDATA style text element }; /** In correct XML the declaration is the first entry in the file. @verbatim @endverbatim TinyXml will happily read or write files without a declaration, however. There are 3 possible attributes to the declaration: version, encoding, and standalone. Note: In this version of the code, the attributes are handled as special cases, not generic attributes, simply because there can only be at most 3 and they are always the same. */ class TiXmlDeclaration : public TiXmlNode { public: /// Construct an empty declaration. TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} #ifdef TIXML_USE_STL /// Constructor. TiXmlDeclaration( const std::string& _version, const std::string& _encoding, const std::string& _standalone ); #endif /// Construct. TiXmlDeclaration( const char* _version, const char* _encoding, const char* _standalone ); TiXmlDeclaration( const TiXmlDeclaration& copy ); void operator=( const TiXmlDeclaration& copy ); virtual ~TiXmlDeclaration() {} /// Version. Will return an empty string if none was found. const char *Version() const { return version.c_str (); } /// Encoding. Will return an empty string if none was found. const char *Encoding() const { return encoding.c_str (); } /// Is this a standalone document? const char *Standalone() const { return standalone.c_str (); } /// Creates a copy of this Declaration and returns it. virtual TiXmlNode* Clone() const; /// Print this declaration to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); protected: void CopyTo( TiXmlDeclaration* target ) const; // used to be public #ifdef TIXML_USE_STL virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ); #endif virtual void StreamOut ( TIXML_OSTREAM * out) const; private: TIXML_STRING version; TIXML_STRING encoding; TIXML_STRING standalone; }; /** Any tag that tinyXml doesn't recognize is saved as an unknown. It is a tag of text, but should not be modified. It will be written back to the XML, unchanged, when the file is saved. DTD tags get thrown into TiXmlUnknowns. */ class TiXmlUnknown : public TiXmlNode { public: TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} virtual ~TiXmlUnknown() {} TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } /// Creates a copy of this Unknown and returns it. virtual TiXmlNode* Clone() const; /// Print this Unknown to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); protected: void CopyTo( TiXmlUnknown* target ) const; #ifdef TIXML_USE_STL virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ); #endif virtual void StreamOut ( TIXML_OSTREAM * out ) const; private: }; /** Always the top level node. A document binds together all the XML pieces. It can be saved, loaded, and printed to the screen. The 'value' of a document node is the xml file name. */ class TiXmlDocument : public TiXmlNode { public: /// Create an empty document, that has no name. TiXmlDocument(); /// Create a document with a name. The name of the document is also the filename of the xml. TiXmlDocument( const char * documentName ); #ifdef TIXML_USE_STL /// Constructor. TiXmlDocument( const std::string& documentName ); #endif TiXmlDocument( const TiXmlDocument& copy ); void operator=( const TiXmlDocument& copy ); virtual ~TiXmlDocument() {} /** Load a file using the current document value. Returns true if successful. Will delete any existing document data before loading. */ bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); /// Save a file using the current document value. Returns true if successful. bool SaveFile() const; /// Load a file using the given filename. Returns true if successful. bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); /// Save a file using the given filename. Returns true if successful. bool SaveFile( const char * filename ) const; #ifdef TIXML_USE_STL bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. { StringToBuffer f( filename ); return ( f.buffer && LoadFile( f.buffer, encoding )); } bool SaveFile( const std::string& filename ) const ///< STL std::string version. { StringToBuffer f( filename ); return ( f.buffer && SaveFile( f.buffer )); } #endif /** Parse the given null terminated block of xml data. Passing in an encoding to this method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml to use that encoding, regardless of what TinyXml might otherwise try to detect. */ virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); /** Get the root element -- the only top level element -- of the document. In well formed XML, there should only be one. TinyXml is tolerant of multiple elements at the document level. */ const TiXmlElement* RootElement() const { return FirstChildElement(); } TiXmlElement* RootElement() { return FirstChildElement(); } /** If an error occurs, Error will be set to true. Also, - The ErrorId() will contain the integer identifier of the error (not generally useful) - The ErrorDesc() method will return the name of the error. (very useful) - The ErrorRow() and ErrorCol() will return the location of the error (if known) */ bool Error() const { return error; } /// Contains a textual (english) description of the error if one occurs. const char * ErrorDesc() const { return errorDesc.c_str (); } /** Generally, you probably want the error string ( ErrorDesc() ). But if you prefer the ErrorId, this function will fetch it. */ int ErrorId() const { return errorId; } /** Returns the location (if known) of the error. The first column is column 1, and the first row is row 1. A value of 0 means the row and column wasn't applicable (memory errors, for example, have no row/column) or the parser lost the error. (An error in the error reporting, in that case.) @sa SetTabSize, Row, Column */ int ErrorRow() { return errorLocation.row+1; } int ErrorCol() { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) to report the correct values for row and column. It does not change the output or input in any way. By calling this method, with a tab size greater than 0, the row and column of each node and attribute is stored when the file is loaded. Very useful for tracking the DOM back in to the source file. The tab size is required for calculating the location of nodes. If not set, the default of 4 is used. The tabsize is set per document. Setting the tabsize to 0 disables row/column tracking. Note that row and column tracking is not supported when using operator>>. The tab size needs to be enabled before the parse or load. Correct usage: @verbatim TiXmlDocument doc; doc.SetTabSize( 8 ); doc.Load( "myfile.xml" ); @endverbatim @sa Row, Column */ void SetTabSize( int _tabsize ) { tabsize = _tabsize; } int TabSize() const { return tabsize; } /** If you have handled the error, it can be reset with this call. The error state is automatically cleared if you Parse a new XML block. */ void ClearError() { error = false; errorId = 0; errorDesc = ""; errorLocation.row = errorLocation.col = 0; //errorLocation.last = 0; } /** Dump the document to standard out. */ void Print() const { Print( stdout, 0 ); } /// Print this Document to a FILE stream. virtual void Print( FILE* cfile, int depth = 0 ) const; // [internal use] void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); protected : virtual void StreamOut ( TIXML_OSTREAM * out) const; // [internal use] virtual TiXmlNode* Clone() const; #ifdef TIXML_USE_STL virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ); #endif private: void CopyTo( TiXmlDocument* target ) const; bool error; int errorId; TIXML_STRING errorDesc; int tabsize; TiXmlCursor errorLocation; bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. }; /** A TiXmlHandle is a class that wraps a node pointer with null checks; this is an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml DOM structure. It is a separate utility class. Take an example: @verbatim @endverbatim Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very easy to write a *lot* of code that looks like: @verbatim TiXmlElement* root = document.FirstChildElement( "Document" ); if ( root ) { TiXmlElement* element = root->FirstChildElement( "Element" ); if ( element ) { TiXmlElement* child = element->FirstChildElement( "Child" ); if ( child ) { TiXmlElement* child2 = child->NextSiblingElement( "Child" ); if ( child2 ) { // Finally do something useful. @endverbatim And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity of such code. A TiXmlHandle checks for null pointers so it is perfectly safe and correct to use: @verbatim TiXmlHandle docHandle( &document ); TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element(); if ( child2 ) { // do something useful @endverbatim Which is MUCH more concise and useful. It is also safe to copy handles - internally they are nothing more than node pointers. @verbatim TiXmlHandle handleCopy = handle; @endverbatim What they should not be used for is iteration: @verbatim int i=0; while ( true ) { TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element(); if ( !child ) break; // do something ++i; } @endverbatim It seems reasonable, but it is in fact two embedded while loops. The Child method is a linear walk to find the element, so this code would iterate much more than it needs to. Instead, prefer: @verbatim TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element(); for( child; child; child=child->NextSiblingElement() ) { // do something } @endverbatim */ class TiXmlHandle { public: /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } /// Copy constructor TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } /// Return a handle to the first child node. TiXmlHandle FirstChild() const; /// Return a handle to the first child node with the given name. TiXmlHandle FirstChild( const char * value ) const; /// Return a handle to the first child element. TiXmlHandle FirstChildElement() const; /// Return a handle to the first child element with the given name. TiXmlHandle FirstChildElement( const char * value ) const; /** Return a handle to the "index" child with the given name. The first child is 0, the second 1, etc. */ TiXmlHandle Child( const char* value, int index ) const; /** Return a handle to the "index" child. The first child is 0, the second 1, etc. */ TiXmlHandle Child( int index ) const; /** Return a handle to the "index" child element with the given name. The first child element is 0, the second 1, etc. Note that only TiXmlElements are indexed: other types are not counted. */ TiXmlHandle ChildElement( const char* value, int index ) const; /** Return a handle to the "index" child element. The first child element is 0, the second 1, etc. Note that only TiXmlElements are indexed: other types are not counted. */ TiXmlHandle ChildElement( int index ) const; #ifdef TIXML_USE_STL TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } #endif /// Return the handle as a TiXmlNode. This may return null. TiXmlNode* Node() const { return node; } /// Return the handle as a TiXmlElement. This may return null. TiXmlElement* Element() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } /// Return the handle as a TiXmlText. This may return null. TiXmlText* Text() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } /// Return the handle as a TiXmlUnknown. This may return null; TiXmlUnknown* Unknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } private: TiXmlNode* node; }; #ifdef _MSC_VER #pragma warning( pop ) #endif #endif gambit-0.2010.09.01/src/gui/tinyxmlerror.cc0000644000076500007650000000326311350032206015074 00000000000000/* www.sourceforge.net/projects/tinyxml Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #include "tinyxml.h" // The goal of the seperate error file is to make the first // step towards localization. tinyxml (currently) only supports // english error messages, but the could now be translated. // // It also cleans up the code a bit. // const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = { "No error", "Error", "Failed to open file", "Memory allocation failed.", "Error parsing Element.", "Failed to read Element name", "Error reading Element value.", "Error reading Attributes.", "Error: empty tag.", "Error reading end tag.", "Error parsing Unknown.", "Error parsing Comment.", "Error parsing Declaration.", "Error document empty.", "Error null (0) or unexpected EOF found in input stream.", "Error parsing CDATA.", }; gambit-0.2010.09.01/src/gui/tinyxmlparser.cc0000644000076500007650000010367611350032206015250 00000000000000/* www.sourceforge.net/projects/tinyxml Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #include "tinyxml.h" #include #include //#define DEBUG_PARSER // Note tha "PutString" hardcodes the same list. This // is less flexible than it appears. Changing the entries // or order will break putstring. TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = { { "&", 5, '&' }, { "<", 4, '<' }, { ">", 4, '>' }, { """, 6, '\"' }, { "'", 6, '\'' } }; // Bunch of unicode info at: // http://www.unicode.org/faq/utf_bom.html // Including the basic of this table, which determines the #bytes in the // sequence from the lead byte. 1 placed for invalid sequences -- // although the result will be junk, pass it through as much as possible. // Beware of the non-characters in UTF-8: // ef bb bf (Microsoft "lead bytes") // ef bf be // ef bf bf const unsigned char TIXML_UTF_LEAD_0 = 0xefU; const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; const int TiXmlBase::utf8ByteTable[256] = { // 0 1 2 3 4 5 6 7 8 9 a b c d e f 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid }; void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) { const unsigned long BYTE_MASK = 0xBF; const unsigned long BYTE_MARK = 0x80; const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; if (input < 0x80) *length = 1; else if ( input < 0x800 ) *length = 2; else if ( input < 0x10000 ) *length = 3; else if ( input < 0x200000 ) *length = 4; else { *length = 0; return; } // This code won't covert this correctly anyway. output += *length; // Scary scary fall throughs. switch (*length) { case 4: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 3: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 2: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 1: --output; *output = (char)(input | FIRST_BYTE_MARK[*length]); } } /*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) { // This will only work for low-ascii, everything else is assumed to be a valid // letter. I'm not sure this is the best approach, but it is quite tricky trying // to figure out alhabetical vs. not across encoding. So take a very // conservative approach. // if ( encoding == TIXML_ENCODING_UTF8 ) // { if ( anyByte < 127 ) return isalpha( anyByte ); else return 1; // What else to do? The unicode set is huge...get the english ones right. // } // else // { // return isalpha( anyByte ); // } } /*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) { // This will only work for low-ascii, everything else is assumed to be a valid // letter. I'm not sure this is the best approach, but it is quite tricky trying // to figure out alhabetical vs. not across encoding. So take a very // conservative approach. // if ( encoding == TIXML_ENCODING_UTF8 ) // { if ( anyByte < 127 ) return isalnum( anyByte ); else return 1; // What else to do? The unicode set is huge...get the english ones right. // } // else // { // return isalnum( anyByte ); // } } class TiXmlParsingData { friend class TiXmlDocument; public: void Stamp( const char* now, TiXmlEncoding encoding ); const TiXmlCursor& Cursor() { return cursor; } private: // Only used by the document! TiXmlParsingData( const char* start, int _tabsize, int row, int col ) { assert( start ); stamp = start; tabsize = _tabsize; cursor.row = row; cursor.col = col; } TiXmlCursor cursor; const char* stamp; int tabsize; }; void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) { assert( now ); // Do nothing if the tabsize is 0. if ( tabsize < 1 ) { return; } // Get the current row, column. int row = cursor.row; int col = cursor.col; const char* p = stamp; assert( p ); while ( p < now ) { // Treat p as unsigned, so we have a happy compiler. const unsigned char* pU = (const unsigned char*)p; // Code contributed by Fletcher Dunn: (modified by lee) switch (*pU) { case 0: // We *should* never get here, but in case we do, don't // advance past the terminating null character, ever return; case '\r': // bump down to the next line ++row; col = 0; // Eat the character ++p; // Check for \r\n sequence, and treat this as a single character if (*p == '\n') { ++p; } break; case '\n': // bump down to the next line ++row; col = 0; // Eat the character ++p; // Check for \n\r sequence, and treat this as a single // character. (Yes, this bizarre thing does occur still // on some arcane platforms...) if (*p == '\r') { ++p; } break; case '\t': // Eat the character ++p; // Skip to next tab stop col = (col / tabsize + 1) * tabsize; break; case TIXML_UTF_LEAD_0: if ( encoding == TIXML_ENCODING_UTF8 ) { if ( *(p+1) && *(p+2) ) { // In these cases, don't advance the column. These are // 0-width spaces. if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) p += 3; else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) p += 3; else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) p += 3; else { p +=3; ++col; } // A normal character. } } else { ++p; ++col; } break; default: if ( encoding == TIXML_ENCODING_UTF8 ) { // Eat the 1 to 4 byte utf8 character. int step = TiXmlBase::utf8ByteTable[*((unsigned char*)p)]; if ( step == 0 ) step = 1; // Error case from bad encoding, but handle gracefully. p += step; // Just advance one column, of course. ++col; } else { ++p; ++col; } break; } } cursor.row = row; cursor.col = col; assert( cursor.row >= -1 ); assert( cursor.col >= -1 ); stamp = p; assert( stamp ); } const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) { if ( !p || !*p ) { return 0; } if ( encoding == TIXML_ENCODING_UTF8 ) { while ( *p ) { const unsigned char* pU = (const unsigned char*)p; // Skip the stupid Microsoft UTF-8 Byte order marks if ( *(pU+0)==TIXML_UTF_LEAD_0 && *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) { p += 3; continue; } else if(*(pU+0)==TIXML_UTF_LEAD_0 && *(pU+1)==0xbfU && *(pU+2)==0xbeU ) { p += 3; continue; } else if(*(pU+0)==TIXML_UTF_LEAD_0 && *(pU+1)==0xbfU && *(pU+2)==0xbfU ) { p += 3; continue; } if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. ++p; else break; } } else { while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) ++p; } return p; } #ifdef TIXML_USE_STL /*static*/ bool TiXmlBase::StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag ) { for( ;; ) { if ( !in->good() ) return false; int c = in->peek(); // At this scope, we can't get to a document. So fail silently. if ( !IsWhiteSpace( c ) || c <= 0 ) return true; *tag += (char) in->get(); } } /*static*/ bool TiXmlBase::StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag ) { //assert( character > 0 && character < 128 ); // else it won't work in utf-8 while ( in->good() ) { int c = in->peek(); if ( c == character ) return true; if ( c <= 0 ) // Silent failure: can't get document at this scope return false; in->get(); *tag += (char) c; } return false; } #endif const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) { *name = ""; assert( p ); // Names start with letters or underscores. // Of course, in unicode, tinyxml has no idea what a letter *is*. The // algorithm is generous. // // After that, they can be letters, underscores, numbers, // hyphens, or colons. (Colons are valid ony for namespaces, // but tinyxml can't tell namespaces from names.) if ( p && *p && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) { while( p && *p && ( IsAlphaNum( (unsigned char ) *p, encoding ) || *p == '_' || *p == '-' || *p == '.' || *p == ':' ) ) { (*name) += *p; ++p; } return p; } return 0; } const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) { // Presume an entity, and pull it out. TIXML_STRING ent; int i; *length = 0; if ( *(p+1) && *(p+1) == '#' && *(p+2) ) { unsigned long ucs = 0; ptrdiff_t delta = 0; unsigned mult = 1; if ( *(p+2) == 'x' ) { // Hexadecimal. if ( !*(p+3) ) return 0; const char* q = p+3; q = strchr( q, ';' ); if ( !q || !*q ) return 0; delta = q-p; --q; while ( *q != 'x' ) { if ( *q >= '0' && *q <= '9' ) ucs += mult * (*q - '0'); else if ( *q >= 'a' && *q <= 'f' ) ucs += mult * (*q - 'a' + 10); else if ( *q >= 'A' && *q <= 'F' ) ucs += mult * (*q - 'A' + 10 ); else return 0; mult *= 16; --q; } } else { // Decimal. if ( !*(p+2) ) return 0; const char* q = p+2; q = strchr( q, ';' ); if ( !q || !*q ) return 0; delta = q-p; --q; while ( *q != '#' ) { if ( *q >= '0' && *q <= '9' ) ucs += mult * (*q - '0'); else return 0; mult *= 10; --q; } } if ( encoding == TIXML_ENCODING_UTF8 ) { // convert the UCS to UTF-8 ConvertUTF32ToUTF8( ucs, value, length ); } else { *value = (char)ucs; *length = 1; } return p + delta + 1; } // Now try to match it. for( i=0; iappend( cArr, len ); } } else { bool whitespace = false; // Remove leading white space: p = SkipWhiteSpace( p, encoding ); while ( p && *p && !StringEqual( p, endTag, caseInsensitive, encoding ) ) { if ( *p == '\r' || *p == '\n' ) { whitespace = true; ++p; } else if ( IsWhiteSpace( *p ) ) { whitespace = true; ++p; } else { // If we've found whitespace, add it before the // new character. Any whitespace just becomes a space. if ( whitespace ) { (*text) += ' '; whitespace = false; } int len; char cArr[4] = { 0, 0, 0, 0 }; p = GetChar( p, cArr, &len, encoding ); if ( len == 1 ) (*text) += cArr[0]; // more efficient else text->append( cArr, len ); } } } return p + strlen( endTag ); } #ifdef TIXML_USE_STL void TiXmlDocument::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) { // The basic issue with a document is that we don't know what we're // streaming. Read something presumed to be a tag (and hope), then // identify it, and call the appropriate stream method on the tag. // // This "pre-streaming" will never read the closing ">" so the // sub-tag can orient itself. if ( !StreamTo( in, '<', tag ) ) { SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); return; } while ( in->good() ) { int tagIndex = (int) tag->length(); while ( in->good() && in->peek() != '>' ) { int c = in->get(); if ( c <= 0 ) { SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); break; } (*tag) += (char) c; } if ( in->good() ) { // We now have something we presume to be a node of // some sort. Identify it, and call the node to // continue streaming. TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); if ( node ) { node->StreamIn( in, tag ); bool isElement = node->ToElement() != 0; delete node; node = 0; // If this is the root element, we're done. Parsing will be // done by the >> operator. if ( isElement ) { return; } } else { SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); return; } } } // We should have returned sooner. SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); } #endif const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) { ClearError(); // Parse away, at the document level. Since a document // contains nothing but other tags, most of what happens // here is skipping white space. if ( !p || !*p ) { SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } // Note that, for a document, this needs to come // before the while space skip, so that parsing // starts from the pointer we are given. location.Clear(); if ( prevData ) { location.row = prevData->cursor.row; location.col = prevData->cursor.col; } else { location.row = 0; location.col = 0; } TiXmlParsingData data( p, TabSize(), location.row, location.col ); location = data.Cursor(); if ( encoding == TIXML_ENCODING_UNKNOWN ) { // Check for the Microsoft UTF-8 lead bytes. const unsigned char* pU = (const unsigned char*)p; if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) { encoding = TIXML_ENCODING_UTF8; useMicrosoftBOM = true; } } p = SkipWhiteSpace( p, encoding ); if ( !p ) { SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } while ( p && *p ) { TiXmlNode* node = Identify( p, encoding ); if ( node ) { p = node->Parse( p, &data, encoding ); LinkEndChild( node ); } else { break; } // Did we get encoding info? if ( encoding == TIXML_ENCODING_UNKNOWN && node->ToDeclaration() ) { TiXmlDeclaration* dec = node->ToDeclaration(); const char* enc = dec->Encoding(); assert( enc ); if ( *enc == 0 ) encoding = TIXML_ENCODING_UTF8; else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) encoding = TIXML_ENCODING_UTF8; else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice else encoding = TIXML_ENCODING_LEGACY; } p = SkipWhiteSpace( p, encoding ); } // Was this empty? if ( !firstChild ) { SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); return 0; } // All is well. return p; } void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) { // The first error in a chain is more accurate - don't set again! if ( error ) return; assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); error = true; errorId = err; errorDesc = errorString[ errorId ]; errorLocation.Clear(); if ( pError && data ) { data->Stamp( pError, encoding ); errorLocation = data->Cursor(); } } TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) { TiXmlNode* returnNode = 0; p = SkipWhiteSpace( p, encoding ); if( !p || !*p || *p != '<' ) { return 0; } TiXmlDocument* doc = GetDocument(); p = SkipWhiteSpace( p, encoding ); if ( !p || !*p ) { return 0; } // What is this thing? // - Elements start with a letter or underscore, but xml is reserved. // - Comments: "; if ( !StringEqual( p, startTag, false, encoding ) ) { document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); return 0; } p += strlen( startTag ); p = ReadText( p, &value, false, endTag, false, encoding ); return p; } const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { p = SkipWhiteSpace( p, encoding ); if ( !p || !*p ) return 0; int tabsize = 4; if ( document ) tabsize = document->TabSize(); if ( data ) { data->Stamp( p, encoding ); location = data->Cursor(); } // Read the name, the '=' and the value. const char* pErr = p; p = ReadName( p, &name, encoding ); if ( !p || !*p ) { if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); return 0; } p = SkipWhiteSpace( p, encoding ); if ( !p || !*p || *p != '=' ) { if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); return 0; } ++p; // skip '=' p = SkipWhiteSpace( p, encoding ); if ( !p || !*p ) { if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); return 0; } const char* end; if ( *p == '\'' ) { ++p; end = "\'"; p = ReadText( p, &value, false, end, false, encoding ); } else if ( *p == '"' ) { ++p; end = "\""; p = ReadText( p, &value, false, end, false, encoding ); } else { // All attribute values should be in single or double quotes. // But this is such a common error that the parser will try // its best, even without them. value = ""; while ( p && *p // existence && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace && *p != '/' && *p != '>' ) // tag end { value += *p; ++p; } } return p; } #ifdef TIXML_USE_STL void TiXmlText::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) { if ( cdata ) { int c = in->get(); if ( c <= 0 ) { TiXmlDocument* document = GetDocument(); if ( document ) document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); return; } (*tag) += (char) c; if ( c == '>' && tag->at( tag->length() - 2 ) == ']' && tag->at( tag->length() - 3 ) == ']' ) { // All is well. return; } } else { while ( in->good() ) { int c = in->peek(); if ( c == '<' ) return; if ( c <= 0 ) { TiXmlDocument* document = GetDocument(); if ( document ) document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); return; } (*tag) += (char) c; in->get(); } } } #endif const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { value = ""; TiXmlDocument* document = GetDocument(); if ( data ) { data->Stamp( p, encoding ); location = data->Cursor(); } const char* const startTag = ""; if ( cdata || StringEqual( p, startTag, false, encoding ) ) { cdata = true; if ( !StringEqual( p, startTag, false, encoding ) ) { document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); return 0; } p += strlen( startTag ); // Keep all the white space, ignore the encoding, etc. while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) { value += *p; ++p; } TIXML_STRING dummy; p = ReadText( p, &dummy, false, endTag, false, encoding ); return p; } else { bool ignoreWhite = true; const char* end = "<"; p = ReadText( p, &value, ignoreWhite, end, false, encoding ); if ( p ) return p-1; // don't truncate the '<' return 0; } } #ifdef TIXML_USE_STL void TiXmlDeclaration::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag ) { while ( in->good() ) { int c = in->get(); if ( c <= 0 ) { TiXmlDocument* document = GetDocument(); if ( document ) document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); return; } (*tag) += (char) c; if ( c == '>' ) { // All is well. return; } } } #endif const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) { p = SkipWhiteSpace( p, _encoding ); // Find the beginning, find the end, and look for // the stuff in-between. TiXmlDocument* document = GetDocument(); if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); return 0; } if ( data ) { data->Stamp( p, _encoding ); location = data->Cursor(); } p += 5; version = ""; encoding = ""; standalone = ""; while ( p && *p ) { if ( *p == '>' ) { ++p; return p; } p = SkipWhiteSpace( p, _encoding ); if ( StringEqual( p, "version", true, _encoding ) ) { TiXmlAttribute attrib; p = attrib.Parse( p, data, _encoding ); version = attrib.Value(); } else if ( StringEqual( p, "encoding", true, _encoding ) ) { TiXmlAttribute attrib; p = attrib.Parse( p, data, _encoding ); encoding = attrib.Value(); } else if ( StringEqual( p, "standalone", true, _encoding ) ) { TiXmlAttribute attrib; p = attrib.Parse( p, data, _encoding ); standalone = attrib.Value(); } else { // Read over whatever it is. while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) ++p; } } return 0; } bool TiXmlText::Blank() const { for ( unsigned i=0; i #include #include #include #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include "libgambit/libgambit.h" #include "valnumber.h" BEGIN_EVENT_TABLE(gbtNumberValidator, wxValidator) EVT_CHAR(gbtNumberValidator::OnChar) END_EVENT_TABLE() static bool IsNumeric(const wxString &p_value) { bool seenDigit = false, seenSeparator = false; for (int i = 0; i < (int) p_value.Length(); i++) { if (isdigit(p_value[i])) { seenDigit = true; continue; } else if ((p_value[i] == '.' && !seenSeparator) || (p_value[i] == '/' && !seenSeparator && seenDigit)) { seenSeparator = true; continue; } else if (i == 0 && p_value[i] == '-') { continue; } return false; } if (p_value[p_value.Length() - 1] == '/') { return false; } else { return true; } } //------------------------------------------------------------------------ // class gbtNumberValidator: Member functions //------------------------------------------------------------------------ gbtNumberValidator::gbtNumberValidator(wxString *p_value) : m_stringValue(p_value), m_hasMin(false), m_hasMax(false) { } gbtNumberValidator::gbtNumberValidator(wxString *p_value, const Gambit::Rational &p_minValue) : m_stringValue(p_value), m_hasMin(true), m_hasMax(false), m_minValue(p_minValue) { } gbtNumberValidator::gbtNumberValidator(wxString *p_value, const Gambit::Rational &p_minValue, const Gambit::Rational &p_maxValue) : m_stringValue(p_value), m_hasMin(true), m_hasMax(true), m_minValue(p_minValue), m_maxValue(p_maxValue) { } gbtNumberValidator::gbtNumberValidator(const gbtNumberValidator &p_validator) { Copy(p_validator); } bool gbtNumberValidator::Copy(const gbtNumberValidator &p_validator) { wxValidator::Copy(p_validator); m_stringValue = p_validator.m_stringValue; m_hasMin = p_validator.m_hasMin; m_hasMax = p_validator.m_hasMax; m_minValue = p_validator.m_minValue; m_maxValue = p_validator.m_maxValue; return true; } bool gbtNumberValidator::Validate(wxWindow *p_parent) { if (!m_stringValue) { return false; } wxTextCtrl *control = (wxTextCtrl *) m_validatorWindow; if (!control->IsEnabled()) { return true; } wxString value(control->GetValue()); if (!IsNumeric(value)) { wxMessageBox(_T("The value ") + value + _T(" in ") + m_validatorWindow->GetName() + _T(" is not a valid number."), _("Error"), wxOK | wxICON_EXCLAMATION, p_parent); m_validatorWindow->SetFocus(); return false; } if ((m_hasMin && Gambit::ToNumber((const char *) value.mb_str()) < m_minValue) || (m_hasMax && Gambit::ToNumber((const char *) value.mb_str()) > m_maxValue)) { wxMessageBox(_T("The value ") + value + _T(" in ") + m_validatorWindow->GetName() + _T(" is out of the range [") + wxString(ToText(m_minValue).c_str(), *wxConvCurrent) + _T(", ") + wxString(ToText(m_maxValue).c_str(), *wxConvCurrent) + _T("]."), _("Error"), wxOK | wxICON_EXCLAMATION, p_parent); m_validatorWindow->SetFocus(); return false; } return true; } bool gbtNumberValidator::TransferToWindow(void) { if (!m_stringValue) { return false; } wxTextCtrl *control = (wxTextCtrl *) m_validatorWindow; control->SetValue(*m_stringValue); return true; } bool gbtNumberValidator::TransferFromWindow(void) { if (!m_stringValue) { return false; } wxTextCtrl *control = (wxTextCtrl *) m_validatorWindow; *m_stringValue = control->GetValue(); return TRUE; } void gbtNumberValidator::OnChar(wxKeyEvent &p_event) { if (m_validatorWindow) { int keyCode = (int) p_event.GetKeyCode(); // we don't filter special keys and Delete if (!(keyCode < WXK_SPACE || keyCode == WXK_DELETE || keyCode > WXK_START) && (!isdigit(keyCode) && keyCode != '.' && keyCode != '-' && keyCode != '/')) { if (!wxValidator::IsSilent()) { wxBell(); } return; } wxTextCtrl *control = (wxTextCtrl *) m_validatorWindow; wxString value = control->GetValue(); if ((keyCode == '.' || keyCode == '/') && (value.Find('.') != -1 || value.Find('/') != -1)) { // At most one slash or decimal point is allowed if (!wxValidator::IsSilent()) wxBell(); return; } if (keyCode == '/' && (control->GetInsertionPoint() == 0 || (control->GetInsertionPoint() == 1 && value == wxT("-")))) { // Can't start with a slash if (!wxValidator::IsSilent()) wxBell(); return; } if (keyCode == '-') { // Only permit minus signs at the start of the text long start, end; control->GetSelection(&start, &end); if (start == end) { // No selection; just see if inserting is OK if (control->GetInsertionPoint() != 0) { if (!wxValidator::IsSilent()) wxBell(); return; } } else { // There is a selection; is selection at beginning? if (start != 0) { if (!wxValidator::IsSilent()) wxBell(); return; } } } } p_event.Skip(); } gambit-0.2010.09.01/src/gui/valnumber.h0000644000076500007650000000337611435216101014162 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/gui/valnumber.h // wxValidator specialization to gbtNumber // // 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 VALNUMBER_H #define VALNUMBER_H #include #include "libgambit/libgambit.h" class gbtNumberValidator : public wxValidator { protected: wxString *m_stringValue; bool m_hasMin, m_hasMax; Gambit::Rational m_minValue, m_maxValue; // Event handlers void OnChar(wxKeyEvent &); public: gbtNumberValidator(wxString *); gbtNumberValidator(wxString *, const Gambit::Rational &); gbtNumberValidator(wxString *, const Gambit::Rational &, const Gambit::Rational &); gbtNumberValidator(const gbtNumberValidator &); virtual ~gbtNumberValidator() { } virtual wxObject *Clone(void) const { return new gbtNumberValidator(*this); } bool Copy(const gbtNumberValidator &); virtual bool Validate(wxWindow *parent); virtual bool TransferToWindow(void); virtual bool TransferFromWindow(void); DECLARE_EVENT_TABLE() }; #endif // VALNUMBER_H gambit-0.2010.09.01/src/labenski/0000777000076500007650000000000011441457127013111 500000000000000gambit-0.2010.09.01/src/labenski/art/0000777000076500007650000000000011441457127013677 500000000000000gambit-0.2010.09.01/src/labenski/art/grab.xpm0000644000076500007650000000066111350032206015241 00000000000000/* XPM */ static const char *grab_xpm[]={ "16 16 4 1", ". c None", "a c #000000", "# c #000040", "b c #ffffff", "................", "................", "................", "....#aa##a##....", "...abbabbabbaa..", "...abbabbabbab#.", ".aa.abbbbbbbabba", "abbaabbbbbbbbbba", "abbbabbbbbbbbba.", ".abbbbbbbbbbbba.", "..abbbbbbbbbbba.", "..abbbbbbbbbba..", "...abbbbbbbbba..", "....abbbbbbba...", ".....abbbbbba...", ".....abbbbbba..."}; gambit-0.2010.09.01/src/labenski/art/hand.xpm0000644000076500007650000000064211350032206015237 00000000000000/* XPM */ static const char *hand_xpm[] = { "16 16 3 1", " c None", "a c Black", "c c #FFFFFF", " aa ", " aa accaaa ", " accaaccacca ", " accaaccacca a ", " accaccaccaaca", " accaccaccacca", " aa acccccccacca", "accaacccccccccca", "acccaccccccccca ", " acccccccccccca ", " accccccccccca ", " acccccccccca ", " accccccccca ", " accccccca ", " acccccca ", " acccccca "}; gambit-0.2010.09.01/src/labenski/art/ledgreen.xpm0000644000076500007650000000414511350032206016114 00000000000000/* XPM */ static char * ledgreen_xpm[] = { "15 15 99 2", " c None", ". c #012B00", "+ c #013402", "@ c #013C04", "# c #012500", "$ c #015209", "% c #015609", "& c #016E0E", "* c #01700E", "= c #01660B", "- c #01620D", "; c #55983D", "> c #014A0F", ", c #012100", "' c #018414", ") c #018C15", "! c #019817", "~ c #018614", "{ c #01680D", "] c #014C06", "^ c #01720F", "/ c #018E15", "( c #01A018", "_ c #01BC20", ": c #17B21E", "< c #25AC1F", "[ c #29A829", "} c #019E17", "| c #013602", "1 c #01660D", "2 c #018814", "3 c #01A71D", "4 c #01BE20", "5 c #1CBB20", "6 c #57DE15", "7 c #9EF330", "8 c #4CCF18", "9 c #15A61B", "0 c #019216", "a c #01640D", "b c #012801", "c c #014606", "d c #01981A", "e c #01B41F", "f c #02CB23", "g c #27CB1A", "h c #87F116", "i c #FFFFFF", "j c #A6F534", "k c #29B01F", "l c #019C17", "m c #013E04", "n c #01740F", "o c #019E1B", "p c #01BA20", "q c #02CD23", "r c #19CC1D", "s c #53E712", "t c #A9F645", "u c #77EF2E", "v c #1AB51E", "w c #014A06", "x c #017C13", "y c #01A01B", "z c #01C822", "A c #02DB26", "B c #19DA19", "C c #2DD617", "D c #30D619", "E c #01C622", "F c #01780F", "G c #014608", "H c #02B11F", "I c #01C221", "J c #2DE436", "K c #02CF23", "L c #02D324", "M c #02AD1E", "N c #012601", "O c #015A0C", "P c #017E13", "Q c #01C021", "R c #02AF1E", "S c #019C1B", "T c #015409", "U c #01A61C", "V c #02A91D", "W c #019A17", "X c #016A0E", "Y c #014E08", "Z c #017812", "` c #012700", " . c #014406", ".. c #014A08", "+. c #015809", "@. c #01600C", "#. c #012C01", "$. c #013804", "%. c #014004", " . + @ + . ", " # $ % & * = - ; > ", " , $ * ' ) ! ! ~ { ] , ", " $ ^ / ( _ : < [ } * ] ", " | 1 2 3 4 5 6 7 8 9 0 a b ", " c * d e f g h i j k l & m ", " $ n o p q r s t u v } ^ w ", " $ x y p z A B C D E d F w ", " G ^ d H I J K L E M 0 * m ", " N O P y H Q Q p R S ' T N ", " c * ) y U V V W 2 X Y ", " # c ^ Z ) / ' P - Y # ", " ` ...+.@.+.T c ` ", " #.$.%.$.#. ", " "}; gambit-0.2010.09.01/src/labenski/art/ledgrey.xpm0000644000076500007650000000334111350032206015757 00000000000000/* XPM */ static char *ledgrey_xpm[]={ "15 15 75 2", "Qt c None", ".# c #000000", ".x c #151515", ".a c #161616", "#a c #171717", "#f c #191919", "#i c #1e1e1e", ".G c #202020", ".q c #2b2b2b", ".H c #2c2c2c", ".h c #2d2d2d", ".8 c #2e2e2e", "#d c #2f2f2f", "#e c #323232", ".b c #343434", ".S c #363636", ".0 c #373737", ".g c #383838", ".p c #3a3a3a", ".f c #3b3b3b", ".R c #3c3c3c", "#h c #3d3d3d", ".y c #404040", "#b c #424242", ".c c #444444", ".i c #464646", ".Z c #474747", ".e c #484848", ".1 c #494949", ".d c #4a4a4a", "#g c #4b4b4b", ".z c #4e4e4e", ".j c #4f4f4f", ".o c #505050", ".I c #515151", ".9 c #525252", ".w c #535353", ".k c #545454", ".Q c #555555", ".n c #565656", ".l c #575757", ".J c #595959", ".m c #5a5a5a", "#c c #5b5b5b", ".7 c #5c5c5c", ".A c #5d5d5d", ".v c #5e5e5e", ".T c #5f5f5f", ".r c #606060", ".K c #616161", "## c #626262", ".6 c #636363", ".2 c #646464", ".s c #676767", ".F c #686868", ".B c #696969", ".Y c #6a6a6a", ".U c #6b6b6b", ".t c #6d6d6d", ".P c #6e6e6e", ".L c #6f6f6f", ".3 c #727272", ".4 c #747474", ".u c #757575", ".5 c #767676", ".E c #7e7e7e", ".V c #7f7f7f", "#. c #808080", ".C c #818181", ".M c #919191", ".X c #959595", ".D c #a1a1a1", ".O c #a4a4a4", ".W c #a8a8a8", ".N c #ffffff", "QtQtQtQtQt.#.#.#.#.#QtQtQtQtQt", "QtQtQt.#.a.b.c.d.e.f.g.#QtQtQt", "QtQt.#.h.i.j.k.l.m.n.o.p.#QtQt", "QtQt.q.i.o.l.r.s.t.u.v.w.fQtQt", "Qt.x.y.z.n.A.B.C.D.E.F.m.j.GQt", "Qt.H.i.I.J.K.L.M.N.O.P.v.Q.RQt", "Qt.S.e.k.m.T.U.V.W.X.Y.A.n.ZQt", "Qt.0.1.w.m.v.2.3.4.5.6.7.Q.ZQt", "Qt.8.i.9.J.A#..r##.r.A.m.w.RQt", "Qt#a#b.z.n.m.A.v.v.A#c.l.z.GQt", "QtQt#d.Z.o.n.J.m.m.J.n.o.pQtQt", "QtQt.##e.e.j.w.Q.Q.9.z.p.#QtQt", "QtQtQt.##f.g.i#g.e#h#i.#QtQtQt", "QtQtQtQtQt.#.#.#.#.#QtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt"}; gambit-0.2010.09.01/src/labenski/doc/0000777000076500007650000000000011441457127013656 500000000000000gambit-0.2010.09.01/src/labenski/doc/README-plotctrl.txt0000644000076500007650000000617011350032206017117 00000000000000README.txt for wxPlotLib ------------------------------------------------------------------------------- wxPlotLib is 2D plot window widget, data/function curve classes, and some data processing functions. It has NOTHING to do with the wxWidgets's wxPlot, except that it was originally based on it. I doubt that it contains more than a line or two of identical code anymore. ------------------------------------------------------------------------------- Written by John Labenski, except as noted below and in headers Copyright 2003, John Labenski, except as noted below and in headers License wxWindows license, except as noted below and in headers. fourier.h/c wxPlotLib includes code for FFT from Don Cross (fourier.h/c) that is to the best of my knowledge from the book "Numerical Recipes in FORTRAN" and is in the public domain. fparser.h/hh/cpp: The function parser library was written by 'Warp', the file fparser.txt explains the license. Basicly the code is free to use for commercial and noncommercial programs, but the original author makes some simple requests if used Commercially. lm_lsqr.h/cpp The Levenberg-Marquart nonlinear least squares 2-D curve fitting class is from the public domain Fortran version of Argonne National Laboratories MINPACK, written in C by Steve Moshier. ------------------------------------------------------------------------------- Depends: wxWidgets - >= 2.5.x, untested in 2.4.x, but would probably work. wxThings - it uses range, medsort, genergdi. ------------------------------------------------------------------------------- Provides: plotwin.h wxPlotWin: a 2D plotting widget, mainly for interactive plotting. It does not generate pie charts or other "fun" plots, just 2D x-y plots. The mouse can mainpulate the display in real time. It's all about being interactive. plotcurve.h wxPlotCurve: a base class for a curve, given an x value return a y. You have to subclass this to have it do anything. wxPlotFunction: a function curve, you send in a wxString "2*sin(x)" and then call GetY(x) to get the value. This is based on the fparser library, please read src/fparser.txt for details. wxPlotData: A data curve (like wxImage) that stores x,y and yImag values. It can do all sorts of stuff, Load/Save, FFT, FFT filter, sort, shift... lm_lsqr.h LM_LeastSquare: a Levenberg-Marquart nonlinear least squares 2-D curve fitting class for use with wxPlotFunction and wxPlotData. From public domain Fortran version of Argonne National Laboratories MINPACK, written in C by Steve Moshier and subsequently turned into a C++ class by John Labenski. Compilation: Only a Makefile for *unix using wxGTK currently. It generates a library in the wxWidgets directory specified by the output of $wx-config --prefix. I have a define in plotwin.cpp called wxPLOT_FAST_GRAPHICS that tries to draw in GTK and MSW using native methods for higher perfomance. If you don't wish to use that then just rem out #define wxPLOT_FAST_GRAPHICS and you'll use wxWidgets dc rendering code. If you have problems compiling in GTK take a look at the Makefile, I try to guess what version of gtk you're using 1.2x or 2.x, search for GTK_CFLAGS. gambit-0.2010.09.01/src/labenski/doc/README-sheet.txt0000644000076500007650000004644511350032206016375 00000000000000README.txt for wxSheet - a wxGrid type spreadsheet widget Copyright : 2004, John Labenski and others (see headers) License : wxWidgets license. This library/program is free software; you can redistribute it and/or modify it under the terms of the wxWidgets Licence; either version 3 of the Licence, or (at your option) any later version. 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 wxWidgets Licence for more details. If you use this program/library and find any bugs or have added any features that you feel may be generally useful, please feel free to contact me by e-mail at jrl1[at]lehigh[dot]edu. =============================================================================== Summary: wxSheet is a spreadsheet type grid widget for the wxWidgets GUI library. The wxSheet code is based on the wxWidget's wxGrid class and is, for the most part, a complete rewrite, almost every function has been tweaked. It is not backwards compatible, but operates and is logically similiar. Many of the functions have the same names and you can expect them to perform a similiar task, but the parameters may be different. The reason for creating a completely separate grid implementation is to allow far more control over the different aspects of the operation either though subclassing or intercepting events. You will find documentation included in the header files with the member functions ordered by function. You can of course look under the hood, at the cpp files, to fully understand what each function does. I welcome any changes or interesting ideas you may have for improvement. The current version suits my needs in terms of flexibility, but I only use a grid widget in a limited capacity. =============================================================================== Provides: wxSheet - the grid window itself and the row/col/corner label windows and the independent scrollbars. wxSheetSplitter - a four way splitter window for the wxSheet, it can split horizontally and/or vertically. Splitting works by setting wxSheet::EnableSplitVertically/Horizontally which will draw a little button next to the scrollbars like Excel/OOCalc for example. The sheet checks for the mouse dragging in the buttons and sends an event. The sheet DOES NOT split itself, but if the parent is a wxSheetSplitter it gets the event, grabs the mouse, draws the splitting line, and (un)splits by appropriately creating/deleting a sheet and showing/hiding the label windows and scrollbars. wxSheetTable - the base class for a data container to provide values, attributes, and spanned cells for wxSheet cells wxSheetStringArray = wxGridStringArray - a 2D wxString wxArray (uses grid's if WXUSE_GRID) wxPairArrayIntSheetString - pair array of (int, string) wxArrayPairArrayIntSheetString - array of pairs of (int, string) wxPairArrayIntPairArraySheetString - pair array [int, array pair (int, string)] wxSheetValueProviderBase - a base class for a value provider for the table wxSheetValueProviderString - a wxSheetStringArray (eg. 2D array of wxStrings) data provider for the table. Good for mostly full sheets, though it is optimised to only fill the arrays as necessary. wxSheetValueProviderSparseString - a wxPairArrayIntPairArraySheetString value provider class for probably less than 2/3 - 3/4 full sheets wxSheetCellAttr - an attribute for the grid/row/col/corner label cells. They provide colours, text alignment, renders, editors... They are chained together so that whatever values are unset for a particular attribute are retrieved from the default attribute. wxNullSheetCellAttr - a const uncreated attribute wxSheetCellAttrProvider - a container for storing non default attributes for the grid and label cells. wxSheetCoords - row, col coords for accessing cells wxSheetBlock - a rectangular block of cells wxSheetSelection - a dumb selection container that stores and array of sorted and nonoverlapping wxSheetBlocks. wxSheetSelectionIterator - an iterator for traversing the selection from top to bottom or in the reverse direction. wxSheetCellEditor - a container for a variety of editors to use with the wxSheet. The ref counted data actually contains the editor code so that they can easily passed around. Please see sheetctl.h for a list. wxSheetCellRenderer - a container for a variety of renderers to use with the wxSheet. The ref counted data actually contains the renderer code so that they can easily passed around. Please see sheetctl.h for a list. =============================================================================== Additional Features: Faster rendering, about %10-%20 faster, but your mileage may vary. GTK2 for example is very slow at rendering antialiased text so that the speedup from the more optimized redrawing is marginalized by the time actually spent drawing. wxSheetCellAttr/Renderer/Editors are wxObject refed so it's simple to use No more Inc/DecRef, treat them just like wxBitmaps, wxPens, etc... Added OnKeyDown and OnChar for editors so they can be more interactive Text editor expands as you type by full cells like other spreadsheets TextRenderer draws a little arrow to show that the text is clipped Smooth scrolling for selection out of window Attributes for all windows, grid row/col/corner labels Renderers for all windows, grid row/col/corner labels Editors for all windows, grid row/col/corner labels or not. The default attributes for the labels are set readonly by default. Note: if you can edit the row/col/corner labels then a single click doesn't select the row/col/everything. You must drag it a pixel or two. This is a reasonable tradeoff since otherwise for a double click to edit you select then deselect which looks bad. If you can't edit it, then single click sels. Adds wxSheetStringSparseTable that is not just a huge double array. Uses binary search for lookup, ideal for less than half full grids. DECLARE_PAIRED_DATA_ARRAYS used for key/value pairs that need to be sorted These are used for faster Attr lookup and sparse string table Added selecting for page up/down Grid lines drawn horizontal and/or vertical or none Additional events RANGE_SELECTING/SELECTED so you can block it AltDown + Arrows resizes cell like OOffice Independent scrollbars, you can have none, both, as needed, or either. Events use IDs like other wxWidget events Left Double click begins editing as well as slow click. wxSheetBlock(row, col, height, width) a rectangular block of cell immensely simplifies logic. Moved the cell spanning (was wxGrid::SetCellSize) code out of the attributes for faster lookup. Rudimentary copy and paste for strings only, not default behavior and you must call the functions yourself. wxSheetSplitter window, a window that given a single child wxSheet can split the view into four panes. You can have complete control over the selection mechanism, override only IsSelection, IsCell/Row/ColSelected, (De)SelectBlock, and ClearSelection. You can have complete control over the attributes, override only CanHaveAttributes, GetOrCreateAttr, GetAttr, and SetAttr. (also works as the wxGrid does by passing to the table where you can override it there and to the attr provider) You can have complete control over the cell values in the grid, override only Get/SetCellValue. (also works as the wxGrid by passing to the table where you can override it there as well) ------------------------------------------------------------------------------- Things that were "fixed" (you may disagree however) MoveCellBlock so that it matches OpenOffice by staying on cells w/ values Right drag in grid does nothing Selecting w/ keyboard moves cursor cell Numpad arrows work to move mouse using EVT_CHAR Events use IDs For selection type rows/cols don't allow sel on opposite col/row labels. ------------------------------------------------------------------------------- The sheet consists of 4 individual windows each is accessed with coords using the semantics below. Functions named Get/SetGridXXX(wxSheetCoords, ...) apply to the grid cells, otherwise the function uses the -1 notation to access the label cells. There are a slew of static bool IsGrid/RowLabel/ColLabel/CornerLabelCell(wxSheetCoords) functions to genericly determine what type of cell it is as well as bool ContainsGrid/RowLabel/ColLabelCell(wxSheetCoords) to determine if the coords are valid for the current grid size. While this may seem slightly more complicated, it makes the code quite a bit more readable. ########################################################################## # corner label # col label | col label | | # # (-1, -1) # (-1, 0) | (-1, 1) | ... | GetNumberCols() - 1 # ########################################################################## # row label # grid cell | grid cell | | # # (0, -1) # (0, 0) | (0, 1) | ... | # #--------------#---------------------------------------------------------# # row label # grid cell | grid cell | | # # (1, -1) # (1, 0) | (1, 1) | ... | # #--------------#---------------------------------------------------------# # # | | | # # ... # ... | ... | ... | # #--------------#---------------------------------------------------------# # # | | | GetNumberRows() - 1 # # GetNumberRows() - 1 | GetNumberCols() - 1 # ########################################################################## =============================================================================== Differences to wxGrid wxSheet::Foo( row, col ) -> Foo( const wxSheetCoords& coords ) wxSheet::GetRow/ColSize -> GetRowHeight/Width - size is ambiguous wxSheet::Get/SetDefaultCol/RowSize -> Get/SetDefaultCol/RowHeight/Width - size is ambiguous wxSheet::Get/SetHighlightXXX -> Get/SetCursorCellHighlightXXX it's for the cursor wxSheet::HighlightBlock -> HighlightSelectingBlock that's what it really does wxSheet::IsVisible -> IsCellVisible wxSheet::Set/GetCaptureWindow added a locker for captured window, never access m_winCapture wxSheet::GetAttr/SetAttr/GetOrCreateAttr all the helper Get/SetXXXAttr call these uses -1 notation for label cell wxSheet::Get/SetCellThis/That -> Get/SetAttr/This/That these function can actually get specific values for specific attributes, ie. for a cell/row/col attr, of course you must have set one previously. The default is like the wxGrid, just any type of attr value you can. wxSheet & wxSheetCellAttr Get/SetAlignment uses single int, no point in horiz and vert since aligments are non intersecting enums DrawTextRectangle only takes one alignment wxSheet & wxSheetAttr::IsReadOnly -> GetReadOnly everything else is GetXXX wxSheet Editing redone. Have m_cellEditor, m_cellEditorCoords to get later More wxCHECK stuff to ensure that you're not arbitrarily calling editor functions since it can be touchy. wxSheet::GetCellSize -> GetCellSpan wxSheet::GetCellSize actually gets the size of the cell as wxSize wxSheet::GetCellSpan, GetCellBlock, GetCellOwner for cell spanning this is implemented in the grid using a wxSheetSelection. It is considerably cleaner than the wxGrid attribute method since it only stores a single block for a spanned cell. wxSheet::XToCol/YToRow(val, clipToMinMax) -> removed internalXToCol/YToRow Redrawing reworked, more functions for simple refreshes so that the code in different functions need only call a single redraw function wxSheet::MovePageUp/Down -> MoveCursorUp/DownPage to match the other MoveCursorXXX wxSheet::DoMoveXXX simplier functions to implement these functions and reduce the amount of duplicate code. wxSheet::IsSelected(cell) -> IsCellSelected (match other cell functions) wxSheet::IsSelection -> HasSelection (bad grammar) ------------------------------------------------------------------------------- wxSheetCellEditor and wxSheetCellRenderer are wxObject refed classes The actual implementation is in the ref data so they're passed as const &obj wxSheetCellEditor::Create -> CreateEditor say what it does Added wxNullSheetCellRenderer, wxNullSheetCellEditor Added OnKeyDown and OnChar for interactive editors Added GetValue, GetInitValue so that you can get the current or initial value wxSheetCellEditor::PaintBackground takes same parameters as wxSheetCellRenderer::Draw ------------------------------------------------------------------------------- wxSheetCellCoords -> wxSheetCoords other name is too long, members PUBLIC! wxSheetCoords added useful operators to make it complete wxSheetNoCellCoords -> wxNullSheetCoords matches other wxWindows empty items Added wxSheetBlock a rectangular selection of cells blocks are similiar to wxRects and implement similiar functionality ------------------------------------------------------------------------------- wxSheetTableMessage::GetPosition/RowsCols, not mysterious CommandInt1/2 creation of messages are now different since com1 = pos, com2 = rows/cols in wxGrid the com1 and com2 took different meaning for different msgs wxSheetTableBase::SendInsert/Append/Delete/Rows/ColsTableMsg to send appropriate wxSheetTableMessage since everyone had to duplicate the code used in the wxSheetStringTable anyway. wxSheetTableBase::GetFirstNonEmptyColToLeft, render helper get next col to left that's not empty or -1, (if you can't do this just return col-1, base does this) wxSheetStringTable is like the wxGridStringTable wxSheetStringSparseTable uses wxPairArrayIntPairArraySheetString which is an array of strings and ints. Binary search lookup. Size of strings table is now approximately (size of strings) + (1 int per string) + (1 int per row). ------------------------------------------------------------------------------- wxSheetEvent is parent for the other events since they're basicly the same wxSheetEvent doesn't take a million different items in constructor add SetKeyDownMousePos( wxEvent* ) to get vals from mouse/key evt. EVT_SHEET_RANGE_SELECT broke into SELECTING and SELECTED, can Veto it EVT_SHEET_SELECT_CELL broke into SELECTING and SELECTED EVT_SHEET_CELL_LEFT/RIGHT_CLICK -> EVT_SHEET_CELL_LEFT/RIGHT_DOWN Added EVT_SHEET_CELL_LEFT/RIGHT_UP EVT_SHEET_EDITOR_SHOWN/HIDDEN -> ENABLED/DISABLED since the events didn't match what they were named after Events take IDs now Removed wxSheetSizeEvent - there is no point for it since wxSheetEvent contains all necessary information ------------------------------------------------------------------------------- wxSheetCellAttr - wxObject ref counted, just like wxBitmap etc... wxSheetNoCellAttr -> wxNullSheetCellAttr matches other wxWindows empty items wxSheetCellAttr::IsReadOnly = HasReadWriteMode everything else is HasXXX wxSheetCellAttr::Get/SetAlignment single alignment, no need for horiz & vert Added Get/Set/HasOrientation for wxHORIZONTAL, wxVERTICAL wxSheetCellAttr::GetSize removed, this is now in wxSheet and called Span All enum/int values are stored in single int so it's smaller ------------------------------------------------------------------------------- wxSheetCellAttrProvider::Get/SetAttr - Get/SetCellAttr and param order matches sheet wxSheetCellAttrProvider::UpdateAttrRows/Cols -> UpdateRows/Cols wxSheetCellAttrData & wxSheetRowOrColAttrData - use binary search ------------------------------------------------------------------------------- wxSheetSelection is completely different, it just selects blocks of cells for full rows/cols it selects to # of rows/cols as opposed to rows/cols-1. You can use wxSheetSelection::SetBoundingBlock to trim it back to grid size if you desire. The selection is a dumb container and is used for other purposes, cell span, and redrawing for example. You can freely modify the selection! Just repaint when done. You can completely override the selection. wxSheetSelection type is stored in the wxSheet since the selection does nothing with it anyway. Added wxSheetSelectionIterator that can iterate forwards from top left by rows then cols or backwards from bottom left by cols then rows. The selection is not preserved when switching selection type or inserting/deleting rows/cols. Ideally you should send slews of confusing (de)selection events and so I think it's best to just clear it. if you click anywhere it gets cleared so the selection is not that precious anyway. There is no technical reason why this couldn't be implemented however. Added EVT_SHEET_RANGE_SELECTING(ED), you can block the SELECTING =============================================================================== List of files include/wx/sheet/ sheet.h - the main header file for the wxSheet component sheetctl.h - the header for the renderers and editors controls sheetsel.h - the header for the wxSheetSelection, selection mechanism also contains wxSheetCoords, wxSheetBlock. sheetspt.h - header for wxSheetSplitter wx24defs.h - provides backwards compatibility for code written for wxWidgets >= 2.5 to compile in wxWidgets 2.4.x pairarr.h - defines a a macro for arbitrary wxArrays of key, value pairs src/ sheet.cpp - the main source file for the wxSheet sheetctl.cpp - the source file for the renderers and editors sheetsel.cpp - the source file for the wxSheetSelection mechanism sheetspt.cpp - the source file for the wxSheetSplitter Makefile - makefile for gcc, relies on wx-config in your path generates a library in your `wx-config --prefix`/lib dir sheetlib_wx24.dsp - project file for lib, Visual Studio for wxWidgets 2.4.x sheetlib_wx25.dsp - project file for lib, Visual Studio for wxWidgets 2.5.x samples/sheet sheetdemo.h/cpp - a sample program based on wxWidget's griddemo sample Makefile - makefile for gcc, relies on wx-config in your path sheetdemo_wx24.dsp - project file for Visual Studio for wxWidgets 2.4.x sheetdemo_wx25.dsp - project file for Visual Studio for wxWidgets 2.5.x =============================================================================== Compliation and use: wxSheet has been tested in wxMSW and wxGTK using wxWidgets 2.4.2 and 2.5. It should be able to run on any platform that the wxGrid does. There may however be some "off by one" sizing errors for the editors since calls to wxWindow::SetSize may not work as expected. I tried to preserve the different sizing #ifdefs as used in the wxGrid, but sometimes they were quite baffling and should be properly cleaned up when the can be tested. I welcome any fixes for different platforms or versions of wxWindows than the ones I use (GTK, MSW, 2.4.2, but mostly CVS head). There is a Makefile for building a library and the sample sheetdemo (griddemo) program for Unix systems and a MSVS project file for the sample. You can build it as a library or just include the source files in your program. It is an independent widget and doesn't rely on the wxGrid, though it does use the hash map and string array defined in grid.h. gambit-0.2010.09.01/src/labenski/doc/README-wxthings.txt0000644000076500007650000000777011350032206017136 00000000000000readme.txt for wxThings block.h/cpp - wxBlockInt is a wxGridSelection type class based on wxRect2DInt to store selected 2-D rectangular areas. It knows how to combine with other blocks. wxBlockIntSelection consists of an array of wxBlockInts. It minimizes them if possible so they never overlap and can sort them from each corner. range.h/cpp - wxRangeInt min/max class for storing a 1-D range of values and knows how to combine with other wxRangeInts. wxRangeIntSelection contains an array of wxRangeInts and minimizes them if possible, they never overlap, and always stay in order from low to high. wxRangeDbl and wxRangeDblSelection is the same, but for double valued ranges. filebrws.h/cpp & filebrws_icons_wdr.h - wxFileBrowser is an Explorer type wiget with a tree view of dirs and a list/icon view of files with optional image preview. Not fully completed, but works. You need wxWidgets CVS HEAD, >= 2.5. geometry.h/cpp - wxCircleInt, wxCircleDouble, wxRay2DDouble, wxRay2DInt wxEllipseInt, wxEllipseDouble, etc... not fully finished. genergdi.h/cpp - wxGenericColour, wxGenericPen. A color and pen that store the values themselves and have identical functions as wxColour and wxPen. They do not require a GUI and are suited to instances where you may want to store a considerable number of different ones. optvalue.h/cpp - wxOptionValue class contains a string type and two arrays of options and values. It works on the same format as the wxFileConfig class and can load and save to a string/stream. [opt valuetype] option1 = value1 option2 = value2 spinctld.h/cpp - wxSpinCtrlDbl is a drop in replacement for a wxSpinCtrl that uses doubles with extra features such as, ESC sets 'default' value, SPACE sets the control to the last valid value, using SHIFT,CTRL,ALT work as multipliers for the increment when using the arrow keys or PgUp/PgDn. It can display in decimal or exponential format and can 'guess' the number of appropriate digits from the increment or you can set it yourself. toggle.h/cpp - wxCustomButton a toggle type button that can act like a wxButton, wxBitmapButton, wxToggleButton (w/ image or not). It is a drop in replacement for each of these controls. It can display the icon along with the text (on any side) and can create a "greyed" out image to use when the button is disabled. It can also do weird things like act like a button on a single click and a toggle on double click. Note: to differentiate between single and double clicks a timer is used, if you want it to be just a regular toggle button I suggest you remove the timer code. dropdown.h/cpp - DropDownBase a base class for a combobox type widget. It manages a wxPopupTransientWindow as a child. See wxBitmapComboBox. bmpcombo.h/cpp - wxBitmapComboBox is a wxComboBox widget for bitmaps. You Append some bitmaps either individually or with an array. Since bitmaps are refed this should be a fast process and you don't have to keep them around. It acts just like a wxComboBox otherwise, sends a EVT_COMBOBOX when selections are made with either the mouse on the pulldown list or by pressing the up/down arrows. There is a problem in wxGTK when this is used in a modal dialog, the mouse events do not go to the popup transient window's child and so you cannot select items, the keys still work though. menubtn.h/cpp - wxMenuButton is a button with a label and/or bitmap and a combobox type dropbown to the right of it. You can attach a menu to it and the dropdown button shows the menu. If you click on the label button the next wxITEM_RADIO in the attached menu is selected in a round robin fashion. If there are no radio items then the label button does nothing. medsort.h - Various Public Domain median finding or sorting macros, a quick select routine, wirth's kth smallest, torben median, pixel qsort, and a pixel qsort that sorts two arrays together (only one is used for the comparison, the other just follows). They can be DECLARED in headers, DEFINED in you cpp files, or just used inline. Since they're macros you can set if they're for arrays of doubles, ints, chars... gambit-0.2010.09.01/src/labenski/include/0000777000076500007650000000000011441457111014525 500000000000000gambit-0.2010.09.01/src/labenski/include/wx/0000777000076500007650000000000011441457114015166 500000000000000gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/0000777000076500007650000000000011441457114017031 500000000000000gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/fourier.h0000644000076500007650000000603311350032206020561 00000000000000/*============================================================================ fourier.h - Don Cross The file FFT.ZIP contains C source code for performing Discrete Fast Fourier Transforms (DFFTs) and inverse DFFTs. Please see fouier.txt which was the readme.txt that Don Cross provided. This source code is public domain. Use at your own risk. For more information, point your web browser at: (dead link) http://www.intersrv.com/~dcross/fft.html Contains definitions for doing Fourier transforms and inverse Fourier transforms. 2003 [John Labenski] Merged fourierd.c (double), fourierf.c (float), and fftmisc.c into fourier.c for simplicity. ============================================================================*/ #ifndef _FOURIER_FFT_H_ #define _FOURIER_FFT_H_ #ifdef __cplusplus extern "C" { #endif /* ** fft() computes the Fourier transform or inverse transform ** of the complex inputs to produce the complex outputs. ** The number of samples must be a power of two to do the ** recursive decomposition of the FFT algorithm. ** See Chapter 12 of "Numerical Recipes in FORTRAN" by ** Press, Teukolsky, Vetterling, and Flannery, ** Cambridge University Press. ** ** returns 1 on success or 0 on failure ** ** Notes: If you pass ImaginaryIn = NULL, this function will "pretend" ** that it is an array of all zeroes. This is convenient for ** transforming digital samples of real number data without ** wasting memory. */ int fft_double ( unsigned NumSamples, /* must be a power of 2 */ int InverseTransform, /* 0=forward FFT, 1=inverse FFT */ double *RealIn, /* array of input's real samples */ double *ImaginaryIn, /* array of input's imag samples */ double *RealOut, /* array of output's reals */ double *ImaginaryOut ); /* array of output's imaginaries */ int fft_float ( unsigned NumSamples, /* must be a power of 2 */ int InverseTransform, /* 0=forward FFT, 1=inverse FFT */ float *RealIn, /* array of input's real samples */ float *ImaginaryIn, /* array of input's imag samples */ float *RealOut, /* array of output's reals */ float *ImaginaryOut ); /* array of output's imaginaries */ /* IsPowerOfTwo returns 1 if x is a power of two or 0 if not */ int IsPowerOfTwo ( unsigned x ); /* NumberOfBitsNeeded returns the number of bits to make the number, 2^n */ unsigned NumberOfBitsNeeded ( unsigned PowerOfTwo ); unsigned ReverseBits ( unsigned index, unsigned NumBits ); /* ** The following function returns an "abstract frequency" of a ** given index into a buffer with a given number of frequency samples. ** Multiply return value by sampling rate to get frequency expressed in Hz. */ double Index_to_frequency ( unsigned NumSamples, unsigned Index ); #ifdef __cplusplus } #endif #endif // _FOURIER_FFT_H_ /*--- end of file fourier.h ---*/ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/fparser.h0000644000076500007650000001222611350032206020551 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: fparser.h // Purpose: wxFunctionParser - a thin wrapper around FunctionParser // Author: John Labenski, Warp, please see fparser.hh/cpp/txt // Modified by: // Created: 6/5/2004 // Copyright: (c) John Labenski, Juha Nieminen, Joel Yliluoma // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// /***************************************************************************\ |* Function parser v2.7 by Warp *| |* ---------------------------- *| |* Parses and evaluates the given function with the given variable values. *| |* *| \***************************************************************************/ #ifndef ONCE_wxFPARSER_H_ #define ONCE_wxFPARSER_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "fparser.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif #include "wx/plotctrl/plotdefs.h" class WXDLLEXPORT wxString; class FunctionParser; //----------------------------------------------------------------------------- // wxFunctionParser usage (see fparser.txt for details) // // After creating call Parse(wxT("x*sin(x)+x/2.8"), wxT("x")) // see available funtions are listed in fparser.txt // "x" is the var or a comma separated list or vars "x,y,z" // // ex. Parse("x*sin(x)+x/2.8+y", "x,y") double f, vars[2]; f = Eval(&vars) // // Parse() returns -1 if ok or the position in the function string where // an error occured, it can also return func.size() if vars are bad // ErrorMsg() returns a human readable message about the error or wxEmptyString // EvalError() returns -1 if no error or an index into the internal error message strings // Eval() returns the f(x,y,...) value, must pass in exactly the same number // elements as you had characters in Parse(func, -> vars <- ) //----------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // wxFunctionParser - a thin wrapper around FunctionParser // // It converts wxString to std::string (for unicode) and isolates the std:: // warnings that MSVC 6 generates from it's own headers. // Additionally, the original fparser.hh and fparser.cpp files do not require // any modification other than adding some code. // ---------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxFunctionParser { public: enum ParseErrorType { SYNTAX_ERROR=0, MISM_PARENTH, MISSING_PARENTH, EMPTY_PARENTH, EXPECT_OPERATOR, OUT_OF_MEMORY, UNEXPECTED_ERROR, INVALID_VARS, ILL_PARAMS_AMOUNT, PREMATURE_EOS, EXPECT_PARENTH_FUNC, FP_NO_ERROR }; wxFunctionParser(); // Copy constructor and assignment operator (implemented using the // copy-on-write technique for efficiency): wxFunctionParser(const wxFunctionParser&); virtual ~wxFunctionParser(); // Parse the function string and a comma delimited list of the variables // in the function. func = "sin(x) + 2*t*x", vars = "x,t" int Parse(const wxString& Function, const wxString& Vars, bool useDegrees = false); // Get a readable error message if error after a call to parse or empty string wxString ErrorMsg() const; // Get the wxFunctionParser::ParseErrorType error id ParseErrorType GetParseErrorType() const; // Evaluate the function (must have called Parse first) where vars is an // array of the variable values to use. double Eval(const double* Vars); // Not really sure - some sort of error flag? int EvalError() const; // Add a constant to the function parser bool AddConstant(const wxString& name, double value); // Function type that can be added to the parser typedef double (*FunctionPtr)(const double*); // Add a function to the parser bool AddFunction(const wxString& name, FunctionPtr, unsigned paramsAmount); bool AddFunction(const wxString& name, wxFunctionParser&); // Try to optimize the parser, use after sucessful call to Parse void Optimize(); // Ok is true after a sucessful call to Parse bool Ok() const { return m_ok; } // Get the number of comma delimited variables sent to Parse int GetNumberVariables() const; // Get the function string sent to Parse wxString GetFunctionString() const { return m_function; } // Get the variable string sent to Parse wxString GetVariableString() const { return m_variables; } // Get one of the variable names from the string sent to Parse wxString GetVariableName(size_t n) const; // Was this parsed using degrees bool GetUseDegrees() const; // operators wxFunctionParser& operator=(const wxFunctionParser&); // implementation FunctionParser* GetFunctionParser() const { return m_functionParser; } protected: FunctionParser *m_functionParser; wxString m_function, m_variables; bool m_ok; }; #endif // ONCE_wxFPARSER_H_ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/lm_lsqr.h0000644000076500007650000002142711350032206020563 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: lm_lsqr.h // Purpose: Levenberg-Marquart nonlinear least squares 2-D curve fitting // Author: John Labenski, mostly others (see below) // Modified by: // Created: 6/5/2002 // Copyright: (c) John Labenski, mostly others (see below) // Licence: Public domain ///////////////////////////////////////////////////////////////////////////// /* * Solves or minimizes the sum of squares of m nonlinear * functions of n variables. * * From public domain Fortran version * of Argonne National Laboratories MINPACK * * argonne national laboratory. minpack project. march 1980. * burton s. garbow, kenneth e. hillstrom, jorge j. more * * C translation by Steve Moshier http://www.moshier.net/ * * C++ "translation" for use w/ wxWindows by John Labenski */ #ifndef _LM_LEASTSQUARE_H_ #define _LM_LEASTSQUARE_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "lm_lsqr.h" #endif #include "wx/plotctrl/plotdefs.h" class WXDLLIMPEXP_PLOTCTRL wxPlotData; class WXDLLIMPEXP_PLOTCTRL wxPlotFunction; // When SetLM_LeastSquareProgressHandler is called with a non NULL handler it will be // called when fitting a curve every SetLM_LeastSquareProgressHandlerTicks // text is the function name // current is the current iteration, max is max allowed iterations // note: current may exceed max by a few iterations in some cases // Usage: create a function like this // void LM_LeastSquareProgressHandler(const wxString &text, int current, int max) // { [ do stuff... for example update a progress dialog ] // wxString str = text + wxString::Format(wxT("\nIteration # %d of %d"), current, max); // int percent = wxMin(int(100.0*current/max), 99); // iterations may overflow! // return s_progressDialog->Update(percent, str); } // // then call SetLM_LeastSquareProgressHandler( LM_LeastSquareProgressHandler ); extern "C" { typedef bool (*LM_LeastSquareProgressHandler_)(const wxString &WXUNUSED(text), int WXUNUSED(current), int WXUNUSED(max)); extern void SetLM_LeastSquareProgressHandler( LM_LeastSquareProgressHandler_ handler ); extern void SetLM_LeastSquareProgressHandlerTicks( int iterations ); } //============================================================================= // LM_LeastSquare - Levenberg-Marquart nonlinear least squares 2-D curve fitting // // Fit the plot function to the plot data // // Notes : // the plot function must have fewer or equal vars than the plotdata has points // the plotfunction MUST! have the LAST variable as 'x' // you can set the starting values by filling 'initial_vals', size = (plotFunc.GetNumberVars - 1) // if initial_vars = NULL then they are all 0.1 // // Sample usage : // wxString message; // // Create some plotData, in this case from a known function // wxPlotData data(wxPlotFunction("2.5*x*x-3*x+5+3.3*log(x)+13*exp(15*x/(x+4))", "x",dummy), 0, 1E-4, 10000); // // Create the plotFunc we want to fit to the data, note: x is last var // wxPlotFunction func("a*x*x+b*x+c+d*log(x)+e*exp(f*x/(x+g))", "a,b,c,d,e,f,g,x", message); // LM_LeastSquare lmLeastSquare; // if (lmLeastSquare.Create(data, func)) { // lmLeastSquare.Fit(NULL); // or Fit(init, init_count) where double init[init_count] = { a, b, c, ... } // for (int k=0; k= m_m double *m_qtf; // output array the first n elements of the vector (q transpose)*fvec int *m_ipvt; // integer output array of length n int m_maxfev; // maximum number of iterations to try private: void Init(); }; #endif // _LM_LEASTSQUARE_H_ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/plotctrl.h0000644000076500007650000016311311350032206020754 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotctrl.h // Purpose: wxPlotCtrl // Author: John Labenski, Robert Roebling // Modified by: // Created: 6/5/2002 // Copyright: (c) John Labenski, Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_PLOTCTRL_H_ #define _WX_PLOTCTRL_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "plotctrl.h" #endif #include "wx/defs.h" #include "wx/geometry.h" #include "wx/bitmap.h" #include "wx/window.h" #include "wx/plotctrl/plotdefs.h" #include "wx/plotctrl/plotcurv.h" #include "wx/plotctrl/plotdata.h" #include "wx/plotctrl/plotmark.h" #include "wx/plotctrl/plotfunc.h" #include "wx/wxthings/range.h" class WXDLLEXPORT wxDC; class WXDLLEXPORT wxNotifyEvent; class WXDLLEXPORT wxPaintEvent; class WXDLLEXPORT wxMouseEvent; class WXDLLEXPORT wxKeyEvent; class WXDLLEXPORT wxTimer; class WXDLLEXPORT wxTimerEvent; class WXDLLEXPORT wxEraseEvent; class WXDLLEXPORT wxScrollBar; class WXDLLEXPORT wxBitmap; class WXDLLEXPORT wxTextCtrl; class WXDLLIMPEXP_THINGS wxRangeIntSelection; class WXDLLIMPEXP_THINGS wxRangeDoubleSelection; class WXDLLIMPEXP_THINGS wxArrayRangeIntSelection; class WXDLLIMPEXP_THINGS wxArrayRangeDoubleSelection; class WXDLLIMPEXP_PLOTCTRL wxPlotArea; class WXDLLIMPEXP_PLOTCTRL wxPlotAxis; class WXDLLIMPEXP_PLOTCTRL wxPlotCtrl; class WXDLLIMPEXP_PLOTCTRL wxPlotEvent; class WXDLLIMPEXP_PLOTCTRL wxPlotCurve; class WXDLLIMPEXP_PLOTCTRL wxPlotData; class WXDLLIMPEXP_PLOTCTRL wxPlotFunction; class WXDLLIMPEXP_PLOTCTRL wxPlotDrawerArea; class WXDLLIMPEXP_PLOTCTRL wxPlotDrawerXAxis; class WXDLLIMPEXP_PLOTCTRL wxPlotDrawerYAxis; class WXDLLIMPEXP_PLOTCTRL wxPlotDrawerKey; class WXDLLIMPEXP_PLOTCTRL wxPlotDrawerCurve; class WXDLLIMPEXP_PLOTCTRL wxPlotDrawerDataCurve; class WXDLLIMPEXP_PLOTCTRL wxPlotDrawerMarker; //----------------------------------------------------------------------------- // wxPlot Constants //----------------------------------------------------------------------------- #ifdef __VISUALC__ #include // disable warning for stl::numeric_limits, // C++ language change: to explicitly specialize #pragma warning(disable:4663) #endif // __VISUALC__ #include extern std::numeric_limits wxDouble_limits; extern const wxDouble wxPlot_MIN_DBL; // = wxDouble_limits.min()*10 extern const wxDouble wxPlot_MAX_DBL; // = wxDouble_limits.max()/10 extern const wxDouble wxPlot_MAX_RANGE; // = wxPlot_MAX_DBL*2 #define CURSOR_GRAB (wxCURSOR_MAX+100) // A hand cursor with fingers closed #include "wx/dynarray.h" #ifndef WX_DECLARE_OBJARRAY_WITH_DECL // for wx2.4 backwards compatibility #define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, expmode) WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLIMPEXP_PLOTCTRL) #endif WX_DECLARE_OBJARRAY_WITH_DECL(wxPoint2DDouble, wxArrayPoint2DDouble, class WXDLLIMPEXP_PLOTCTRL); WX_DECLARE_OBJARRAY_WITH_DECL(wxRect2DDouble, wxArrayRect2DDouble, class WXDLLIMPEXP_PLOTCTRL); WX_DECLARE_OBJARRAY_WITH_DECL(wxPlotCurve, wxArrayPlotCurve, class WXDLLIMPEXP_PLOTCTRL); // What type of axis for wxPlotAxis window enum wxPlotAxis_Type { wxPLOT_X_AXIS = 0x0020, wxPLOT_Y_AXIS = 0x0200, wxPLOT_DEFAULT = wxPLOT_X_AXIS|wxPLOT_Y_AXIS }; // What is the function of the mouse during left down and dragging enum wxPlotMouse_Type { wxPLOT_MOUSE_NOTHING, // do nothing wxPLOT_MOUSE_ZOOM, // zoom into the plot wxPLOT_MOUSE_SELECT, // select points in the active curve wxPLOT_MOUSE_DESELECT, // deselect points in the active curve wxPLOT_MOUSE_PAN // offset the origin }; // What sort of marker should be drawn for mouse left down and dragging enum wxPlotMarker_Type { wxPLOT_MARKER_NONE, // draw nothing wxPLOT_MARKER_RECT, // draw a rectangle wxPLOT_MARKER_VERT, // draw two vertical lines wxPLOT_MARKER_HORIZ // draw two horizonal lines }; // How does the selection mechanism act to selections enum wxPlotSelection_Type { wxPLOT_SELECT_NONE, // no selections wxPLOT_SELECT_SINGLE, // only one selection in one curve at a time wxPLOT_SELECT_SINGLE_CURVE, // only one curve may have selections at once wxPLOT_SELECT_SINGLE_PER_CURVE, // multiple curves may one have one selection each wxPLOT_SELECT_MULTIPLE // multiple curves may have multiple selections }; // Redraw parts or all of the windows enum wxPlotRedraw_Type { wxPLOT_REDRAW_NONE = 0x000, // do nothing wxPLOT_REDRAW_PLOT = 0x001, // redraw only the plot area wxPLOT_REDRAW_XAXIS = 0x002, // redraw x-axis, combine w/ redraw_plot wxPLOT_REDRAW_YAXIS = 0x004, // redraw y-axis, combine w/ redraw_plot wxPLOT_REDRAW_WINDOW = 0x008, // wxPlotCtrl container window wxPLOT_REDRAW_WHOLEPLOT = wxPLOT_REDRAW_PLOT|wxPLOT_REDRAW_XAXIS|wxPLOT_REDRAW_YAXIS, wxPLOT_REDRAW_EVERYTHING = wxPLOT_REDRAW_WHOLEPLOT|wxPLOT_REDRAW_WINDOW, wxPLOT_REDRAW_BLOCKER = 0x010 // don't let OnPaint redraw, used internally }; // Styles for the different plot window components enum wxPlotStyle_Type { wxPLOT_STYLE_WINDOW, wxPLOT_STYLE_LABELS, wxPLOT_STYLE_TITLE, wxPLOT_STYLE_XAXIS_LABEL, wxPLOT_STYLE_YAXIS_LABEL, wxPLOT_STYLE_XAXIS_TICS, wxPLOT_STYLE_YAXIS_TICS, wxPLOT_STYLE_KEY, wxPLOT_STYLE_LAST }; enum wxPlotStyleUse_Type { wxPLOT_STYLEUSE_FORECOLOUR = 0x0001, wxPLOT_STYLEUSE_BACKCOLOUR = 0x0002, wxPLOT_STYLEUSE_FONT = 0x0004, wxPLOT_STYLEUSE_LINEWIDTH = 0x0008 }; //----------------------------------------------------------------------------- // wxPlotArea - window where the plot is drawn (privately used in wxPlotCtrl) //----------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotArea : public wxWindow { public: wxPlotArea( wxWindow *parent, wxWindowID win_id ) { Init(); (void)Create(parent, win_id); } bool Create( wxWindow *parent, wxWindowID win_id ); virtual ~wxPlotArea() {} // Get the owner (parent) wxPlotCtrl wxPlotCtrl *GetOwner() const { return m_owner; } // Draw the area of the plot window in client coords bounded by rect // resizes backing bitmap if necessary void CreateBitmap( const wxRect &rect ); // implementation void OnEraseBackground( wxEraseEvent & ) { } void OnPaint( wxPaintEvent &event ); void OnMouse( wxMouseEvent &event ); void OnChar( wxKeyEvent &event ); void OnKeyDown( wxKeyEvent &event ); void OnKeyUp( wxKeyEvent &event ); wxRect m_mouseRect; // mouse drag rectangle, or 0,0,0,0 when not dragging wxPoint m_mousePt; // last mouse position wxBitmap m_bitmap; wxPlotCtrl *m_owner; private: void Init(); DECLARE_CLASS(wxPlotArea) DECLARE_EVENT_TABLE() }; //----------------------------------------------------------------------------- // wxPlotAxis - X or Y axis window (privately used in wxPlotCtrl) //----------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotAxis : public wxWindow { public: wxPlotAxis( wxWindow *parent, wxWindowID win_id, wxPlotAxis_Type style ) { Init(); (void)Create( parent, win_id, style ); } bool Create( wxWindow *parent, wxWindowID win_id, wxPlotAxis_Type style ); virtual ~wxPlotAxis() {} // Create the backing bitmap of the window contents void CreateBitmap(); // Get the owner (parent) wxPlotCtrl wxPlotCtrl *GetOwner() const { return m_owner; } bool IsXAxis() const { return (m_style & wxPLOT_X_AXIS) != 0; } // implementation void OnEraseBackground( wxEraseEvent & ) { } void OnPaint( wxPaintEvent &event ); void OnMouse( wxMouseEvent &event ); void OnChar( wxKeyEvent &event ); wxPoint m_mousePt; // last mouse position wxPlotAxis_Type m_style; wxBitmap m_bitmap; wxPlotCtrl *m_owner; private: void Init(); DECLARE_CLASS(wxPlotAxis) DECLARE_EVENT_TABLE() }; //----------------------------------------------------------------------------- // wxPlotCtrl - window to display wxPlotCurves, public interface // // notes: // call CalcBoundingRect() whenever you modify a curve's values so that // the default size of the plot is correct, see wxPlotCurve::GetBoundingRect // //----------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotCtrl : public wxWindow { public: wxPlotCtrl() : wxWindow() { Init(); } wxPlotCtrl( wxWindow *parent, wxWindowID win_id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, wxPlotAxis_Type flags = wxPLOT_DEFAULT, const wxString& name = wxT("wxPlotCtrl") ) { Init(); (void)Create(parent, win_id, pos, size, flags, name); } bool Create( wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, wxPlotAxis_Type flags = wxPLOT_DEFAULT, const wxString& name = wxT("wxPlotCtrl") ); virtual ~wxPlotCtrl(); // ------------------------------------------------------------------------ // Curve Accessors // // note: the curves are stored in an array casted to class wxPlotCurve // in order to know the type and use it as a wxPlotFunction, wxPlotData // or a class derived from one of these use // wxPlotData *pd = wxDynamicCast( GetCurve(i), wxPlotData ); // pd will be NULL if GetCurve isn't a wxPlotData (or derived from it) // ------------------------------------------------------------------------ // Add a curve to the plot, takes ownership of the curve and deletes it bool AddCurve( wxPlotCurve *curve, bool select=true, bool send_event=false ); // Add a curve to the plot, increases ref count bool AddCurve( const wxPlotCurve &curve, bool select=true, bool send_event=false ); // Delete this curve bool DeleteCurve( wxPlotCurve* curve, bool send_event=false ); // Delete this curve, if curve_index = -1, delete all curves bool DeleteCurve( int curve_index, bool send_event=false ); // Total number of curves associated with the plotctrl int GetCurveCount() const { return m_curves.GetCount(); } bool CurveIndexOk(int curve_index) const { return (curve_index>=0) && (curve_index < int(m_curves.GetCount())); } // Get the curve at this index wxPlotCurve *GetCurve( int curve_index ) const; // returns NULL if curve_index is not wxPlotData or derived from it wxPlotData *GetDataCurve( int curve_index ) const { return wxDynamicCast(GetCurve(curve_index), wxPlotData); } // returns NULL if curve_index is not wxPlotFunction or derived from it wxPlotFunction *GetFunctionCurve( int curve_index ) const { return wxDynamicCast(GetCurve(curve_index), wxPlotFunction); } // returns true if the curve is a wxPlotData curve bool IsDataCurve( int curve_index ) const { return GetDataCurve(curve_index) != NULL; } // returns true if the curve is a wxPlotFunction curve bool IsFunctionCurve( int curve_index ) const { return GetFunctionCurve(curve_index) != NULL; } // Else the function must be some sort of subclassed wxPlotCurve // Sets the currently active curve, NULL for none active void SetActiveCurve( wxPlotCurve* curve, bool send_event=false ); // Gets the currently active curve, NULL if none wxPlotCurve *GetActiveCurve() const { return m_activeCurve; } // Gets the currently active curve as a wxPlotFunction // returns NULL if its not a wxPlotFunction, even if a curve is active wxPlotFunction *GetActiveFuncCurve() const { return wxDynamicCast(m_activeCurve, wxPlotFunction); } // Gets the currently active curve as a wxPlotData // returns NULL if its not a wxPlotData, even if a curve is active wxPlotData *GetActiveDataCurve() const { return wxDynamicCast(m_activeCurve, wxPlotData); } // Set the curve_index curve active, use -1 to have none selected void SetActiveIndex( int curve_index, bool send_event=false ); // Get the index of the active curve, returns -1 if none active int GetActiveIndex() const { return m_active_index; } // Get an array of curve indexes that are of class wxPlotData, // wxPlotFunction or derived from either wxArrayInt GetPlotDataIndexes() const; wxArrayInt GetPlotFunctionIndexes() const; //------------------------------------------------------------------------- // Markers //------------------------------------------------------------------------- // Add a marker to be displayed int AddMarker( const wxPlotMarker& marker ); void RemoveMarker(int marker); void ClearMarkers(); wxPlotMarker GetMarker(int marker) const; wxArrayPlotMarker& GetMarkerArray() { return m_plotMarkers; } //------------------------------------------------------------------------- // Cursor position - a single selected point in a curve //------------------------------------------------------------------------- // Hide the cursor void InvalidateCursor(bool send_event=false); // Does the cursor point to a valid curve and if a data curve a valid data index bool IsCursorValid(); // Get the index of the curve that the cursor is associated with, -1 if none int GetCursorCurveIndex() const { return m_cursor_curve; } // Get the index into the wxPlotData curve of the cursor, -1 if not on a data curve int GetCursorDataIndex() const { return m_cursor_index; } // Get the location of the cursor, valid for all curve types if cursor valid wxPoint2DDouble GetCursorPoint(); // Set the curve and the index into the wxPlotData of the cursor // curve_index must point to a data curve and cursor_index valid in data bool SetCursorDataIndex(int curve_index, int cursor_index, bool send_event=false); // Set the curve and the x-value of the cursor, valid for all curve types // if curve_index is a wxPlotData curve it finds nearest index bool SetCursorXPoint(int curve_index, double x, bool send_event=false); // The cursor must be valid, if center then it centers the plot on the cursor // if !center then make the cursor just barely visible by shifting the view void MakeCursorVisible(bool center, bool send_event=false); //------------------------------------------------------------------------- // Selected points //------------------------------------------------------------------------- // Is anything selected in a particular curve or any curve if index = -1 bool HasSelection(int curve_index = -1) const; // double valued selections can be made for wxPlotCurves and wxPlotFunctions // for curves that are wxPlotData, the selection is empty, see GetDataCurveSelections const wxArrayRangeDoubleSelection& GetCurveSelections() const { return m_curveSelections; } // Get the particluar selection for the curve at index curve_index wxRangeDoubleSelection *GetCurveSelection(int curve_index) const; // the selections of wxPlotData curves are of the indexes of the data // for curves that are wxPlotCurves or wxPlotFunctions the selection is empty const wxArrayRangeIntSelection& GetDataCurveSelections() const { return m_dataSelections; } // Get the particluar selection for the curve at index curve_index wxRangeIntSelection *GetDataCurveSelection(int curve_index) const; // Get the number of individual selections of this curve int GetSelectedRangeCount(int curve_index) const; // Selects points in a curve using a rectangular selection (see select range) // this works for all plotcurve classes, for wxPlotData they're converted to the indexes however // if there's nothing to select or already selected it returns false // if curve_index == -1 then try to select points in all curves bool SelectRectangle( int curve_index, const wxRect2DDouble &rect, bool send_event = false) { return DoSelectRectangle(curve_index, rect, true, send_event); } bool DeselectRectangle( int curve_index, const wxRect2DDouble &rect, bool send_event = false) { return DoSelectRectangle(curve_index, rect, false, send_event); } // Select a single point wxRangeDouble(pt,pt) or a data range wxRangeDouble(pt1, pt2) // this works for all plotcurve classes, for wxPlotData they're converted to the indexes however // if there's nothing to select or already selected it returns false // if curve_index == -1 then try to select points in all curves bool SelectXRange(int curve_index, const wxRangeDouble &range, bool send_event = false) { return DoSelectRectangle(curve_index, wxRect2DDouble(range.m_min, -wxPlot_MAX_DBL, range.GetRange(), wxPlot_MAX_RANGE), true, send_event); } bool DeselectXRange(int curve_index, const wxRangeDouble &range, bool send_event = false) { return DoSelectRectangle(curve_index, wxRect2DDouble(range.m_min, -wxPlot_MAX_DBL, range.GetRange(), wxPlot_MAX_RANGE), false, send_event); } bool SelectYRange(int curve_index, const wxRangeDouble &range, bool send_event = false) { return DoSelectRectangle(curve_index, wxRect2DDouble(-wxPlot_MAX_DBL, range.m_min, wxPlot_MAX_RANGE, range.GetRange()), true, send_event); } bool DeselectYRange(int curve_index, const wxRangeDouble &range, bool send_event = false) { return DoSelectRectangle(curve_index, wxRect2DDouble(-wxPlot_MAX_DBL, range.m_min, wxPlot_MAX_RANGE, range.GetRange()), false, send_event); } // Select a single point wxRangeInt(pt, pt) or a range of points wxRangeInt(pt1, pt2) // if there's nothing to select or already selected it returns false, // this ONLY works for wxPlotData curves bool SelectDataRange(int curve_index, const wxRangeInt &range, bool send_event = false) { return DoSelectDataRange(curve_index, range, true, send_event); } bool DeselectDataRange(int curve_index, const wxRangeInt &range, bool send_event = false) { return DoSelectDataRange(curve_index, range, false, send_event); } // Clear the ranges, if curve_index = -1 then clear them all bool ClearSelectedRanges(int curve_index, bool send_event = false); // internal use, or not... virtual bool DoSelectRectangle(int curve_index, const wxRect2DDouble &rect, bool select, bool send_event = false); virtual bool DoSelectDataRange(int curve_index, const wxRangeInt &range, bool select, bool send_event = false); // called from DoSelect... when selecting to ensure that the current selection // matches the SetSelectionType by unselecting as appropriate // The input curve_index implies that a selection will be made for that curve // This is not called for a deselection event. virtual bool UpdateSelectionState(int curve_index, bool send_event); // Set how the selections mechanism operates, see enum wxPlotSelection_Type // You are responsible to clean up the selections if you change this, // however it won't fail, but may be out of sync. void SetSelectionType(wxPlotSelection_Type type) { m_selection_type = type; } int GetSelectionType() const { return m_selection_type; } // ------------------------------------------------------------------------ // Get/Set origin, size, and Zoom in/out of view, set scaling, size... // ------------------------------------------------------------------------ // make this curve fully visible or -1 to make all curves visible // uses wxPlotCurve::GetBoundingRect() // data curves have known sizes, function curves use default rect, unless set bool MakeCurveVisible(int curve_index, bool send_event=false); // Set the origin of the plot window bool SetOrigin( double origin_x, double origin_y, bool send_event=false ) { return SetZoom( m_zoom.m_x, m_zoom.m_y, origin_x, origin_y, send_event ); } // Get the bounds of the plot window view in plot coords const wxRect2DDouble& GetViewRect() const { return m_viewRect; } // Set the bounds of the plot window bool SetViewRect(const wxRect2DDouble &view, bool send_event=false); // Get the zoom factor = (pixel size of window)/(GetViewRect().m_width or height) const wxPoint2DDouble& GetZoom() const { return m_zoom; } // Zoom, if zoom_x or zoom_y <= 0 then fit that axis to window and center it bool SetZoom( const wxPoint2DDouble &zoom, bool around_center=true, bool send_event=false ); virtual bool SetZoom( double zoom_x, double zoom_y, double origin_x, double origin_y, bool send_event=false ); // Zoom in client coordinates, window.[xy] is top left (unlike plot axis) bool SetZoom( const wxRect &window, bool send_event=false ); // Set/Get the default size the plot should take when either no curves are // loaded or only plot(curves/functions) that have no bounds are loaded // The width and the height must both be > 0 void SetDefaultBoundingRect( const wxRect2DDouble &rect, bool send_event = false ); const wxRect2DDouble& GetDefaultBoundingRect() const { return m_defaultPlotRect; } // Get the bounding rect of all the curves, // equals the default if no curves or no bounds on the curves const wxRect2DDouble& GetCurveBoundingRect() const { return m_curveBoundingRect; } // Get client rect of the wxPlotArea window, 0, 0, client_width, client_height const wxRect& GetPlotAreaRect() const { return m_areaClientRect; } // The history of mouse drag rects are saved (mouseFunc_zoom) void NextHistoryView(bool foward, bool send_event=false); int GetHistoryViewCount() const { return m_historyViews.GetCount(); } int GetHistoryViewIndex() const { return m_history_views_index; } // Fix the aspect ratio of the x and y axes, if set then when the zoom is // set the smaller of the two (x or y) zooms is multiplied by the ratio // to calculate the other. void SetFixAspectRatio(bool fix, double ratio = 1.0); void FixAspectRatio( double *zoom_x, double *zoom_y, double *origin_x, double *origin_y ); // ------------------------------------------------------------------------ // Mouse Functions for the area window // ------------------------------------------------------------------------ // The current (last) pixel position of the mouse in the plotArea const wxPoint& GetAreaMouseCoord() const { return m_area->m_mousePt; } // The current plotArea position of the mouse cursor wxPoint2DDouble GetAreaMousePoint() const { return wxPoint2DDouble(GetPlotCoordFromClientX(m_area->m_mousePt.x), GetPlotCoordFromClientY(m_area->m_mousePt.y)); } // Get the rect during dragging mouse, else 0 const wxRect& GetAreaMouseMarkedRect() const { return m_area->m_mouseRect; } // Set what the mouse will do for different actions void SetAreaMouseFunction(wxPlotMouse_Type func, bool send_event=false); wxPlotMouse_Type GetAreaMouseFunction() const { return m_area_mouse_func; } // Set what sort of marker should be drawn when dragging mouse void SetAreaMouseMarker(wxPlotMarker_Type type); wxPlotMarker_Type GetAreaMouseMarker() const { return m_area_mouse_marker; } // Set the mouse cursor wxCURSOR_XXX + CURSOR_GRAB for the plot area void SetAreaMouseCursor(int cursorid); // ------------------------------------------------------------------------ // Options // ------------------------------------------------------------------------ // Scroll the window only when the mouse button is released (for slow machines) bool GetScrollOnThumbRelease() const { return m_scroll_on_thumb_release; } void SetScrollOnThumbRelease( bool scrollOnThumbRelease = true ) { m_scroll_on_thumb_release = scrollOnThumbRelease; } // Use a full width/height crosshair as a cursor bool GetCrossHairCursor() const { return m_crosshair_cursor; } void SetCrossHairCursor( bool useCrosshairCursor = false ) { m_crosshair_cursor = useCrosshairCursor; m_area->m_mousePt = wxPoint(-1,-1); Redraw(wxPLOT_REDRAW_PLOT); } // Draw the data curve symbols on the plotctrl bool GetDrawSymbols() const { return m_draw_symbols; } void SetDrawSymbols( bool drawsymbols = true ) { m_draw_symbols = drawsymbols; Redraw(wxPLOT_REDRAW_PLOT); } // Draw the interconnecting straight lines between data points bool GetDrawLines() const { return m_draw_lines; } void SetDrawLines( bool drawlines = true ) { m_draw_lines = drawlines; Redraw(wxPLOT_REDRAW_PLOT); } // Draw the interconnecting splines between data points bool GetDrawSpline() const { return m_draw_spline; } void SetDrawSpline( bool drawspline = false ) { m_draw_spline = drawspline; Redraw(wxPLOT_REDRAW_PLOT); } // Draw the plot grid over the whole window, else just tick marks at edge bool GetDrawGrid() const { return m_draw_grid; } void SetDrawGrid( bool drawgrid = true ) { m_draw_grid = drawgrid; Redraw(wxPLOT_REDRAW_PLOT); } // Try to fit the window to show all curves when a new curve is added bool GetFitPlotOnNewCurve() const { return m_fit_on_new_curve; } void SetFitPlotOnNewCurve( bool fit = true ) { m_fit_on_new_curve = fit; } // Set the focus to this window if the mouse enters it, otherwise you have to click // sometimes convenient, but often this is annoying bool GetGreedyFocus() const { return m_greedy_focus; } void SetGreedyFocus(bool grab_focus = false) { m_greedy_focus = grab_focus; } // turn on or off the Correct Ticks functions. Turning this off allows a graph // that scrolls to scroll smoothly in the direction expected. Turning this // on (default) gives better accuracy for 'mouse hover' information display bool GetCorrectTicks() const { return m_correct_ticks; } void SetCorrectTicks( bool correct = true ) { m_correct_ticks = correct; } // get/set the width of a 1 pixel pen in mm for printing double GetPrintingPenWidth(void) { return m_pen_print_width; } void SetPrintingPenWidth(double width) { m_pen_print_width = width; } // ------------------------------------------------------------------------ // Colours & Fonts for windows, labels, title... // ------------------------------------------------------------------------ // Get/Set the background colour of all the plot windows, default white wxColour GetBackgroundColour() const { return m_area->GetBackgroundColour(); } virtual bool SetBackgroundColour( const wxColour &colour ); // Get/Set the colour of the grid lines in the plot area, default grey wxColour GetGridColour() const { return m_area->GetForegroundColour(); } void SetGridColour( const wxColour &colour ); // Get/Set the colour of the border around the plot area, default black wxColour GetBorderColour() const { return m_borderColour; } void SetBorderColour( const wxColour &colour ); // Get/Set the colour of the cursor marker, default green wxColour GetCursorColour() const; void SetCursorColour( const wxColour &colour ); // Get/Set the cursor size, the size of the circle drawn for the cursor. // set size to 0 to not have the cursor shown (default = 2) int GetCursorSize() const; void SetCursorSize(int size); // Get/Set the axis numbers font and colour, default normal & black wxFont GetAxisFont() const; wxColour GetAxisColour() const; void SetAxisFont( const wxFont &font ); void SetAxisColour( const wxColour &colour ); // Get/Set axis label fonts and colour, default swiss and black wxFont GetAxisLabelFont() const; wxColour GetAxisLabelColour() const; void SetAxisLabelFont( const wxFont &font ); void SetAxisLabelColour( const wxColour &colour ); // Get/Set the title font and colour, default swiss and black wxFont GetPlotTitleFont() const { return m_titleFont; } wxColour GetPlotTitleColour() const { return m_titleColour; } void SetPlotTitleFont( const wxFont &font ); void SetPlotTitleColour( const wxColour &colour ); // Get/Set the key font and colour wxFont GetKeyFont() const; wxColour GetKeyColour() const; void SetKeyFont( const wxFont &font ); void SetKeyColour( const wxColour & colour ); // ------------------------------------------------------------------------ // Title, axis labels, and key values and visibility // ------------------------------------------------------------------------ // Get/Set showing x and/or y axes void SetShowXAxis(bool show) { m_show_xAxis = show; } void SetShowYAxis(bool show) { m_show_yAxis = show; } bool GetShowXAxis() { return m_show_xAxis; } bool GetShowYAxis() { return m_show_yAxis; } // Get/Set and show/hide the axis labels const wxString& GetXAxisLabel() const { return m_xLabel; } const wxString& GetYAxisLabel() const { return m_yLabel; } void SetXAxisLabel(const wxString &label); void SetYAxisLabel(const wxString &label); bool GetShowXAxisLabel() const { return m_show_xlabel; } bool GetShowYAxisLabel() const { return m_show_ylabel; } void SetShowXAxisLabel( bool show ) { m_show_xlabel = show; DoSize(); } void SetShowYAxisLabel( bool show ) { m_show_ylabel = show; DoSize(); } // Get/Set and show/hide the title const wxString& GetPlotTitle() const { return m_title; } void SetPlotTitle(const wxString &title); bool GetShowPlotTitle() const { return m_show_title; } void SetShowPlotTitle( bool show ) { m_show_title = show; DoSize(); } // Show a key with the function/data names, pos is %width and %height (0-100) const wxString& GetKeyString() const { return m_keyString; } bool GetShowKey() const { return m_show_key; } void SetShowKey(bool show) { m_show_key = show; Redraw(wxPLOT_REDRAW_PLOT); } wxPoint GetKeyPosition() const; bool GetKeyInside() const; void SetKeyPosition(const wxPoint &pos, bool stay_inside = true); // used internally to update the key string from the curve names virtual void CreateKeyString(); // set the minimum value to be displayed as an exponential on the axes long GetMinExpValue() const { return m_min_exponential; } void SetMinExpValue( long min ) { m_min_exponential = min; } // ------------------------------------------------------------------------ // Title, axis label editor control // ------------------------------------------------------------------------ enum wxPlotCtrlTextCtrl_Type { wxPLOT_EDIT_TITLE = 1, wxPLOT_EDIT_XAXIS, wxPLOT_EDIT_YAXIS, }; // Sends the wxEVT_PLOT_BEGIN_TITLE_(X/Y_LABEL)_EDIT event if send_event // which can be vetoed void ShowTextCtrl(wxPlotCtrlTextCtrl_Type type, bool send_event = false); // Sends the wxEVT_PLOT_END_TITLE_(X/Y_LABEL)_EDIT event if send_event // which can be vetoed void HideTextCtrl(bool save_value = true, bool send_event = false); bool IsTextCtrlShown() const; // ------------------------------------------------------------------------ // Event processing // ------------------------------------------------------------------------ // EVT_MOUSE_EVENTS from the area and axis windows are passed to these functions virtual void ProcessAreaEVT_MOUSE_EVENTS( wxMouseEvent &event ); virtual void ProcessAxisEVT_MOUSE_EVENTS( wxMouseEvent &event ); // EVT_CHAR from the area and axis windows are passed to these functions virtual void ProcessAreaEVT_CHAR( wxKeyEvent &event ) { OnChar(event); return; } virtual void ProcessAreaEVT_KEY_DOWN( wxKeyEvent &event ); virtual void ProcessAreaEVT_KEY_UP( wxKeyEvent &event ); virtual void ProcessAxisEVT_CHAR( wxKeyEvent &event ) { OnChar(event); return; } void OnChar( wxKeyEvent &event ); void OnScroll( wxScrollEvent& event ); void OnPaint( wxPaintEvent &event ); void OnEraseBackground( wxEraseEvent &event ) { event.Skip(false); } void OnIdle( wxIdleEvent &event ); void OnMouse( wxMouseEvent &event ); void OnTextEnter( wxCommandEvent &event ); // ------------------------------------------------------------------------ // Drawing functions // ------------------------------------------------------------------------ // call BeginBatch to disable redrawing EndBatch to reenable and refresh // when batchcount == 0, if !force_refresh then don't refresh when batch == 0 void BeginBatch() { m_batch_count++; } void EndBatch(bool force_refresh = true); int GetBatchCount() const { return m_batch_count; } // Redraw parts of the plotctrl using combinations of wxPlot_Redraw_Type void Redraw(int type); // Get/Set the redraw type variable (this is for internal use, see Redraw()) int GetRedrawType() const { return m_redraw_type; } void SetRedrawType(int type) { m_redraw_type = type; } // Draw a marker in lower right signifying that this has the focus virtual void DrawActiveBitmap( wxDC *dc ); // Draw the wxPlotCtrl (this window) virtual void DrawPlotCtrl( wxDC *dc ); // Draw the area window virtual void DrawAreaWindow( wxDC *dc, const wxRect& rect ); // Draw a wxPlotData derived curve virtual void DrawDataCurve( wxDC *dc, wxPlotData *curve, int curve_index, const wxRect &rect ); // Draw a generic wxPlotCurve curve virtual void DrawCurve( wxDC *dc, wxPlotCurve *curve, int curve_index, const wxRect &rect ); // Draw the key virtual void DrawKey( wxDC *dc ); // Draw the left click drag marker, type is wxPlot_Marker_Type virtual void DrawMouseMarker( wxDC *dc, int type, const wxRect &rect ); // Draw a crosshair cursor at the point (mouse cursor) virtual void DrawCrosshairCursor( wxDC *dc, const wxPoint &pos ); // Draw the cursor marking a single point in a curve wxPlotCtrl::GetCursorPoint virtual void DrawCurveCursor( wxDC *dc ); // Draw the tick marks or grid lines virtual void DrawTickMarks( wxDC *dc, const wxRect& rect ); // Draw markers virtual void DrawMarkers( wxDC *dc, const wxRect& rect ); // redraw this wxPlotData between these two indexes (for (de)select redraw) virtual void RedrawDataCurve(int index, int min_index, int max_index); // redraw this wxPlotCurve between these two values (for (de)select redraw) virtual void RedrawCurve(int index, double min_x, double max_x); // Draw the X or Y axis onto the dc virtual void DrawXAxis( wxDC *dc, bool refresh ); virtual void DrawYAxis( wxDC *dc, bool refresh ); // Draw the plot axes and plotctrl on this wxDC for printing, sort of WYSIWYG // the plot is drawn to fit inside the boundingRect (i.e. the margins) void DrawWholePlot( wxDC *dc, const wxRect &boundingRect, int dpi = 72 ); // ------------------------------------------------------------------------ // Axis tick calculations // ------------------------------------------------------------------------ // find the optimal number of ticks, step size, and format string void AutoCalcTicks() { AutoCalcXAxisTicks(); AutoCalcYAxisTicks(); } void AutoCalcXAxisTicks() { DoAutoCalcTicks(true); } void AutoCalcYAxisTicks() { DoAutoCalcTicks(false); } virtual void DoAutoCalcTicks(bool x_axis); // slightly correct the Zoom and origin to exactly match tick marks // otherwise when the mouse is over '1' you may get 0.99999 or 1.000001 void CorrectTicks() { CorrectXAxisTicks(); CorrectYAxisTicks(); } void CorrectXAxisTicks(); void CorrectYAxisTicks(); // Find the correct dc coords for the tick marks and label strings, internal use void CalcTickPositions() { CalcXAxisTickPositions(); CalcYAxisTickPositions(); } virtual void CalcXAxisTickPositions(); virtual void CalcYAxisTickPositions(); // ------------------------------------------------------------------------ // Utilities // ------------------------------------------------------------------------ // Find a curve at pt, in rect of size +- dxdyPt, starting with active curve // return sucess, setting curve_index, data_index if data curve, and if // curvePt fills the exact point in the curve. bool FindCurve(const wxPoint2DDouble &pt, const wxPoint2DDouble &dxdyPt, int &curve_index, int &data_index, wxPoint2DDouble *curvePt = NULL) const; // if n is !finite send wxEVT_PLOT_ERROR if msg is not empty bool IsFinite(double n, const wxString &msg = wxEmptyString) const; // call this whenever you adjust the size of a data curve // this necessary to know the default zoom to show them void CalcBoundingPlotRect(); // Client (pixels) to/from plot (double) coords inline double GetPlotCoordFromClientX( int clientx ) const { return (clientx/m_zoom.m_x + m_viewRect.GetLeft()); } inline double GetPlotCoordFromClientY( int clienty ) const { return ((m_areaClientRect.height - clienty)/m_zoom.m_y + m_viewRect.GetTop());} inline wxRect2DDouble GetPlotRectFromClientRect( const wxRect &clientRect ) const { return wxRect2DDouble( GetPlotCoordFromClientX(clientRect.x), GetPlotCoordFromClientY(clientRect.GetBottom()), clientRect.width/m_zoom.m_x, clientRect.height/m_zoom.m_y ); } inline int GetClientCoordFromPlotX( double plotx ) const { double x = m_zoom.m_x*(plotx - m_viewRect.GetLeft()) + 0.5; return x < INT_MAX ? int(x) : INT_MAX; } inline int GetClientCoordFromPlotY( double ploty ) const { double y = m_areaClientRect.height - m_zoom.m_y*(ploty - m_viewRect.GetTop()) + 0.5; return y < INT_MAX ? int(y) : INT_MAX; } inline wxRect GetClientRectFromPlotRect( const wxRect2DDouble &plotRect ) const { double w = plotRect.m_width*m_zoom.m_x + 0.5; double h = plotRect.m_height*m_zoom.m_y + 0.5; return wxRect( GetClientCoordFromPlotX(plotRect.m_x), GetClientCoordFromPlotY(plotRect.GetBottom()), w < INT_MAX ? int(w) : INT_MAX, h < INT_MAX ? int(h) : INT_MAX ); } // IDs for the children windows enum { ID_PLOTCTRL_X_AXIS = 100, ID_PLOTCTRL_Y_AXIS, ID_PLOTCTRL_AREA, ID_PLOTCTRL_X_SCROLLBAR, ID_PLOTCTRL_Y_SCROLLBAR }; // Get the windows wxPlotArea* GetPlotArea() const { return m_area; } wxPlotAxis* GetPlotXAxis() const { return m_xAxis; } wxPlotAxis* GetPlotYAxis() const { return m_yAxis; } // internal use size adjustment void AdjustScrollBars(); void UpdateWindowSize(); void DoSize(const wxRect &boundingRect = wxRect(0, 0, 0, 0)); // who's got the focus, if this then draw the bitmap to show it, internal bool CheckFocus(); // send event returning true if it's allowed bool DoSendEvent(wxPlotEvent &event) const; // Start the mouse timer with the win_id, stops old if for different id enum mouseTimerIDs { ID_AREA_TIMER = 10, ID_XAXIS_TIMER, ID_YAXIS_TIMER }; void StartMouseTimer(wxWindowID win_id); void StopMouseTimer(); bool IsTimerRunning(); void OnTimer( wxTimerEvent &event ); // A locker for the captured window, set to NULL to release void SetCaptureWindow( wxWindow *win ); wxWindow *GetCaptureWindow() const { return m_winCapture; } protected: void OnSize( wxSizeEvent& event ); wxArrayPlotCurve m_curves; // all the curves wxPlotCurve* m_activeCurve; // currently active curve int m_active_index; // index in array of currently active curve wxPlotMarker m_cursorMarker; // marker to draw for cursor int m_cursor_curve; // index into plot curve array int m_cursor_index; // if data curve, index in curve wxArrayRangeIntSelection m_dataSelections; // for wxPlotData wxArrayRangeDoubleSelection m_curveSelections; // for wxPlotCurve, wxPlotFunction int m_selection_type; wxArrayPlotMarker m_plotMarkers; // extra markers to draw bool m_show_key; // show the key wxString m_keyString; // the key string // title and label bool m_show_title; wxString m_title; bool m_show_xlabel, m_show_ylabel; wxString m_xLabel, m_yLabel; wxRect m_titleRect, m_xLabelRect, m_yLabelRect; // fonts and colours wxFont m_titleFont; wxColour m_titleColour; wxColour m_borderColour; // option variables bool m_scroll_on_thumb_release; bool m_crosshair_cursor; bool m_draw_symbols; bool m_draw_lines; bool m_draw_spline; bool m_draw_grid; bool m_fit_on_new_curve; bool m_show_xAxis; bool m_show_yAxis; // rects of the positions of each window - remember for DrawPlotCtrl wxRect m_xAxisRect, m_yAxisRect, m_areaRect, m_clientRect; // zooms wxPoint2DDouble m_zoom; wxArrayRect2DDouble m_historyViews; int m_history_views_index; void AddHistoryView(); // maintains small list of views bool m_fix_aspectratio; double m_aspectratio; // bounding rect, (GetLeft,GetTop) is lower left in screen coords wxRect2DDouble m_viewRect; // part of the plot currently displayed wxRect2DDouble m_curveBoundingRect; // total extent of the plot - CalcBoundingPlotRect wxRect2DDouble m_defaultPlotRect; // default extent of the plot, fallback wxRect m_areaClientRect; // rect of (wxPoint(0,0), PlotArea.GetClientSize()) wxArrayInt m_xAxisTicks, m_yAxisTicks; // pixel coordinates of the tic marks wxArrayString m_xAxisTickLabels, m_yAxisTickLabels; // the tick labels wxString m_xAxisTickFormat, m_yAxisTickFormat; // format %lg for example double m_xAxisTick_step, m_yAxisTick_step; // step size between ticks int m_xAxisTick_count, m_yAxisTick_count; // how many ticks fit? bool m_correct_ticks; // tick correction // drawers wxPlotDrawerArea *m_areaDrawer; wxPlotDrawerXAxis *m_xAxisDrawer; wxPlotDrawerYAxis *m_yAxisDrawer; wxPlotDrawerKey *m_keyDrawer; wxPlotDrawerCurve *m_curveDrawer; wxPlotDrawerDataCurve *m_dataCurveDrawer; wxPlotDrawerMarker *m_markerDrawer; // windows wxPlotArea *m_area; wxPlotAxis *m_xAxis, *m_yAxis; wxScrollBar *m_xAxisScrollbar, *m_yAxisScrollbar; // textctrl for label/title editor, created and deleted as necessary wxTextCtrl *m_textCtrl; // focusing and bitmap to display focus wxBitmap *m_activeBitmap, *m_inactiveBitmap; bool m_focused; bool m_greedy_focus; // remember what needs to be repainted so unnecessary EVT_PAINTS are skipped int m_redraw_type; int m_batch_count; wxSize m_axisFontSize; // pixel size of the number '5' for axis font int m_y_axis_text_width; // size of "-5e+005" for max y axis width int m_area_border_width; // width of area border pen (default 1) int m_border; // width of border between labels and axes long m_min_exponential; // minimum number displayed as an exponential double m_pen_print_width; // width of a 1 pixel pen in mm when printed wxTimer *m_timer; // don't use, see accessor functions wxWindow *m_winCapture; // don't use, see accessor functions wxPlotMouse_Type m_area_mouse_func; wxPlotMarker_Type m_area_mouse_marker; int m_area_mouse_cursorid; void SetPlotWinMouseCursor(int cursorid); int m_mouse_cursorid; private: void Init(); DECLARE_ABSTRACT_CLASS(wxPlotCtrl) DECLARE_EVENT_TABLE() }; //----------------------------------------------------------------------------- // wxPlotEvent //----------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotEvent : public wxNotifyEvent { public: wxPlotEvent(wxEventType commandType = wxEVT_NULL, int id = wxID_ANY, wxPlotCtrl *window = NULL); wxPlotEvent(const wxPlotEvent &event) : wxNotifyEvent(event), m_curve(event.m_curve), m_curveIndex(event.m_curveIndex), m_curveData_index(event.m_curveData_index), m_x(event.m_x), m_y(event.m_y) {} // position of the mouse cursor, double click, single point selection or 1st selected point double GetX() const { return m_x; } double GetY() const { return m_y; } void SetPosition( double x, double y ) { m_x = x; m_y = y; } int GetCurveDataIndex() const { return m_curveData_index; } void SetCurveDataIndex(int data_index) { m_curveData_index = data_index; } // pointer to the curve, NULL if not appropriate for the event type wxPlotCurve *GetCurve() const { return m_curve; } void SetCurve(wxPlotCurve *curve, int curve_index) { m_curve = curve; m_curveIndex = curve_index; } // index of the curve in wxPlotCtrl::GetCurve(index) int GetCurveIndex() const { return m_curveIndex; } void SetCurveIndex( int curve_index ) { m_curveIndex = curve_index; } bool IsDataCurve() const { return wxDynamicCast(m_curve, wxPlotData) != NULL; } wxPlotCtrl *GetPlotCtrl() const { return wxDynamicCast(GetEventObject(),wxPlotCtrl); } int GetMouseFunction() const { return m_commandInt; } void SetMouseFunction(int func) { m_commandInt = func; } // implementation virtual wxEvent *Clone() const { return new wxPlotEvent(*this); } wxPlotCurve *m_curve; int m_curveIndex; int m_curveData_index; double m_x, m_y; private: DECLARE_ABSTRACT_CLASS(wxPlotEvent); }; //----------------------------------------------------------------------------- // wxPlotEvent //----------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotSelectionEvent : public wxPlotEvent { public: wxPlotSelectionEvent(wxEventType commandType = wxEVT_NULL, int id = wxID_ANY, wxPlotCtrl *window = NULL); wxPlotSelectionEvent(const wxPlotSelectionEvent &event) : wxPlotEvent(event), m_dataRange(event.m_dataRange), m_curveRange(event.m_curveRange), m_dataSelection(event.m_dataSelection), m_selecting(event.m_selecting) {} // for SELection events the range specifies the new (de)selection range // note : for unordered data sets an event is only sent after all selections are made // the data selection range is used for wxPlotData curves these are the indexes // for wxPlotCurves and wxPlotFunctions these are the pixel locations wxRangeInt GetDataSelectionRange() const { return m_dataRange; } void SetDataSelectionRange( const wxRangeInt &range, bool selecting ) { m_dataRange = range; m_selecting = selecting; } // the curve selection range is the double valued start and stop position of the selection wxRangeDouble GetCurveSelectionRange() const { return m_curveRange; } void SetCurveSelectionRange( const wxRangeDouble &range, bool selecting ) { m_curveRange = range; m_selecting = selecting; } // for a wxPlotData this is filled with the (de)selected ranges. // there will only be more than one for unordered wxPlotDatas wxRangeIntSelection GetDataSelections() const { return m_dataSelection; } void SetDataSelections(const wxRangeIntSelection &ranges) { m_dataSelection = ranges; } // range is selected as opposed to being deselected bool IsSelecting() const { return m_selecting; } // implementation virtual wxEvent *Clone() const { return new wxPlotSelectionEvent(*this); } wxRangeInt m_dataRange; wxRangeDouble m_curveRange; wxRangeIntSelection m_dataSelection; bool m_selecting; private: DECLARE_ABSTRACT_CLASS(wxPlotSelectionEvent); }; // ---------------------------------------------------------------------------- // wxPlotEvent event types // ---------------------------------------------------------------------------- BEGIN_DECLARE_EVENT_TYPES() // wxPlotEvent DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_ADD_CURVE, 0) // a curve has been added DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_DELETING_CURVE, 0) // a curve is about to be deleted, event.Skip(false) to prevent DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_DELETED_CURVE, 0) // a curve has been deleted DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURVE_SEL_CHANGING, 0) // curve selection changing, event.Skip(false) to prevent DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURVE_SEL_CHANGED, 0) // curve selection has changed DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_MOUSE_MOTION, 0) // mouse moved DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CLICKED, 0) // mouse left or right clicked DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_DOUBLECLICKED, 0) // mouse left or right doubleclicked DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_POINT_CLICKED, 0) // clicked on a plot point (+-2pixels) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_POINT_DOUBLECLICKED,0) // dclicked on a plot point (+-2pixels) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CREATING, 0) // mouse left down and drag begin DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CHANGING, 0) // mouse left down and dragging DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CREATED, 0) // mouse left down and drag end DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VIEW_CHANGING, 0) // zoom or origin of plotctrl is about to change DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VIEW_CHANGED, 0) // zoom or origin of plotctrl has changed DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURSOR_CHANGING, 0) // cursor point/curve is about to change, event.Skip(false) to prevent // if the cursor is invalidated since // the curve is gone you cannot prevent it DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURSOR_CHANGED, 0) // cursor point/curve changed DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_ERROR, 0) // an error has occured, see event.GetString() // usually nonfatal NaN overflow errors DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_BEGIN_TITLE_EDIT, 0) // title is about to be edited, event.Skip(false) to prevent DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_END_TITLE_EDIT, 0) // title has been edited and changed, event.Skip(false) to prevent DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_BEGIN_X_LABEL_EDIT, 0) // x label is about to be edited, event.Skip(false) to prevent DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_END_X_LABEL_EDIT, 0) // x label has been edited and changed, event.Skip(false) to prevent DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_BEGIN_Y_LABEL_EDIT, 0) // y label is about to be edited, event.Skip(false) to prevent DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_END_Y_LABEL_EDIT, 0) // y label has been edited and changed, event.Skip(false) to prevent DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_MOUSE_FUNC_CHANGING,0) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_MOUSE_FUNC_CHANGED, 0) // wxPlotSelectionEvent //DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CREATING,0) //DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CREATED, 0) //DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CHANGING,0) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CHANGED, 0) // unused /* DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VALUE_SEL_CREATING, 0) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VALUE_SEL_CREATED, 0) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VALUE_SEL_CHANGING, 0) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VALUE_SEL_CHANGED, 0) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CHANGED, 0) */ END_DECLARE_EVENT_TYPES() // ---------------------------------------------------------------------------- // wxPlotEvent macros // ---------------------------------------------------------------------------- typedef void (wxEvtHandler::*wxPlotEventFunction)(wxPlotEvent&); #define wxPlotEventHandler(func) \ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxPlotEventFunction, &func) #define wx__DECLARE_PLOTEVT(evt, id, fn) wx__DECLARE_EVT1( evt, id, wxPlotEventHandler(fn)) #define EVT_PLOT_ADD_CURVE(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_ADD_CURVE, id, fn) #define EVT_PLOT_DELETING_CURVE(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_DELETING_CURVE, id, fn) #define EVT_PLOT_DELETED_CURVE(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_DELETED_CURVE, id, fn) #define EVT_PLOT_CURVE_SEL_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURVE_SEL_CHANGING, id, fn) #define EVT_PLOT_CURVE_SEL_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURVE_SEL_CHANGED, id, fn) #define EVT_PLOT_MOUSE_MOTION(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_MOUSE_MOTION, id, fn) #define EVT_PLOT_CLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CLICKED, id, fn) #define EVT_PLOT_DOUBLECLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_DOUBLECLICKED, id, fn) #define EVT_PLOT_POINT_CLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_POINT_CLICKED, id, fn) #define EVT_PLOT_POINT_DOUBLECLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_POINT_DOUBLECLICKED, id, fn) #define EVT_PLOT_AREA_SEL_CREATING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_AREA_SEL_CREATING, id, fn) #define EVT_PLOT_AREA_SEL_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_AREA_SEL_CHANGING, id, fn) #define EVT_PLOT_AREA_SEL_CREATED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_VIEW_CREATED, id, fn) #define EVT_PLOT_VIEW_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_VIEW_CHANGING, id, fn) #define EVT_PLOT_VIEW_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_VIEW_CHANGED, id, fn) #define EVT_PLOT_CURSOR_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURSOR_CHANGING, id, fn) #define EVT_PLOT_CURSOR_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURSOR_CHANGED, id, fn) #define EVT_PLOT_ERROR(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_ERROR, id, fn) #define EVT_PLOT_BEGIN_TITLE_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_BEGIN_TITLE_EDIT, id, fn) #define EVT_PLOT_END_TITLE_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_END_TITLE_EDIT, id, fn) #define EVT_PLOT_BEGIN_X_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_BEGIN_X_LABEL_EDIT, id, fn) #define EVT_PLOT_END_X_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_END_X_LABEL_EDIT, id, fn) #define EVT_PLOT_BEGIN_Y_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_BEGIN_Y_LABEL_EDIT, id, fn) #define EVT_PLOT_END_Y_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_END_Y_LABEL_EDIT, id, fn) #define EVT_PLOT_MOUSE_FUNC_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_MOUSE_FUNC_CHANGING, id, fn) #define EVT_PLOT_MOUSE_FUNC_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_MOUSE_FUNC_CHANGED, id, fn) typedef void (wxEvtHandler::*wxPlotSelectionEventFunction)(wxPlotSelectionEvent&); #define wxPlotSelectionEventHandler(func) \ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxPlotSelectionEventFunction, &func) #define wx__DECLARE_PLOTSELECTIONEVT(evt, id, fn) wx__DECLARE_EVT1( evt, id, wxPlotSelectionEventHandler(fn)) //#define EVT_PLOT_RANGE_SEL_CREATING(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_RANGE_SEL_CREATING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotSelectionEventFunction, & fn ), (wxObject *) NULL ), //#define EVT_PLOT_RANGE_SEL_CREATED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_RANGE_SEL_CREATED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotSelectionEventFunction, & fn ), (wxObject *) NULL ), //#define EVT_PLOT_RANGE_SEL_CHANGING(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_RANGE_SEL_CHANGING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotSelectionEventFunction, & fn ), (wxObject *) NULL ), #define EVT_PLOT_RANGE_SEL_CHANGED(id, fn) wx__DECLARE_PLOTSELECTIONEVT(wxEVT_PLOT_RANGE_SEL_CHANGED, id, fn) /* #define EVT_PLOT_VALUE_SEL_CREATING(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CREATING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), #define EVT_PLOT_VALUE_SEL_CREATED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CREATED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), #define EVT_PLOT_VALUE_SEL_CHANGING(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CHANGING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), #define EVT_PLOT_VALUE_SEL_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), #define EVT_PLOT_AREA_SEL_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_AREA_SEL_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), */ #endif // _WX_PLOTCTRL_H_ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/plotcurv.h0000644000076500007650000001753011350032206020770 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotcurv.h // Purpose: wxPlotCurve for wxPlotCtrl // Author: John Labenski // Modified by: // Created: 12/1/2000 // Copyright: (c) John Labenski // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_PLOTCURVE_H_ #define _WX_PLOTCURVE_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "plotcurv.h" #endif #include "wx/defs.h" #include "wx/object.h" #include "wx/clntdata.h" #include "wx/geometry.h" #include "wx/wxthings/genergdi.h" #include "wx/plotctrl/plotdefs.h" #ifdef GetYValue // Visual Studio 7 defines this #undef GetYValue #endif //----------------------------------------------------------------------------- // Utility functions //----------------------------------------------------------------------------- // Find y at point x along the line from (x0,y0)-(x1,y1), x0 must != x1 extern double LinearInterpolateY( double x0, double y0, double x1, double y1, double x ); // Find x at point y along the line from (x0,y0)-(x1,y1), y0 must != y1 extern double LinearInterpolateX( double x0, double y0, double x1, double y1, double y ); //---------------------------------------------------------------------------- // Constants //---------------------------------------------------------------------------- // defines wxArrayDouble for use as necessary #if !wxCHECK_VERSION(2,7,0) WX_DEFINE_USER_EXPORTED_ARRAY_DOUBLE(double, wxArrayDouble, class WXDLLIMPEXP_PLOTCTRL); #endif // wxNullPlotBounds = wxRect2DDouble(0,0,0,0) WXDLLIMPEXP_DATA_PLOTCTRL(extern const wxRect2DDouble) wxNullPlotBounds; extern wxBitmap wxPlotSymbolNormal; extern wxBitmap wxPlotSymbolActive; extern wxBitmap wxPlotSymbolSelected; enum wxPlotSymbol_Type { wxPLOTSYMBOL_ELLIPSE, wxPLOTSYMBOL_RECTANGLE, wxPLOTSYMBOL_CROSS, wxPLOTSYMBOL_PLUS, wxPLOTSYMBOL_MAXTYPE }; enum wxPlotPen_Type { wxPLOTPEN_NORMAL, wxPLOTPEN_ACTIVE, wxPLOTPEN_SELECTED, wxPLOTPEN_MAXTYPE }; #define wxPLOTCURVE_OPTION_FILENAME wxT("File.Name") #define wxPLOTCURVE_OPTION_EOLMODE wxT("EOL.Mode") #define wxPLOTCURVE_OPTION_MODIFIED wxT("Modified") #define wxPLOTCURVE_OPTION_HEADER wxT("Header") #define wxPLOTCURVE_OPTION_DATASEPARATOR wxT("Data.Separator") #define wxPLOTCURVE_DATASEPARATOR_SPACE wxT(" ") #define wxPLOTCURVE_DATASEPARATOR_COMMA wxT(",") #define wxPLOTCURVE_DATASEPARATOR_TAB wxT("\t") //---------------------------------------------------------------------------- // wxPlotCurveRefData - the wxObject::m_refData used for wxPlotCurves // this should be the base class for ref data for your subclassed curves // // The ref data is also of class wxClientDataContainer so that you can // attach arbitrary data to it //---------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotCurveRefData : public wxObjectRefData, public wxClientDataContainer { public: wxPlotCurveRefData(); wxPlotCurveRefData(const wxPlotCurveRefData& data); virtual ~wxPlotCurveRefData() {} void Copy(const wxPlotCurveRefData &source); wxRect2DDouble m_boundingRect; // bounds the curve or part to draw // if width or height <= 0 then no bounds wxArrayGenericPen m_pens; static wxArrayGenericPen sm_defaultPens; wxSortedArrayString m_optionNames; wxArrayString m_optionValues; }; //----------------------------------------------------------------------------- // wxPlotCurve - generic base plot curve class that must be subclassed for use // // GetY must be overridden as it "is" the curve //----------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotCurve: public wxObject { public: // see the remmed out code in this function if you subclass it wxPlotCurve(); virtual ~wxPlotCurve() {} // override as necessary so that Ok means that GetY works virtual bool Ok() const; // This *is* the output of the curve y = f(x) virtual double GetY( double WXUNUSED(x) ) { return 0.0; } // Bounding rect used for drawing the curve and... // if the width or height <= 0 then there's no bounds (or unknown) // wxPlotCurve/Function : may be unknown and should probably be (0,0,0,0) // you can limit the extent by setting to a smaller rect // wxPlotData : calculated from CalcBoundingRect and is well defined // DON'T call SetBoundingRect unless you know what you're doing virtual wxRect2DDouble GetBoundingRect() const; virtual void SetBoundingRect( const wxRect2DDouble &rect ); // Get/Set Pens for Normal, Active, Selected drawing // if these are not set it resorts to the defaults wxGenericPen GetPen(wxPlotPen_Type colour_type) const; void SetPen(wxPlotPen_Type colour_type, const wxGenericPen &pen); // Get/Set Default Pens for Normal, Active, Selected drawing for all curves // these are the pens that are used when a wxPlotCurve/Function/Data is created // default: Normal(0,0,0,1,wxSOLID), Active(0,0,255,1,wxSOLID), Selected(255,0,0,1,wxSOLID) static wxGenericPen GetDefaultPen(wxPlotPen_Type colour_type); static void SetDefaultPen(wxPlotPen_Type colour_type, const wxGenericPen &pen); //------------------------------------------------------------------------- // Get/Set Option names/values //------------------------------------------------------------------------- // Get the number of options set size_t GetOptionCount() const; // return the index of the option or wxNOT_FOUND (-1) int HasOption(const wxString& name) const; // Get the name/value at the index position wxString GetOptionName( size_t index ) const; wxString GetOptionValue( size_t index ) const; // Set an option, if update=true then force it, else only set it if not found // returns the index of the option int SetOption(const wxString& name, const wxString& value, bool update=true); int SetOption(const wxString& name, int option, bool update=true); // Get an option returns the index if found // returns wxNOT_FOUND (-1) if it doesn't exist and value isn't changed int GetOption(const wxString& name, wxString& value) const; // returns wxEmptyString if not found wxString GetOption(const wxString& name) const; // returns 0 if not found int GetOptionInt(const wxString& name) const; // get the arrays of option values wxArrayString GetOptionNames() const; wxArrayString GetOptionValues() const; //------------------------------------------------------------------------- // Get/Set the ClientData in the ref data - see wxClientDataContainer // You can store any extra info here. //------------------------------------------------------------------------- void SetClientObject( wxClientData *data ); wxClientData *GetClientObject() const; void SetClientData( void *data ); void *GetClientData() const; //------------------------------------------------------------------------- // operators bool operator == (const wxPlotCurve& plotCurve) const { return m_refData == plotCurve.m_refData; } bool operator != (const wxPlotCurve& plotCurve) const { return m_refData != plotCurve.m_refData; } wxPlotCurve& operator = (const wxPlotCurve& plotCurve) { if ( (*this) != plotCurve ) Ref(plotCurve); return *this; } private : // ref counting code virtual wxObjectRefData *CreateRefData() const; virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; DECLARE_DYNAMIC_CLASS(wxPlotCurve); }; #endif // _WX_PLOTCURVE_H_ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/plotdata.h0000644000076500007650000005007411350032206020722 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotdata.h // Purpose: wxPlotData container class for wxPlotCtrl // Author: John Labenski // Modified by: // Created: 12/1/2000 // Copyright: (c) John Labenski // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_PLOTDATA_H_ #define _WX_PLOTDATA_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "plotdata.h" #endif #include "wx/txtstrm.h" // for wxEOL #include "wx/plotctrl/plotcurv.h" #include "wx/plotctrl/plotfunc.h" class WXDLLIMPEXP_THINGS wxRangeIntSelection; //----------------------------------------------------------------------------- // wxPlotData consts and defines //----------------------------------------------------------------------------- // arbitray reasonable max size to avoid malloc errors #define wxPLOTDATA_MAX_SIZE 10000000 enum wxPlotDataLoad_Type { // store the header, ie. any #comment lines BEFORE the first line w/ valid data // use Get(Set)Header() to retrieve it wxPLOTDATA_LOAD_HEADER = 0x0001, // stop loading datafile if there is a blank line, will continue if a line is merely #commented out // ignores any blank lines before first line w/ data however wxPLOTDATA_LOAD_BREAKONBLANKLINE = 0x0010, // defaults used for loading a data file wxPLOTDATA_LOAD_DEFAULT = wxPLOTDATA_LOAD_HEADER | wxPLOTDATA_LOAD_BREAKONBLANKLINE }; //----------------------------------------------------------------------------- // wxPlotData // // Notes: // You must ALWAYS call CalcBoundingRect() after externally modifying the data // otherwise it might not be displayed properly in a wxPlotCtrl // //----------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotData : public wxPlotCurve { public: wxPlotData() : wxPlotCurve() {} wxPlotData( const wxPlotData& plotData ):wxPlotCurve() { Create(plotData); } wxPlotData( int points, bool zero = true ):wxPlotCurve() { Create(points, zero); } wxPlotData( double *x_data, double *y_data, int points, bool static_data = false ):wxPlotCurve() { Create( x_data, y_data, points, static_data ); } wxPlotData( const wxString &filename, int x_col, int y_col, int options = wxPLOTDATA_LOAD_DEFAULT ):wxPlotCurve() { LoadFile( filename, x_col, y_col, options ); } wxPlotData( const wxPlotFunction &plotFunc, double x_start, double dx, int points ):wxPlotCurve() { Create( plotFunc, x_start, dx, points ); } virtual ~wxPlotData() {} // Ref the source plotdata bool Create( const wxPlotData& plotData ); // Create from a wxPlotFunction // starting at x-start, with dx increment, for number of points bool Create( const wxPlotFunction &plotFunc, double x_start, double dx, int points ); // Allocate memory for given number of points, if zero then init to zeroes // don't use uninitialized data, trying to plot it will cause problems bool Create( int points, bool zero = true ); // Load plotdata from a file, see Loadfile bool Create( const wxString &filename, int x_col, int y_col, int options = wxPLOTDATA_LOAD_DEFAULT ) { return LoadFile( filename, x_col, y_col, options ); } // Assign the malloc(ed) data sets to this plotdata, // if !static_data they'll be free(ed) on destruction bool Create( double *x_data, double *y_data, int points, bool static_data = false ); // Make true (not refed) copy of this, // if copy_all = true then copy header, filename, pens, etc bool Copy( const wxPlotData &source, bool copy_all = false ); // Only copy the header, filename, pens, etc... from the source bool CopyExtra( const wxPlotData &source ); // Resize the data by appending or cropping points to/from the end // if zero then zero any added new points bool Resize( int new_size, bool zero = true ); // Resize the data by appending or cropping points to/from the end. // Sets created values with x starting from last point + dx in steps of // dx with a value of y. bool Resize( int new_size, double dx, double y ); // Append the source curve to the end, Yi data is copied only if both have it. wxPlotData Append(const wxPlotData &source) const; // Insert a the source curve at data index, Yi data is copied only if both have it. wxPlotData Insert(const wxPlotData &source, int index) const; // Delete a number of points in the curve, if count < 0 then delete to end // do not delete from 0 to end, it will assert, Destroy the data instead wxPlotData Remove(int index, int count = -1) const; // Get a sub-section of this curve from index of size count points. // if count < 0 then get data from index to end wxPlotData GetSubPlotData(int index, int count = -1) const; // Unref the data void Destroy(); // Is there data, has it been properly constructed? bool Ok() const; // Get the number of points in the data set int GetCount() const; // calc BoundingRect of the data and determine if X is ordered // ALWAYS call CalcBoundingRect after externally modifying the data, // especially if reording X quantities and using the wxPlotCtrl virtual void CalcBoundingRect(); // are consecutive x points always > than the previous ones bool GetIsXOrdered() const; //------------------------------------------------------------------------- // Load/Save, Filename, file header, saving options //------------------------------------------------------------------------- // Load a data file use # for comments and spaces, tabs, commas for column separators // if x_col or y_col is < 0 then if more than two cols pop-up a dialog to select // otherwise use col 1 and 2 or if only 1 col then // fill x with 0,1,2,3... // if x_col == y_col then fill y_col with data and x_col with 0,1,2,3... bool LoadFile( const wxString &filename, int x_col = -1, int y_col = -1, int options = wxPLOTDATA_LOAD_DEFAULT ); // Save a data file bool SaveFile( const wxString &filename, bool save_header = false, const wxString &format=wxT("%g") ); // Get/Set the filename was used for LoadFile or a previous SetFilename (if any) wxString GetFilename() const; void SetFilename( const wxString &filename ); // Get/Set the Header that from LoadFile or a previous call to SetHeader (if any) wxString GetHeader() const; void SetHeader( const wxString &header ); // Get/Set the EOL mode from LoadFile or a previous call to SetEOLMode (if any) wxEOL GetEOLMode() const; void SetEOLMode( wxEOL eol = wxEOL_NATIVE ); // Get/Set the column separator to use when loading or saving the data wxString GetDataColumnSeparator() const; void SetDataColumnSeparator(const wxString &separator = wxPLOTCURVE_DATASEPARATOR_SPACE); //------------------------------------------------------------------------- // Get/Set data values //------------------------------------------------------------------------- // Get a pointer to the data (call CalcBoundingRect afterwards if changing values) double *GetXData() const; double *GetYData() const; // imaginary Y data, not normally created, but if !NULL then it will be free()ed, see FFT double *GetYiData() const; // use (double*)malloc(sizeof(double)*GetCount()) to create // it'll be free()ed if the PlotData was NOT Created with existing arrays and static=true void SetYiData( double *yi_data ); // Get the point's value at this data index double GetXValue( int index ) const; double GetYValue( int index ) const; wxPoint2DDouble GetPoint( int index ) const; // Interpolate if necessary to get the y value at this point, // doesn't fail just returns ends if out of bounds double GetY( double x ); // Set the point at this data index, don't need to call CalcBoundingRect after void SetXValue( int index, double x ); void SetYValue( int index, double y ); void SetValue(int index, double x, double y); void SetPoint(int index, const wxPoint2DDouble &pt) { SetValue(index, pt.m_x, pt.m_y); } // Set a range of values starting at start_index for count points. // If count = -1 go to end of data void SetXValues( int start_index, int count = -1, double x = 0.0 ); void SetYValues( int start_index, int count = -1, double y = 0.0 ); // Set a range of values to be steps starting at x_start with dx increment // starts at start_index for count points, if count = -1 go to end void SetXStepValues( int start_index, int count = -1, double x_start = 0.0, double dx = 1.0 ); void SetYStepValues( int start_index, int count = -1, double y_start = 0.0, double dy = 1.0 ); enum Index_Type { index_round, index_floor, index_ceil }; // find the first occurance of an index whose value is closest (index_round), // or the next lower (index_floor), or next higher (index_ceil), to the given value // always returns a valid index int GetIndexFromX( double x, wxPlotData::Index_Type type = index_round ) const; int GetIndexFromY( double y, wxPlotData::Index_Type type = index_round ) const; // find the first occurance of an index whose value is closest to x,y // if x_range != 0 then limit search between +- x_range (useful for x-ordered data) int GetIndexFromXY( double x, double y, double x_range=0 ) const; // Find the average of the data starting at start_index for number of count points // if count < 0 then to to last point double GetAverage( int start_index = 0, int count = -1 ) const; // Get the minimum, maximum, and average x,y values for the ranges including // the indexes where the min/maxes occurred. // returns the number of points used. int GetMinMaxAve( const wxRangeIntSelection& rangeSel, wxPoint2DDouble* minXY, wxPoint2DDouble* maxXY, wxPoint2DDouble* ave, int *x_min_index, int *x_max_index, int *y_min_index, int *y_max_index ) const; // Returns array of indicies of nearest points where the data crosses the point y wxArrayInt GetCrossing( double y_value ) const; // Get the index of the first point with the min/max index value // if count == -1 then go to end of dataset int GetMinYIndex(int start_index = 0, int end_index = -1) const; int GetMaxYIndex(int start_index = 0, int end_index = -1) const; //------------------------------------------------------------------------- // Data processing functions //------------------------------------------------------------------------- // Add this offset to each data point (data += offset) void OffsetX( double offset, int start_index = 0, int end_index = -1 ); void OffsetY( double offset, int start_index = 0, int end_index = -1 ); void OffsetXY( double offsetX, double offsetY, int start_index = 0, int end_index = -1 ); // Scale the data, multiply by scale around offset value (data = (data-offset)*scale+offset) void ScaleX( double scale, double offset = 0.0, int start_index = 0, int end_index = -1 ); void ScaleY( double scale, double offset = 0.0, int start_index = 0, int end_index = -1 ); void ScaleXY( double scaleX, double scaleY, double offsetX = 0.0, double offsetY = 0.0, int start_index = 0, int end_index = -1 ); // Raise the data to the power void PowerX( double power, int start_index = 0, int end_index = -1 ); void PowerY( double power, int start_index = 0, int end_index = -1 ); void PowerXY( double powerX, double powerY, int start_index = 0, int end_index = -1 ); enum FuncModify_Type { add_x, add_y, mult_x, mult_y, add_yi, mult_yi }; wxPlotData Resample( double start_x, double dx, int points ) const; // Take the x values of the curve and resample this curve's x values to match // interpolates if necessary. Only for x ordered curves. // returns empty plotdata if ranges don't match wxPlotData Resample( const wxPlotData &source ) const; // Take the y-values of the wxPlotFunction curve at this curve's x-values // add_x adds function's y-values to this curve's x-values // add_y adds function's y-values to this curve's y-values // mult_x multiplies function's y-values to this curve's x-values // mult_y multiplies function's y-values to this curve's y-values wxPlotData Modify( const wxPlotFunction &func, FuncModify_Type type ) const; // Add y values of curves 1 (this) and 2, after multiplying each curve by their factors // interpolating between points if necessary, but outlying points are ignored // if factor1,2 are both 1.0 then strictly add them // if factor1 = -1 and factor2 = 1 then subtract this curve (1) from 2... wxPlotData Add( const wxPlotData &curve2, double factor1 = 1.0, double factor2 = 1.0 ) const; // Runaverage the data using a window of width number of points // use odd number, it'll make it odd anyway // points closer then width/2 to ends are not changed // averaging is performed between start_index for count # points, if count < 0 to end wxPlotData RunAverage( int width, int start_index=0, int count = -1 ) const; // Simple function that does fabs(y) on the data wxPlotData Abs() const; // Linearize the y-points (straight line) from start_index for count points // x-values are not changed wxPlotData LinearizeY(int start_index, int count = -1) const; // Simple derivitive y_(n+1) - y_(n) wxPlotData Derivitive() const; // Variance = SumOverN(sqrt(E(yn-)^2))/N double Variance(int start_index = 0, int count = -1) const; // returns a curve that is the variance at each point in a window of width wxPlotData VarianceCurve(int width) const; // Deviation = sqrt(E(y-y1)^2), don't divide by max-min+1 since double Deviation( const wxPlotData &other, int min=0, int max=-1 ) const; double CrossCorrelation( const wxPlotData &other, int runave=0, int min=0, int max=-1 ) const; // Tries to line up these two curves by shifting the other along the x-axis // it returns the x shift that gives the minimum deviation double MinShiftX( const wxPlotData &other ) const; // Fast Fourier Transform the data, forward = true for forward xform // note that the data size will be expanded to the smallest 2^n size that contains the data // the last point is replicated to fill it. // Since there are typically real and imaginary parts GetYiData() is now valid wxPlotData FFT( bool forward ); // Return the power spectrum of the FFT of the data wxPlotData PowerSpectrum(); enum FFTFilter_Type { FilterStep, FilterButterworth, FilterGaussian, FilterFermi }; // String representation of the equations of the FFT transform filters static wxString FFTHiPassFilterFormat( double fc, wxPlotData::FFTFilter_Type filter, double n = 5 ); static wxString FFTLoPassFilterFormat( double fc, wxPlotData::FFTFilter_Type filter, double n = 5 ); static wxString FFTNotchFilterFormat( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n = 5 ); static wxString FFTBandPassFilterFormat( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n = 5 ); // Use FFT to make either a high or a low pass filter, at fc = cutoff freq // The cutoff function is of type FFTFilter_Type // n is unused for FilterStep and FilterGaussian // the n for FilterButterworth & FilterFermi is typically an int > 1 // Butterworth filter 1.0/(1.0 + (f/fc)^2n) [n=1,2,3...] // where at fc the amplitude is 1/2 and n (order) determines the cutoff slope wxPlotData FFTHiPassFilter( double fc, wxPlotData::FFTFilter_Type filter, double n = 5 ); wxPlotData FFTLoPassFilter( double fc, wxPlotData::FFTFilter_Type filter, double n = 5 ); // Use FFT to make either a Notch filter (remove frequencies between low and high) or // a Band Pass (allow frequencies between low and high) filter // the cutoff can either be a step function, // or follow that of a Butterworth filter 1.0/(1.0 + (f/fc)^2n) [n=1,2,3...] wxPlotData FFTNotchFilter( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n = 5 ); wxPlotData FFTBandPassFilter( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n = 5 ); // After FFT this curve, apply the filter (mult y points at each x) and transform back wxPlotData FFTCustomFilter( const wxPlotFunction &func ); // Sorts the points by their x-values starting from the min to max bool SortByX(); // Sorts the points by their y-values starting from the min to max bool SortByY(); //------------------------------------------------------------------------- // Get/Set Symbols to use for plotting - CreateSymbol is untested // note: in MSW drawing bitmaps is sloooow! <-- so I haven't bothered finishing //------------------------------------------------------------------------- // Get the symbol used for marking data points wxBitmap GetSymbol(wxPlotPen_Type colour_type=wxPLOTPEN_NORMAL) const; // Set the symbol to some arbitray bitmap, make size odd so it can be centered void SetSymbol( const wxBitmap &bitmap, wxPlotPen_Type colour_type=wxPLOTPEN_NORMAL ); // Set the symbol from of the available types, using default colours if pen and brush are NULL void SetSymbol( wxPlotSymbol_Type type, wxPlotPen_Type colour_type=wxPLOTPEN_NORMAL, int width = 5, int height = 5, const wxPen *pen = NULL, const wxBrush *brush = NULL); // Get a copy of the symbol thats created for SetSymbol wxBitmap CreateSymbol( wxPlotSymbol_Type type, wxPlotPen_Type colour_type=wxPLOTPEN_NORMAL, int width = 5, int height = 5, const wxPen *pen = NULL, const wxBrush *brush = NULL); //----------------------------------------------------------------------- // Operators bool operator == (const wxPlotData& plotData) const { return m_refData == plotData.m_refData; } bool operator != (const wxPlotData& plotData) const { return m_refData != plotData.m_refData; } wxPlotData& operator = (const wxPlotData& plotData) { if ( (*this) != plotData ) Ref(plotData); return *this; } private: // ref counting code virtual wxObjectRefData *CreateRefData() const; virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; DECLARE_DYNAMIC_CLASS(wxPlotData) }; // ---------------------------------------------------------------------------- // Functions for getting/setting a wxPlotData to/from the wxClipboard // ---------------------------------------------------------------------------- #if wxUSE_DATAOBJ && wxUSE_CLIPBOARD // Try to get a wxPlotData from the wxClipboard, returns !Ok plotdata on failure wxPlotData wxClipboardGetPlotData(); // Set the plotdata curve into the wxClipboard, actually just sets a // wxPlotDataObject which is a string containing wxNow. The plotdata is not // actually copied to the clipboard since no other program could use it anyway. // returns sucess bool wxClipboardSetPlotData(const wxPlotData& plotData); // ---------------------------------------------------------------------------- // wxPlotDataObject - a wxClipboard object // ---------------------------------------------------------------------------- #include "wx/dataobj.h" //#define wxDF_wxPlotData (wxDF_MAX+1010) // works w/ GTK 1.2 non unicode extern const wxChar* wxDF_wxPlotData; // wxT("wxDF_wxPlotData"); class WXDLLIMPEXP_PLOTCTRL wxPlotDataObject : public wxTextDataObject { public: wxPlotDataObject(); wxPlotDataObject(const wxPlotData& plotData); wxPlotData GetPlotData() const; void SetPlotData(const wxPlotData& plotData); }; #endif // wxUSE_DATAOBJ && wxUSE_CLIPBOARD #endif // _WX_PLOTDATA_H_ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/plotdefs.h0000644000076500007650000000313211350032206020723 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotdefs.h // Purpose: Definitions for wxPlotLib // Author: John Labenski // Modified by: // Created: 1/08/2005 // RCS-ID: $Id$ // Copyright: (c) John Labenski // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// #ifndef __WX_PLOTDEF_H__ #define __WX_PLOTDEF_H__ #include "wx/defs.h" // ---------------------------------------------------------------------------- // DLLIMPEXP macros // ---------------------------------------------------------------------------- // These are our DLL macros (see the contrib libs like wxPlot) /* #ifdef WXMAKINGDLL_PLOTCTRL #define WXDLLIMPEXP_PLOTCTRL WXEXPORT #define WXDLLIMPEXP_DATA_PLOTCTRL(type) WXEXPORT type #elif defined(WXUSINGDLL) #define WXDLLIMPEXP_PLOTCTRL WXIMPORT #define WXDLLIMPEXP_DATA_PLOTCTRL(type) WXIMPORT type #else // not making nor using DLL */ #define WXDLLIMPEXP_PLOTCTRL #define WXDLLIMPEXP_DATA_PLOTCTRL(type) type /* #endif */ // ---------------------------------------------------------------------------- // Convenience macros // ---------------------------------------------------------------------------- // Check if value is >= min_val and <= max_val #define wxPCHECK_MINMAX_RET(val, min_val, max_val, msg) \ wxCHECK_RET((int(val)>=int(min_val))&&(int(val)<=int(max_val)), msg) #define wxPCHECK_MINMAX_MSG(val, min_val, max_val, ret, msg) \ wxCHECK_MSG((int(val)>=int(min_val))&&(int(val)<=int(max_val)), ret, msg) #endif // __WX_PLOTDEF_H__ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/plotdraw.h0000644000076500007650000001756311350032206020754 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotdraw.h // Purpose: wxPlotDrawer and friends // Author: John Labenski // Modified by: // Created: 6/5/2002 // Copyright: (c) John Labenski // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_PLOTDRAW_H_ #define _WX_PLOTDRAW_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "plotdraw.h" #endif #include "wx/defs.h" #include "wx/geometry.h" #include "wx/bitmap.h" #include "wx/plotctrl/plotdefs.h" #include "wx/plotctrl/plotcurv.h" #include "wx/plotctrl/plotdata.h" #include "wx/plotctrl/plotfunc.h" #include "wx/wxthings/range.h" class WXDLLEXPORT wxDC; class WXDLLIMPEXP_THINGS wxRangeIntSelection; class WXDLLIMPEXP_THINGS wxRangeDoubleSelection; class WXDLLIMPEXP_THINGS wxArrayRangeIntSelection; class WXDLLIMPEXP_THINGS wxArrayRangeDoubleSelection; class WXDLLIMPEXP_PLOTCTRL wxPlotCtrl; class WXDLLIMPEXP_PLOTCTRL wxPlotCurve; class WXDLLIMPEXP_PLOTCTRL wxPlotData; class WXDLLIMPEXP_PLOTCTRL wxPlotFunction; class WXDLLIMPEXP_PLOTCTRL wxPlotMarker; //----------------------------------------------------------------------------- // wxPlotDrawerBase //----------------------------------------------------------------------------- class wxPlotDrawerBase : public wxObject { public: wxPlotDrawerBase(wxPlotCtrl* owner) : wxObject(), m_owner(owner), m_pen_scale(1), m_font_scale(1) {} virtual void Draw(wxDC* dc, bool refresh) = 0; // Get/Set the owner plotctrl wxPlotCtrl* GetOwner() const { return m_owner; } void SetOwner(wxPlotCtrl* owner) { m_owner = owner; } // Get/Get the rect in the DC to draw on void SetDCRect(const wxRect& rect) { m_dcRect = rect; } const wxRect& GetDCRect() const { return m_dcRect; } // Get/Set the rect of the visible area in the plot window void SetPlotViewRect(const wxRect2DDouble& rect) { m_plotViewRect = rect; } const wxRect2DDouble& GetPlotViewRect() const { return m_plotViewRect; } // Get/Set the scaling for drawing, fonts, pens, etc are scaled void SetPenScale(double scale) { m_pen_scale = scale; } double GetPenScale() const { return m_pen_scale; } void SetFontScale(double scale) { m_font_scale = scale; } double GetFontScale() const { return m_font_scale; } protected: wxPlotCtrl* m_owner; wxRect m_dcRect; wxRect2DDouble m_plotViewRect; double m_pen_scale; // width scaling factor for pens double m_font_scale; // scaling factor for font sizes private: DECLARE_ABSTRACT_CLASS(wxPlotDrawerBase); }; //----------------------------------------------------------------------------- // wxPlotDrawerArea //----------------------------------------------------------------------------- class wxPlotDrawerArea : public wxPlotDrawerBase { public: wxPlotDrawerArea(wxPlotCtrl* owner) : wxPlotDrawerBase(owner) {} virtual void Draw(wxDC *dc, bool refresh); private: DECLARE_ABSTRACT_CLASS(wxPlotDrawerArea); }; //----------------------------------------------------------------------------- // wxPlotDrawerAxisBase //----------------------------------------------------------------------------- class wxPlotDrawerAxisBase : public wxPlotDrawerBase { public: wxPlotDrawerAxisBase(wxPlotCtrl* owner); virtual void Draw(wxDC *dc, bool refresh) = 0; void SetTickFont( const wxFont& font ) { m_tickFont = font; } void SetLabelFont( const wxFont& font ) { m_labelFont = font; } void SetTickColour( const wxGenericColour& colour ) { m_tickColour = colour; } void SetLabelColour( const wxGenericColour& colour ) { m_labelColour = colour; } void SetTickPen( const wxGenericPen& pen ) { m_tickPen = pen; } void SetBackgroundBrush( const wxGenericBrush& brush ) { m_backgroundBrush = brush; } void SetTickPositions( const wxArrayInt& pos ) { m_tickPositions = pos; } void SetTickLabels( const wxArrayString& labels ) { m_tickLabels = labels; } void SetLabel( const wxString& label ) { m_label = label; } // implementation wxArrayInt m_tickPositions; wxArrayString m_tickLabels; wxString m_label; wxFont m_tickFont; wxFont m_labelFont; wxGenericColour m_tickColour; wxGenericColour m_labelColour; wxGenericPen m_tickPen; wxGenericBrush m_backgroundBrush; private: DECLARE_ABSTRACT_CLASS(wxPlotDrawerAxisBase); }; //----------------------------------------------------------------------------- // wxPlotDrawerXAxis //----------------------------------------------------------------------------- class wxPlotDrawerXAxis : public wxPlotDrawerAxisBase { public: wxPlotDrawerXAxis(wxPlotCtrl* owner) : wxPlotDrawerAxisBase(owner) {} virtual void Draw(wxDC *dc, bool refresh); private: DECLARE_ABSTRACT_CLASS(wxPlotDrawerXAxis); }; //----------------------------------------------------------------------------- // wxPlotDrawerYAxis //----------------------------------------------------------------------------- class wxPlotDrawerYAxis : public wxPlotDrawerAxisBase { public: wxPlotDrawerYAxis(wxPlotCtrl* owner) : wxPlotDrawerAxisBase(owner) {} virtual void Draw(wxDC *dc, bool refresh); private: DECLARE_ABSTRACT_CLASS(wxPlotDrawerYAxis); }; //----------------------------------------------------------------------------- // wxPlotDrawerKey //----------------------------------------------------------------------------- class wxPlotDrawerKey : public wxPlotDrawerBase { public: wxPlotDrawerKey(wxPlotCtrl* owner); virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused virtual void Draw(wxDC *dc, const wxString& keyString); void SetFont(const wxFont& font) { m_font = font; } void SetFontColour(const wxGenericColour& colour) { m_fontColour = colour; } void SetKeyPosition(const wxPoint& pos) { m_keyPosition = pos; } // implementation wxFont m_font; wxGenericColour m_fontColour; wxPoint m_keyPosition; bool m_key_inside; int m_border; int m_key_line_width; // length of line to draw for curve int m_key_line_margin; // margin between line and key text private: DECLARE_ABSTRACT_CLASS(wxPlotDrawerKey); }; //----------------------------------------------------------------------------- // wxPlotDrawerCurve //----------------------------------------------------------------------------- class wxPlotDrawerCurve : public wxPlotDrawerBase { public: wxPlotDrawerCurve(wxPlotCtrl* owner) : wxPlotDrawerBase(owner) {} virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused virtual void Draw(wxDC *dc, wxPlotCurve *curve, int curve_index); private: DECLARE_ABSTRACT_CLASS(wxPlotDrawerCurve); }; //----------------------------------------------------------------------------- // wxPlotDrawerDataCurve //----------------------------------------------------------------------------- class wxPlotDrawerDataCurve : public wxPlotDrawerBase { public: wxPlotDrawerDataCurve(wxPlotCtrl* owner) : wxPlotDrawerBase(owner) {} virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused virtual void Draw(wxDC *dc, wxPlotData* plotData, int curve_index); private: DECLARE_ABSTRACT_CLASS(wxPlotDrawerDataCurve); }; //----------------------------------------------------------------------------- // wxPlotDrawerMarkers //----------------------------------------------------------------------------- class wxPlotDrawerMarker : public wxPlotDrawerBase { public: wxPlotDrawerMarker(wxPlotCtrl* owner) : wxPlotDrawerBase(owner) {} virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused virtual void Draw(wxDC *dc, const wxArrayPlotMarker& markers); virtual void Draw(wxDC *dc, const wxPlotMarker& marker); private: DECLARE_ABSTRACT_CLASS(wxPlotDrawerMarker); }; #endif // _WX_PLOTDRAW_H_ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/plotfunc.h0000644000076500007650000001063611350032206020744 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotfunc.h // Purpose: wxPlotFunction curve for wxPlotCtrl // Author: John Labenski // Modified by: // Created: 12/1/2000 // Copyright: (c) John Labenski // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_PLOTFUNC_H_ #define _WX_PLOTFUNC_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "plotfunc.h" #endif #include "wx/plotctrl/plotcurv.h" //----------------------------------------------------------------------------- // wxPlotFunction - a compiled string function parsing PlotCurve // // see fparser.txt to see function string capability // vars is "x" or "x,y" where x and y are the vars used in the function string // //----------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotFunction: public wxPlotCurve { public: wxPlotFunction() : wxPlotCurve() {} wxPlotFunction(const wxPlotFunction &curve) : wxPlotCurve() { Create(curve); } wxPlotFunction(const wxString &function, const wxString &vars = wxT("x"), bool useDegrees = false) : wxPlotCurve() { Create(function, vars, useDegrees); } virtual ~wxPlotFunction() {} // Initialize curve, returns -1 on sucess and errormsg is wxEmptyString. // On error, the errormsg contains a message and the character location // in the 'function' string where the error occurred is returned. // Check if errormsg != wxEmptyString, or curve.Ok() not the returned int // vars is a comma delimited list of variables used in the function "x,y,z" // vars can be wxEmptyString, see GetValue(NULL), the function is a constant int Create( const wxString &function, const wxString &vars = wxT("x"), bool useDegrees = false ); // Make a copy of the other plotFunction bool Create( const wxPlotFunction &curve ); bool Ok() const; void Destroy(); // Parse and use the function, see Create, does not destroy refdata int Parse( const wxString &function, const wxString &vars = wxT("x"), bool useDegrees = false ); // Get the strings sent to Create wxString GetFunctionString() const; // the function string "a*(b+3)/2 + c" wxString GetVariableString() const; // the variable string "a,b,c" wxString GetVariableName(size_t n) const; // a single variable name n=0="a" int GetNumberVariables() const; bool GetUseDegrees() const; // was this created to use degrees? // Get an error message (if any) if Create does not return -1 false wxString GetErrorMsg() const; // Get the f(x) value from the function parser, use this if only have x variable double GetY( double x ); // Get the f(x,y...) using an arbitrary number of vars // you absolutely MUST pass double x[GetNumberVariables()] // if you sent in a wxEmptyString for the vars then use NULL double GetValue( double *x ); // add a constant to use bool AddConstant(const wxString& name, double value); bool operator == (const wxPlotFunction& plotFunc) const { return m_refData == plotFunc.m_refData; } bool operator != (const wxPlotFunction& plotFunc) const { return m_refData != plotFunc.m_refData; } wxPlotFunction& operator = (const wxPlotFunction& plotFunc) { if ( (*this) != plotFunc ) Ref(plotFunc); return *this; } private : // ref counting code virtual wxObjectRefData *CreateRefData() const; virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; DECLARE_DYNAMIC_CLASS(wxPlotFunction); }; //----------------------------------------------------------------------------- // Functions for getting/setting a wxPlotFunction to/from the wxClipboard //----------------------------------------------------------------------------- #if wxUSE_DATAOBJ && wxUSE_CLIPBOARD // Try to get a wxPlotFunction from the wxClipboard, return !Ok plotfunction on failure wxPlotFunction wxClipboardGetPlotFunction(); // Set the plot function curve into the clipboard. Copies function and vars string // separated by a ';' as a text object, use wxString::Before/AfterLast(wxT(';')). // returns sucess bool wxClipboardSetPlotFunction(const wxPlotFunction& plotFunction); #endif // wxUSE_DATAOBJ && wxUSE_CLIPBOARD #endif // _WX_PLOTFUNC_H_ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/plotmark.h0000644000076500007650000002037311350032206020742 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotmark.h // Purpose: wxPlotMarker // Author: John Labenski // Modified by: // Created: 6/5/2002 // Copyright: (c) John Labenski // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_PLOTMARK_H_ #define _WX_PLOTMARK_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "plotmark.h" #endif #include "wx/bitmap.h" #include "wx/geometry.h" #include "wx/plotctrl/plotdefs.h" #include "wx/wxthings/genergdi.h" class WXDLLIMPEXP_PLOTCTRL wxPlotCtrl; class WXDLLIMPEXP_PLOTCTRL wxPlotMarker; WX_DECLARE_OBJARRAY_WITH_DECL(wxPlotMarker, wxArrayPlotMarker, class WXDLLIMPEXP_PLOTCTRL); //----------------------------------------------------------------------------- // wxPlotMarker - a marker to draw in the plot window // This is a catch all class, containing info to draw various marker types. // Therefore, some parts may not be used for some markers. // Use a two part construction to ensure it's created properly // wxPlotMarker marker; marker.CreateXXX(...) //----------------------------------------------------------------------------- enum wxPlotMarkerType { wxPLOTMARKER_NONE, // invalid, don't draw it wxPLOTMARKER_POINT, // single pixel point, only position & pen used // size, brush, bitmap unused wxPLOTMARKER_LINE, // line from upper left to lower right of rect // rect may be inverted to draw at any angle // size, brush, bitmap unused wxPLOTMARKER_HORIZ_LINE,// horizontal line, full width // only vert position and pen used // size, brush, bitmap unused wxPLOTMARKER_VERT_LINE, // vertical line, full height // only horiz position and pen used // size, brush, bitmap unused wxPLOTMARKER_CROSS, // vertical and horizontal line, full height & width // position used for center of cross // size, brush, bitmap unused wxPLOTMARKER_RECT, // rectangle - see plot rect conditions // pen draws outline and brush fills (if set) // bitmap unused // rect drawn centered on position // size is size of the rect wxPLOTMARKER_ELLIPSE, // ellipse - see plot rect conditions wxPLOTMARKER_BITMAP // the bitmap is drawn at the position }; class WXDLLIMPEXP_PLOTCTRL wxPlotMarker : public wxObject { public: wxPlotMarker() : wxObject() {} // Create a full marker (see CreateXXX functions) wxPlotMarker(int marker_type, const wxRect2DDouble& rect, const wxSize& size, const wxGenericPen& pen, const wxGenericBrush& brush = wxNullGenericBrush, const wxBitmap& bitmap = wxNullBitmap) : wxObject() { Create(marker_type, rect, size, pen, brush, bitmap); } // Create a shape marker to be drawn at the point with the given size // in pixels wxPlotMarker(int marker_type, const wxPoint2DDouble& pt, const wxSize& size, const wxGenericPen& pen, const wxGenericBrush& brush = wxNullGenericBrush) : wxObject() { Create(marker_type, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), size, pen, brush); } // Create a bitmap marker wxPlotMarker(const wxPoint2DDouble& pt, const wxBitmap& bitmap) : wxObject() { CreateBitmapMarker(pt, bitmap); } virtual ~wxPlotMarker() {} // is the marker created bool Ok() const { return m_refData != NULL; } // Generic create function void Create(int marker_type, const wxRect2DDouble& rect, const wxSize& size, const wxGenericPen& pen, const wxGenericBrush& brush = wxNullGenericBrush, const wxBitmap& bitmap = wxNullBitmap); // Simplified methods (use these) void CreatePointMarker(const wxPoint2DDouble& pt, const wxGenericPen& pen) { Create(wxPLOTMARKER_POINT, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), wxSize(-1, -1), pen); } void CreateLineMarker(const wxRect2DDouble& rect, const wxGenericPen& pen) { Create(wxPLOTMARKER_LINE, rect, wxSize(-1, -1), pen); } void CreateHorizLineMarker(double y, const wxGenericPen& pen) { Create(wxPLOTMARKER_HORIZ_LINE, wxRect2DDouble(0, y, -1, 0), wxSize(-1, -1), pen); } void CreateVertLineMarker(double x, const wxGenericPen& pen) { Create(wxPLOTMARKER_VERT_LINE, wxRect2DDouble(x, 0, 0, -1), wxSize(-1, -1), pen); } void CreateRectMarker(const wxRect2DDouble& rect, const wxGenericPen& pen, const wxGenericBrush& brush = wxNullGenericBrush) { Create(wxPLOTMARKER_RECT, rect, wxSize(-1, -1), pen, brush); } void CreateRectMarker(const wxPoint2DDouble& pt, const wxSize& size, const wxGenericPen& pen, const wxGenericBrush& brush = wxNullGenericBrush) { Create(wxPLOTMARKER_RECT, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), size, pen, brush); } // void CreateEllipseMarker(const wxRect2DDouble& rect, // const wxGenericPen& pen, // const wxGenericBrush& brush = wxNullGenericBrush) // { Create(wxPLOTMARKER_ELLIPSE, rect, wxSize(-1, -1), pen, brush); } void CreateEllipseMarker(const wxPoint2DDouble& pt, const wxSize& size, const wxGenericPen& pen, const wxGenericBrush& brush = wxNullGenericBrush) { Create(wxPLOTMARKER_ELLIPSE, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), size, pen, brush); } void CreateBitmapMarker(const wxPoint2DDouble& pt, const wxBitmap& bitmap) { Create(wxPLOTMARKER_BITMAP, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), wxSize(-1, -1), wxNullGenericPen, wxNullGenericBrush, bitmap); } // Get/Set the marker type int GetMarkerType() const; void SetMarkerType(int type); // Get/Set the rect to draw the marker into // The meaning of the rect is different for each marker type // // Bitmap markers // Drawn centered at upper left if width = height = 0 // Drawn into the rect and scaled if width & height != 0 // // Shape markers // Draws a full rect/ellipse if width & height > 0 // Draws a point if width & height = 0 // Draws a vertical line if width = 0 & height != 0 // Draws a horizontal line if height = 0 & width != 0 // Draws the full width if width < 0 // Draws the full height if height < 0 wxRect2DDouble GetPlotRect() const; wxRect2DDouble& GetPlotRect(); void SetPlotRect(const wxRect2DDouble& rect); wxPoint2DDouble GetPlotPosition() const; void SetPlotPosition(const wxPoint2DDouble& pos); // for rect/ellipse markers you can set the size in pixels wxSize GetSize() const; void SetSize(const wxSize& size); // Get/Set the pen to draw the lines with wxGenericPen GetPen() const; void SetPen(const wxGenericPen& pen); // Get/Set the brush to fill the area with (null for none) wxGenericBrush GetBrush() const; void SetBrush(const wxGenericBrush& brush); // Get/Set the bitmap to draw (null for none, ignored if not wxPLOTMARKER_BITMAP) wxBitmap GetBitmap() const; void SetBitmap(const wxBitmap& bitmap); // operators bool operator == (const wxPlotMarker& pm) const { return m_refData == pm.m_refData; } bool operator != (const wxPlotMarker& pm) const { return m_refData != pm.m_refData; } wxPlotMarker& operator = (const wxPlotMarker& pm) { if ( (*this) != pm ) Ref(pm); return *this; } private: // ref counting code virtual wxObjectRefData *CreateRefData() const; virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; DECLARE_DYNAMIC_CLASS(wxPlotMarker); }; #endif // _WX_PLOTMARK_H_ gambit-0.2010.09.01/src/labenski/include/wx/plotctrl/plotprnt.h0000644000076500007650000000547711350032206021003 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotprnt.h // Purpose: wxPlotPrintout // Author: John Labenski // Modified by: // Created: 6/5/2002 // Copyright: (c) John Labenski // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_PLOTPRINT_H_ #define _WX_PLOTPRINT_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "plotprnt.h" #endif #include "wx/print.h" #include "wx/plotctrl/plotdefs.h" class WXDLLIMPEXP_PLOTCTRL wxPlotCtrl; //----------------------------------------------------------------------------- // wxPlotPrintout - simple mechanism to print the contents of the wxPlotCtrl // on a single page //----------------------------------------------------------------------------- class WXDLLIMPEXP_PLOTCTRL wxPlotPrintout : public wxPrintout { public: wxPlotPrintout(wxPlotCtrl* plotWin, const wxString &title = wxEmptyString); bool OnPrintPage(int page); bool HasPage(int page) { return page == 1; } bool OnBeginDocument(int startPage, int endPage); void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) { if (minPage) *minPage = 1; if (maxPage) *maxPage = 1; if (selPageFrom) *selPageFrom = 1; if (selPageTo) *selPageTo = 1; } // Simplified methods to show the standard print dialogs bool ShowPrintDialog(); bool ShowPrintPreviewDialog(const wxString& frameTitle = wxT("Plot print preview")); bool ShowPrintSetupDialog(); bool ShowPrintPageSetupDialog(); wxPlotCtrl *GetPlotCtrl() const { return m_plotWin; } // Get/Set the wxPrintData/wxPageSetupData that will be used // if NULL then one will be created on first use and deleted when the // program exits. It may make sense to create a single instance of your // printdata in the wxApp for all your program's printing needs and use // SetPrintData/PageSetupData to share it with this. static wxPrintData *GetPrintData(bool create_on_demand = false); static wxPageSetupData *GetPageSetupData(bool create_on_demand = false); static bool GetPrintDataStatic(); static bool GetPageSetupDataStatic(); // Set the wxPrintData/PageSetupData, if !is_static then it will be deleted // when the program exits static void SetPrintData( wxPrintData *printData, bool is_static ); static void SetPageSetupData( wxPageSetupData *pageSetupData, bool is_static ); protected: wxPlotCtrl *m_plotWin; static wxPrintData *s_wxPlotPrintData; static wxPageSetupData *s_wxPlotPageSetupData; static bool s_wxPlotPrintdata_static; static bool s_wxPlotPagesetupdata_static; private: DECLARE_ABSTRACT_CLASS(wxPlotPrintout) }; #endif // _WX_PLOTPRINT_H_ gambit-0.2010.09.01/src/labenski/include/wx/sheet/0000777000076500007650000000000011441457114016276 500000000000000gambit-0.2010.09.01/src/labenski/include/wx/sheet/pairarr.h0000644000076500007650000003345311350032206020021 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: pairarr.h // Purpose: Sorted Key/Value pairs of wxArrays using a binary search lookup // Author: John Labenski // Modified by: // Created: 1/08/2004 // RCS-ID: $Id$ // Copyright: (c) John Labenski // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_PAIRARR_H__ #define __WX_PAIRARR_H__ // Note: there is no cpp file as all the code is contained in these macros. #include "wx/dynarray.h" // ============================================================================ // Provides macros for creating your own (key, value) pair arrays using a binary // search to insert/retrieve values using a key. While this doesn't have the // performance of a good hash table O(n), it is smaller and with a lookup speed // O(log(n)) is suitable for some applications. You can use virtually any // class for keys and values that can be put into wxArrays so long as they // define the standard comparison operators ==, <, >, <=, >=. // // Implementation note: I've chosen to use two independent arrays instead of // a single array of a data struct with (key, value) members to squeeze out the // slightest increase in performance. // ---------------------------------------------------------------------------- // DECLARE_PAIRED_DATA_ARRAYS(Tkey, TkeyArray, Tval, TvalArray, name, classexp) // DEFINE_PAIRED_DATA_ARRAYS(Tkey, Tval, name) // Tkey must have the operators =, ==, <, >, <=, >= // They'll be sorted by using the <, >, <=, >= operators // Tval must have a default constructor and be able to be passed as const Tval& val // You must have created wx(Object)Arrays of Tkey with name TkeyArray // and of Tval named TvalArray, for example wxArrayInt and wxArrayString // // Creates a class named "name" that manages the TkeyArray, TvalArray data. // It keeps the pairs sorted in order of Tkey and uses a binary search // to retrieve and set the values. // // ---------------------------------------------------------------------------- // DECLARE_PAIRED_INT_DATA_ARRAYS(Tval, TvalArray, name, classexp) // DEFINE_PAIRED_INT_DATA_ARRAYS(Tval, name) // Tkey is an int (wxArrayInt), Tval may be anything // UpdatePos(int pos, int num) is added for inserting if num > 0 and // deleting if num < 0. The keys above pos are shifted. // // ---------------------------------------------------------------------------- // name() - default constructor // name(const Tval& defaultVal) - initialize the class with the default value, // see Get/SetDefaultValue to change it later. // name(const name& other) - full copy constructor // name(Tkey key, const Tval& val) - create with the first pair // int GetCount() - get the number of pairs // int FindIndex(Tkey) - find this key returning position in pair array or wxNOT_FOUND // size_t FindInsertIndex(Tkey) - find array position to insert key at, returns // GetCount for append (check first in case count=0), the pos to insert // before, or the pos with existing key (see SetValue for code) // bool HasKey(Tkey) - does this key exist // Tval& GetValue(Tkey) - get the value for this key or it it doesn't exist // the default value, see also Get/SetDefaultValue. // Tval& GetOrCreateValue(Tkey key) - get or create a GetDefaultValue() value for this key // void SetValue(Tkey, Tval) - set the Tval for this Tkey, replacing if exists // bool RemoveValue(Tkey) - remove pair with this Tkey, returns if it existed // void Clear() - clears the pair arrays // const Tval& GetItemValue(index) const - get the Tval at this array index // const Tkey& GetItemKey(index) const - get the Tkey at this array index // Tval& GetItemValue(index) - get the Tval at this array index // Tkey& GetItemKey(index) - get the Tkey at this array index // void RemoveAt(index) - remove the key and value at this array index // TvalArray& GetValues() - get the TvalArray // TkeyArray& GetKeys() - get the TkeyArray (don't unsort them) // const Tval& GetDefaultValue() const - get the default value to return for // GetValue(Tkey) when the key doesn't exist. (inits to Tval()) // void SetDefaultValue(const Tval& val) - set the default value to return for // GetValue(Tkey) when the key doesn't exist. If your values don't have a // default constructor (eg. ints) you'll want to set this. // void Copy(const name& other) - make full copy of other // void Sort() - sort the pairs by the keys (only necessary if you want to // quickly add unorderered pairs using GetKeys().Add(x); GetValues().Add(x);) // You MUST keep them sorted for the lookup mechanism to work. // name& operator=(const name& other) - make full copy of other // // ---------------------------------------------------------------------------- // DECLARE_PAIRED_INT_DATA_ARRAYS - added functions // bool UpdatePos(int pos, int numPos) - // if numPos > 0 - shifts keys greater than pos by numPos // if numPos < 0 - deletes keys between pos and pos-numPos, // shifts keys greater than by pos-numPos by -numPos // // ============================================================================ // Examples: // // 1.) For string arrays you'll write this in the header // DECLARE_PAIRED_DATA_ARRAYS(wxString, wxArrayString, wxString, wxArrayString, // wxPairArrayStringString, class WXDLLIMPEXP_ADV) // And this code in some cpp file. // DEFINE_PAIRED_DATA_ARRAYS(wxString, wxString, wxPairArrayStringString) // // 2.) For int pairs and wxString values, write this in your header // DECLARE_PAIRED_INT_DATA_ARRAYS(wxString, wxArrayString, // wxPairArrayIntSheetString, class WXDLLIMPEXP_ADV) // // You can even make nested pair arrays, 2D arrays (wxSheetStringSparseTable) // WX_DECLARE_OBJARRAY_WITH_DECL(wxPairArrayIntSheetString, // wxArrayPairArrayIntSheetString, // class WXDLLIMPEXP_ADV); // DECLARE_PAIRED_INT_DATA_ARRAYS(wxPairArrayIntSheetString, wxArrayPairArrayIntSheetString, // wxPairArrayIntPairArraySheetStringBase, class WXDLLIMPEXP_ADV) // // In your source file write this to get the code for the pair array // DEFINE_PAIRED_INT_DATA_ARRAYS(wxString, wxPairArrayIntSheetString) // DEFINE_PAIRED_INT_DATA_ARRAYS(wxPairArrayIntSheetString, // wxPairArrayIntPairArraySheetStringBase) // // ============================================================================ #define DECLARE_PAIRED_DATA_ARRAYS_BASE(Tkey, TkeyArray, Tval, TvalArray, name, classexp) \ \ classexp name \ { \ public: \ name() {} \ name(const Tval& defaultVal) : m_defaultValue(defaultVal) {} \ name(const name& other) { Copy(other); } \ name(const Tkey& key, const Tval& val) { m_keys.Add(key); m_values.Add(val); } \ int GetCount() const { return m_keys.GetCount(); } \ int FindIndex(const Tkey& key) const; \ size_t FindInsertIndex(const Tkey& pos) const; \ bool HasKey(const Tkey& key) const { return FindIndex(key) != wxNOT_FOUND; } \ const Tval& GetValue(const Tkey& key) const; \ Tval& GetValue(const Tkey& key); \ Tval& GetOrCreateValue(const Tkey& key); \ void SetValue(const Tkey& key, const Tval& value); \ bool RemoveValue(const Tkey& key); \ void Clear() { m_keys.Clear(); m_values.Clear(); } \ const Tval& GetItemValue(size_t index) const { return m_values[index]; } \ const Tkey& GetItemKey(size_t index) const { return m_keys[index]; } \ Tval& GetItemValue(size_t index) { return m_values[index]; } \ Tkey& GetItemKey(size_t index) { return m_keys[index]; } \ void RemoveAt(size_t index) { m_keys.RemoveAt(index); m_values.RemoveAt(index); } \ const TvalArray& GetValues() const { return m_values; } \ const TkeyArray& GetKeys() const { return m_keys; } \ TvalArray& GetValues() { return m_values; } \ TkeyArray& GetKeys() { return m_keys; } \ const Tval& GetDefaultValue() const { return m_defaultValue; } \ void SetDefaultValue(const Tval& val) { m_defaultValue = val; } \ void Copy(const name& other); \ void Sort() { if (GetCount() > 1) q_sort(0, GetCount()-1); } \ name& operator=(const name& other) { Copy(other); return *this; } \ protected : \ void q_sort(int left, int right); \ TkeyArray m_keys; \ TvalArray m_values; \ Tval m_defaultValue; // ---------------------------------------------------------------------------- // Note: The above macros is incomplete to allow you to extend the class. #define DECLARE_PAIRED_DATA_ARRAYS(Tkey, TkeyArray, Tval, TvalArray, name, classexp) \ DECLARE_PAIRED_DATA_ARRAYS_BASE(Tkey, TkeyArray, Tval, TvalArray, name, classexp) \ }; #define DECLARE_PAIRED_INT_DATA_ARRAYS_BASE(Tval, TvalArray, name, classexp) \ DECLARE_PAIRED_DATA_ARRAYS_BASE(int, wxArrayInt, Tval, TvalArray, name, classexp) \ public: \ bool UpdatePos( int pos, int numPos ); #define DECLARE_PAIRED_INT_DATA_ARRAYS(Tval, TvalArray, name, classexp) \ DECLARE_PAIRED_INT_DATA_ARRAYS_BASE(Tval, TvalArray, name, classexp) \ }; // ============================================================================ #define DEFINE_PAIRED_DATA_ARRAYS(Tkey, Tval, name) \ \ const Tval& name::GetValue(const Tkey& key) const \ { \ const int n = FindIndex(key); \ if (n != wxNOT_FOUND) return m_values[n]; \ return m_defaultValue; \ } \ Tval& name::GetValue(const Tkey& key) \ { \ const int n = FindIndex(key); \ if (n != wxNOT_FOUND) return m_values[n]; \ return m_defaultValue; \ } \ Tval& name::GetOrCreateValue(const Tkey& key) \ { \ const size_t n = FindInsertIndex(key); \ if (n == m_keys.GetCount()) \ { m_keys.Add(key); m_values.Add(Tval(m_defaultValue)); } \ else if (key != m_keys[n]) \ { m_keys.Insert(key, n); m_values.Insert(Tval(m_defaultValue), n); } \ return m_values[n]; \ } \ void name::SetValue(const Tkey& key, const Tval& value) \ { \ const size_t n = FindInsertIndex(key); \ if (n == m_keys.GetCount()) \ { m_keys.Add(key); m_values.Add(value); } \ else if (key == m_keys[n]) \ m_values[n] = value; \ else \ { m_keys.Insert(key, n); m_values.Insert(value, n); } \ } \ bool name::RemoveValue(const Tkey& key) \ { \ const int n = FindIndex(key); \ if (n != wxNOT_FOUND) { RemoveAt(n); return true; } \ return false; \ } \ int name::FindIndex(const Tkey& key) const \ { \ size_t n, lo = 0, hi = m_keys.GetCount(); \ while ( lo < hi ) \ { \ n = (lo + hi)/2; \ const Tkey &tmp = m_keys[n]; \ if (tmp == key) return n; \ if (tmp > key) hi = n; \ else lo = n + 1; \ } \ return wxNOT_FOUND; \ } \ size_t name::FindInsertIndex(const Tkey& key) const \ { \ size_t n, lo = 0, hi = m_keys.GetCount(); \ while ( lo < hi ) \ { \ n = (lo + hi)/2; \ const Tkey &tmp = m_keys[n]; \ if (tmp == key) return n; \ if (tmp > key) hi = n; \ else lo = n + 1; \ } \ return lo; \ } \ void name::Copy(const name& other) \ { \ m_keys = other.GetKeys(); \ m_values = other.GetValues(); \ m_defaultValue = other.GetDefaultValue(); \ } \ void name::q_sort(int left, int right) \ { \ int l_hold = left, r_hold = right; \ Tkey pivot = m_keys[left]; Tval pivotVal = m_values[left]; \ while (left < right) \ { \ while ((m_keys[right] >= pivot) && (left < right)) right--; \ if (left != right) { m_keys[left] = m_keys[right]; \ m_values[left] = m_values[right]; left++; } \ while ((m_keys[left] <= pivot) && (left < right)) left++; \ if (left != right) { m_keys[right] = m_keys[left]; \ m_values[right] = m_values[left]; right--; } \ } \ m_keys[left] = pivot; m_values[left] = pivotVal; \ if (l_hold < left) q_sort(l_hold, left-1); \ if (r_hold > left) q_sort(left+1, r_hold); \ } // ---------------------------------------------------------------------------- #define DEFINE_PAIRED_INT_DATA_ARRAYS(Tval, name) \ DEFINE_PAIRED_DATA_ARRAYS(int, Tval, name) \ bool name::UpdatePos( int pos, int numPos ) \ { \ int n, count = m_keys.GetCount(), start_pos = FindInsertIndex(pos); \ if ((numPos == 0) || (start_pos >= count)) return false; \ if ( numPos > 0 ) \ { \ for (n=start_pos; n= pos_right) { k += numPos; } \ } \ } \ return true; \ } #endif // __WX_PAIRARR_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/sheet.h0000644000076500007650000024323211350032206017467 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheet.h // Purpose: wxSheet and related classes // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) // Modified by: John Labenski // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski, Michael Bedward // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_SHEET_H__ #define __WX_SHEET_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "sheet.h" #endif #include "wx/sheet/sheetdef.h" // Always include sheetdef.h first #include "wx/sheet/sheetatr.h" // might as well include everything #include "wx/sheet/sheetsel.h" #include "wx/sheet/sheetedt.h" #include "wx/sheet/sheetren.h" #include "wx/sheet/sheettbl.h" #include "wx/sheet/sheetedg.h" #include "wx/window.h" #include "wx/scrolbar.h" #include "wx/clntdata.h" class WXDLLEXPORT wxTimer; class WXDLLEXPORT wxTimerEvent; // ---------------------------------------------------------------------------- // wxSheetChildWindow - a child window of the wxSheet, forwards events to sheet // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetChildWindow : public wxWindow { public: wxSheetChildWindow( wxSheet *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = wxWANTS_CHARS|wxBORDER_NONE|wxCLIP_CHILDREN, //|wxFULL_REPAINT_ON_RESIZE ) // FIXME const wxString& name = wxT("wxSheetChildWindow") ); // implementation void OnPaint( wxPaintEvent& event ); void OnMouse( wxMouseEvent& event ); void OnKeyAndChar( wxKeyEvent& event ); void OnFocus( wxFocusEvent& event ); void OnEraseBackground( wxEraseEvent& ); wxSheet* GetOwner() const { return m_owner; } wxSheet *m_owner; int m_mouseCursor; // remember the last cursor set for this window private: DECLARE_ABSTRACT_CLASS(wxSheetChildWindow) DECLARE_EVENT_TABLE() DECLARE_NO_COPY_CLASS(wxSheetChildWindow) }; //----------------------------------------------------------------------------- // wxSheetRefData - ref counted data to share with refed wxSheets // // Please use accessors in the wxSheet to adjust the values, for very // complicated scenarios adjust these as a last resort. // // This is separated from the wxSheetTable since these are required for the // sheet and the table may not have been assigned yet. // // This MUST always exist as the wxObject::m_refData of the wxSheet. It is // automatically created in wxSheet::Init, if you wish to use your own // subclassed refdata then in your wxSheet constructor (or Create) function call // UnRef to delete the original and m_refData=new MySheetRefData to set the new. //----------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetRefData : public wxObjectRefData { public: wxSheetRefData(); virtual ~wxSheetRefData(); // Find/Add/Remove sheets that share this data - used for wxSheetSplitter int FindSheet(wxSheet* sheet) const; bool HasSheet(wxSheet* sheet) const { return FindSheet(sheet) != wxNOT_FOUND; } void AddSheet(wxSheet* sheet); void RemoveSheet(wxSheet* sheet); wxSheet *GetSheet(size_t n) const { return (wxSheet*)m_sheets.Item(n); } size_t GetSheetCount() const { return m_sheets.GetCount(); } // implementation --------------------------------------------------------- wxArrayPtrVoid m_sheets; // list of sheets sharing this data wxSheetTable *m_table; // the table that stores the values bool m_ownTable; wxSheetTypeRegistry* m_typeRegistry; // editor/renderer registry wxSheetArrayEdge m_rowEdges; // calculates edge positions and wxSheetArrayEdge m_colEdges; // stores num rows/cols // width of row labels and height of col labels int m_rowLabelWidth; int m_colLabelHeight; // the size of the margin to the right and bottom of the cell area wxSize m_marginSize; int m_equal_col_widths; wxColour m_gridLineColour; int m_gridLinesEnabled; wxColour m_cursorCellHighlightColour; int m_cursorCellHighlightPenWidth; int m_cursorCellHighlightROPenWidth; wxColour m_labelOutlineColour; wxCursor m_rowResizeCursor; wxCursor m_colResizeCursor; bool m_editable; // applies to whole grid - brute force readonly int m_canDrag; // enum wxSheetDragCellSize_Type wxSheetCoords m_cursorCoords; wxSheetBlock m_selectingBlock; // during selection !Empty wxSheetCoords m_selectingAnchor; // corner of active selection, other is usually cursor wxSheetSelection* m_selection; int m_selectionMode; // wxSheetSelectionMode_Type wxColour m_selectionBackground; wxColour m_selectionForeground; // the default cell attr objects for cells that don't have their own wxSheetCellAttr m_defaultGridCellAttr; wxSheetCellAttr m_defaultRowLabelAttr; wxSheetCellAttr m_defaultColLabelAttr; wxSheetCellAttr m_defaultCornerLabelAttr; wxSheetCellEditor m_cellEditor; // valid only when editing wxSheetCoords m_cellEditorCoords; wxSheetValueProviderSparseString m_copiedData; bool m_pasting; }; // ---------------------------------------------------------------------------- // wxSheet // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheet : public wxWindow { public: wxSheet() : wxWindow(), m_gridWin(NULL) { Init(); } wxSheet( wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxWANTS_CHARS, const wxString& name = wxT("wxSheet") ) : wxWindow(), m_gridWin(NULL) { Init(); Create(parent, id, pos, size, style, name); } bool Create( wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxWANTS_CHARS, const wxString& name = wxT("wxSheet") ); virtual ~wxSheet(); virtual bool Destroy(); // ref another wxSheet's ref data - see usage in wxSheetSplitter void RefSheet(wxSheet* otherSheet); // Create a new wxSheet with same parent, used for wxSheetSplitter. // override this so that the top left sheet in the splitter can return // a "new MySheet" for the other sheets as necessary // This is one of the few ways for the splitter to create new sheets. virtual wxSheet* Clone(wxWindowID id = wxID_ANY); // override wxWindow::Enable to ensure proper refresh virtual bool Enable(bool enable = true); // ------------------------------------------------------------------------ // Create/Set/Get wxSheetTable - the underlying data to be displayed wxSheetTable* GetTable() const { return GetSheetRefData()->m_table; } // Set your own table derived from wxSheetTable, if takeOwnership the // the table will be deleted when this window is destroyed bool SetTable( wxSheetTable *table, bool takeOwnership ); // Create a wxSheetTable using string data containers to use // see this function to see how to setup the table and use SetTable // for the case where you want to customize things // This function exists to show how to create and assign tables bool CreateGrid( int numRows, int numCols, int options = 0 ); // ------------------------------------------------------------------------ // Dimensions of the number of cells on the sheet and helper cell functions int GetNumberRows() const { return GetSheetRefData()->m_rowEdges.GetCount(); } int GetNumberCols() const { return GetSheetRefData()->m_colEdges.GetCount(); } // Is the coords anywhere in labels or grid, -1 to GetNumberRows/Cols()-1 bool ContainsCell( const wxSheetCoords& coords ) const { return (coords.m_row >= -1) && (coords.m_col >= -1) && (coords.m_row < GetNumberRows()) && (coords.m_col < GetNumberCols()); } // returns true if the coords are within the grid cells of the sheet bool ContainsGridRow( int row ) const { return (row >= 0) && (row < GetNumberRows()); } bool ContainsGridCol( int col ) const { return (col >= 0) && (col < GetNumberCols()); } bool ContainsGridCell( const wxSheetCoords& coords ) const { return ContainsGridRow(coords.m_row) && ContainsGridCol(coords.m_col); } // returns true if the coords are within the row/col label cells bool ContainsRowLabelCell( const wxSheetCoords& coords ) const { return (coords.m_col == -1) && ContainsGridRow(coords.m_row); } bool ContainsColLabelCell( const wxSheetCoords& coords ) const { return (coords.m_row == -1) && ContainsGridCol(coords.m_col); } // static helper functions to determine what type of cell it is, not check validity static bool IsGridCell(const wxSheetCoords& coords) { return (coords.m_row >= 0) && (coords.m_col >= 0); } static bool IsLabelCell(const wxSheetCoords& coords) { return (coords.m_row >= -1) && (coords.m_col >= -1) && ((coords.m_row == -1) || (coords.m_col == -1)); } static bool IsRowLabelCell(const wxSheetCoords& coords) { return (coords.m_row >= 0) && (coords.m_col == -1); } static bool IsColLabelCell(const wxSheetCoords& coords) { return (coords.m_row == -1) && (coords.m_col >= 0); } static bool IsCornerLabelCell(const wxSheetCoords& coords) { return (coords.m_row == -1) && (coords.m_col == -1); } // Get an enum value of what window the coords are meant for static wxSheetCell_Type GetCellCoordsType(const wxSheetCoords& coords); // "clear" the contents of the grid (depends on table's Clear() function) // the string implementations clear the cell values, not the # rows/cols void ClearValues(int update = wxSHEET_UpdateValues); // Insert/Add/DeleteRows/Cols to the grid cells // update contains or'ed values of enum wxSheetUpdate_Type. // you proabably want UpdateAll unless you ensure that no problems will occur // or you will update some other way bool InsertRows( size_t row, size_t numRows, int update = wxSHEET_UpdateAll ) { return UpdateRows(row, numRows, update); } bool AppendRows( size_t numRows, int update = wxSHEET_UpdateAll ) { return UpdateRows(GetNumberRows(), numRows, update); } bool DeleteRows( size_t row, size_t numRows, int update = wxSHEET_UpdateAll ) { return UpdateRows(row, -int(numRows), update); } bool InsertCols( size_t col, size_t numCols, int update = wxSHEET_UpdateAll ) { return UpdateCols(col, numCols, update); } bool AppendCols( size_t numCols, int update = wxSHEET_UpdateAll ) { return UpdateCols(GetNumberCols(), numCols, update); } bool DeleteCols( size_t col, size_t numCols, int update = wxSHEET_UpdateAll ) { return UpdateCols(col, -int(numCols), update); } // Set exactly the number of rows or cols, these functions Append or // Delete rows/cols to/from the end. If you are setting attributes for // particular cells/rows/cols you probably won't want to use these bool SetNumberRows( size_t rows, int update = wxSHEET_UpdateAll ); bool SetNumberCols( size_t cols, int update = wxSHEET_UpdateAll ); bool SetNumberCells( size_t rows, size_t cols, int update = wxSHEET_UpdateAll ) { return SetNumberRows(rows, update) || SetNumberCols(cols, update); } // Inserting/Appending/Deleting rows/cols functions are forwarded here // and then sent to the wxSheetTable::UpdateRows/Cols functions // numRows/Cols > 0 : InsertRows/Cols at row/col else if < 0 delete // row/col == GetNumberRows/Cols && numRows/Cols > 0 to append to end virtual bool UpdateRows( size_t row, int numRows, int update = wxSHEET_UpdateAll ); virtual bool UpdateCols( size_t col, int numCols, int update = wxSHEET_UpdateAll ); // ------------------------------------------------------------------------ // Dimensions of the row and column sizes // Get/Set the default height/width of newly created rows/cols // if resizeExisting then resize all to match the newly set default int GetDefaultRowHeight() const { return GetSheetRefData()->m_rowEdges.GetDefaultSize(); } int GetDefaultColWidth() const { return GetSheetRefData()->m_colEdges.GetDefaultSize(); } void SetDefaultRowHeight( int height, bool resizeExistingRows = false ); void SetDefaultColWidth( int width, bool resizeExistingCols = false ); // Get/Set the absolute min row/col width/height, 0 for no min size // Call during grid creation, existing rows/cols are not resized // This value is used when dragging cell size with the mouse if no // particular min size for a row/col has been set int GetMinimalAcceptableRowHeight() const { return GetSheetRefData()->m_rowEdges.GetMinAllowedSize(); } int GetMinimalAcceptableColWidth() const { return GetSheetRefData()->m_colEdges.GetMinAllowedSize(); } void SetMinimalAcceptableRowHeight(int height) { GetSheetRefData()->m_rowEdges.SetMinAllowedSize(height); } void SetMinimalAcceptableColWidth(int width) { GetSheetRefData()->m_colEdges.SetMinAllowedSize(width); } // Don't allow specific rows/cols to be resized smaller than this // Call during grid creation, existing rows/cols are not resized // The setting is cleared to default val if width/height is < min acceptable int GetMinimalRowHeight(int row) const { return GetSheetRefData()->m_rowEdges.GetMinSize(row); } int GetMinimalColWidth(int col) const { return GetSheetRefData()->m_colEdges.GetMinSize(col); } void SetMinimalRowHeight(int row, int height) { GetSheetRefData()->m_rowEdges.SetMinSize(row, height); } void SetMinimalColWidth(int col, int width) { GetSheetRefData()->m_colEdges.SetMinSize(col, width); } // Set the height of a row or width of a col, -1 notation for labels // use height/width = -1 to autosize from the row/col labels void SetRowHeight( int row, int height ); void SetColWidth( int col, int width ); // Get the height/top/bottom for rows, uses -1 notation int GetRowHeight(int row) const; int GetRowTop(int row) const; int GetRowBottom(int row) const; // Get the width/left/right for cols, uses -1 notation int GetColWidth(int col) const; int GetColLeft(int col) const; int GetColRight(int col) const; // Get the width, height of a cell as a wxSize, -1 notation // this does not include spanned cells wxSize GetCellSize(const wxSheetCoords& coords) const; // does the cell have a non-zero width and height, may not be visible, -1 notation bool IsCellShown( const wxSheetCoords& coords ) const; // grid may occupy more space than needed for its rows/columns, this // function allows to set how big this margin space is void SetMargins(int width, int height) { GetSheetRefData()->m_marginSize.x = wxMax(0, width); GetSheetRefData()->m_marginSize.y = wxMax(0, height); } // Get the renderer's best size for the cell, uses -1 notation wxSize GetCellBestSize(const wxSheetCoords& coords, wxDC *dc = NULL) const; // Get the best height of a row or the best width of a col using the // renderer's best size int GetRowBestHeight(int row) const; int GetColBestWidth(int col) const; // ------------------------------------------------------------------------ // Row/Col label size // Get the fixed initial size of the width of row labels or height of col labels int GetDefaultRowLabelWidth() const { return WXSHEET_DEFAULT_ROW_LABEL_WIDTH; } int GetDefaultColLabelHeight() const { return WXSHEET_DEFAULT_COL_LABEL_HEIGHT; } // Get/Set the row/col label widths, // if zero_not_shown and row/col & corner not shown return 0 int GetRowLabelWidth(bool zero_not_shown=true) const; int GetColLabelHeight(bool zero_not_shown=true) const; void SetRowLabelWidth( int width ); void SetColLabelHeight( int height ); // ------------------------------------------------------------------------ // Auto sizing of the row/col widths/heights // automatically size the col/row to fit to its contents, if setAsMin, // this optimal width will also be set as minimal width for this column // returns the width or height used. int AutoSizeRow( int row, bool setAsMin = true ); int AutoSizeCol( int col, bool setAsMin = true ); // auto size all columns (very ineffective for big grids!) void AutoSizeRows( bool setAsMin = true ); void AutoSizeCols( bool setAsMin = true ); // auto size the grid, that is make the columns/rows of the "right" size // and also set the grid size to just fit its contents void AutoSize( bool setAsMin = true ); // autosize row height depending on label text void AutoSizeRowLabelHeight( int row ); // autosize column width depending on label text void AutoSizeColLabelWidth( int col ); // Force the col widths to be of equal size so that they fit within the // the window size. This is maintained even when the window is resized. // The col widths will not be sized less than min_width in pixels. // Use this if you know that the window will be of a reasonable size to // fit the cols, but you don't want to track the EVT_SIZE yourself. // use a min_width <= 0 to turn it off void SetEqualColWidths(int min_width); // ------------------------------------------------------------------------ // Row/Col drag resizing enabled or disabled // // if CanDragRow/ColSize the rows/cols can be resized by the mouse // if CanDragGridSize you can resize the rows/cols in the grid window // else you resize in the label windows (if CanDragRow/ColSize is true) void EnableDragRowSize( bool enable = true ) { SetDragCellSize(wxSHEET_DragLabelRowHeight, enable); } void EnableDragColSize( bool enable = true ) { SetDragCellSize(wxSHEET_DragLabelColWidth, enable); } void EnableDragGridSize(bool enable = true ) { SetDragCellSize(wxSHEET_DragGridCellSize, enable); } void DisableDragRowSize() { EnableDragRowSize( false ); } void DisableDragColSize() { EnableDragColSize( false ); } void DisableDragGridSize() { EnableDragGridSize(false); } bool CanDragRowSize() const { return (GetDragCellSize() & wxSHEET_DragLabelRowHeight) != 0; } bool CanDragColSize() const { return (GetDragCellSize() & wxSHEET_DragLabelColWidth) != 0; } bool CanDragGridSize() const { return (GetDragCellSize() & wxSHEET_DragGridCellSize) != 0; } // Directly set the dragging of the cell size use wxSheetDragCellSize_Type enums void SetDragCellSize( int type ) { GetSheetRefData()->m_canDrag = type; } void SetDragCellSize( int type, bool enable ) { SetDragCellSize( enable ? (GetDragCellSize() | type) : (GetDragCellSize() & (~type)) ); } int GetDragCellSize() const { return GetSheetRefData()->m_canDrag; } // ------------------------------------------------------------------------ // Grid line, cell highlight, selection colouring // Draw the grid lines, wxHORIZONAL | wxVERTICAL (wxBOTH), 0 for none void EnableGridLines( int dir = wxBOTH ); int GridLinesEnabled() const { return GetSheetRefData()->m_gridLinesEnabled; } const wxColour& GetGridLineColour() const { return GetSheetRefData()->m_gridLineColour; } void SetGridLineColour( const wxColour& colour ); const wxColour& GetCursorCellHighlightColour() const { return GetSheetRefData()->m_cursorCellHighlightColour; } int GetCursorCellHighlightPenWidth() const { return GetSheetRefData()->m_cursorCellHighlightPenWidth; } int GetCursorCellHighlightROPenWidth() const { return GetSheetRefData()->m_cursorCellHighlightROPenWidth; } void SetCursorCellHighlightColour( const wxColour& colour ); void SetCursorCellHighlightPenWidth(int width); void SetCursorCellHighlightROPenWidth(int width); // get/set the colour bounding the labels to give 3-D effect const wxColour& GetLabelOutlineColour() const { return GetSheetRefData()->m_labelOutlineColour; } void SetLabelOutlineColour( const wxColour& colour ); const wxColour& GetSelectionBackground() const { return GetSheetRefData()->m_selectionBackground; } const wxColour& GetSelectionForeground() const { return GetSheetRefData()->m_selectionForeground; } void SetSelectionBackground(const wxColour& c) { GetSheetRefData()->m_selectionBackground = c; } void SetSelectionForeground(const wxColour& c) { GetSheetRefData()->m_selectionForeground = c; } // ------------------------------------------------------------------------ // Span, cells can span across multiple cells, hiding cells below // // Normally cells are of size 1x1, but they can be larger. // The other cells can still have values and attributes, but they // will not be used since GetCellOwner is used for most coord operations // so that the underlying cell values and attributes are ignored. // The span for the owner cell is 1x1 or larger, the span for other // cells contained within the spanned block have a cell span of <= 0, such // that coords + GetCellSpan() = the owner cell // // You can completely override this functionality if you provide // HasSpannedCells, GetCellBlock, SetCellSpan // Are there any spanned cells at all? virtual bool HasSpannedCells() const; // if cell is part of a spanning cell, return owner's coords else input coords wxSheetCoords GetCellOwner( const wxSheetCoords& coords ) const; // Get a block of the cell, unless a spanned cell it's of size 1,1 // note: the top left of block is the owner cell of coords virtual wxSheetBlock GetCellBlock( const wxSheetCoords& coords ) const; // Get the span of a cell, the owner (top right) cell always has a span of // (1, 1) or greater. The other cells in a spanned block will have a span // (<1, <1) such that, coords + coordsSpan = ownerCoords wxSheetCoords GetCellSpan( const wxSheetCoords& coords ) const; // Set the span of a cell, must be 1x1 or greater, // To remove a spanned cell set it to a cell of size 1x1 // For grid cells the whole block must be contained within the grid cells // and if the block intersects a previously spanned cell block the top left // corners must match up. // Row and Col labels can span cells as well, spanned row labels must have a // width of 1 and a height of >= 1, col labels a height of 1 and width >= 1 virtual void SetCellSpan( const wxSheetBlock& block ); void SetCellSpan( const wxSheetCoords& coords, const wxSheetCoords& numRowsCols ) { SetCellSpan(wxSheetBlock(coords, numRowsCols.m_row, numRowsCols.m_col)); } // Get a pointer to the spanned blocks to iterate through, may return NULL. const wxSheetSelection* GetSpannedBlocks() const { return GetTable() ? GetTable()->GetSpannedBlocks() : NULL; } // ------------------------------------------------------------------------ // Get/Set attributes for the cells, row, col, corner labels // See wxSheetAttr_Type for a description of the type of attribute // The coords are specified as // The Grid area (0 <= row < GetNumberRows), (0 <= col < GetNumberCols) // The Corner window row = col = -1 // The Row labels (0 <= row < GetNumberRows), col = -1 // The Col labels row = -1, (0 <= col < GetNumberCols) // For the wxSHEET_AttrDefault type the coords should be contained within the // size of the sheet, but the particular values are not used. // see const wxGridCellSheetCoords = (0,0) for example // wxRowLabelSheetCoords, wxColLabelSheetCoords, wxCornerLabelSheetCoords // To completely override this you may provide alternate // GetOrCreateAttr, GetAttr, and SetAttr functions. // make sure that the last default attr of initAttr is defAttr // This is called internally when you call SetAttr bool InitAttr( wxSheetCellAttr& initAttr, const wxSheetCellAttr& defAttr ) const; // Get an attribute for the coords if it exists or create a new one // and put it into the table which puts it in the attr provider. // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col for the grid cells // and wxSHEET_AttrDefault/Cell for the labels virtual wxSheetCellAttr GetOrCreateAttr( const wxSheetCoords& coords, wxSheetAttr_Type type ) const; // Get the attribute for any area depending on the coords and type // returns a valid attr if the coords are valid and type = wxSHEET_AttrAny // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col/Any for the grid cells // and wxSHEET_AttrDefault/Cell/Any for the labels virtual wxSheetCellAttr GetAttr( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny) const; // Set the attribute for any area depending on the coords // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col for the grid cells // and wxSHEET_AttrDefault/Cell for the labels virtual void SetAttr(const wxSheetCoords& coords, const wxSheetCellAttr& attr, wxSheetAttr_Type type ); // ------ Simplified functions for accessing the attributes --------------- // Get an attribute for the grid coords, returning a cell/row/col attr or // if multiple attr for the coords an attr that's merged, or the def attr wxSheetCellAttr GetGridAttr(const wxSheetCoords& coords) const { return GetAttr(coords, wxSHEET_AttrAny); } // Get a specific Cell/Row/Col attr for the coords in the grid // if none set returns wxNullSheetCellAttr wxSheetCellAttr GetGridCellAttr(const wxSheetCoords& coords) const { return GetAttr(coords, wxSHEET_AttrCell); } wxSheetCellAttr GetGridRowAttr(int row) const { return GetAttr(wxSheetCoords(row, 0), wxSHEET_AttrRow); } wxSheetCellAttr GetGridColAttr(int col) const { return GetAttr(wxSheetCoords(0, col), wxSHEET_AttrCol); } // Set a specific Cell/Row/Col attr for coords, row/col only apply to the grid void SetGridCellAttr(const wxSheetCoords& coords, const wxSheetCellAttr& attr) { SetAttr(coords, attr, wxSHEET_AttrCell); } void SetGridRowAttr(int row, const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(row, 0), attr, wxSHEET_AttrRow); } void SetGridColAttr(int col, const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(0, col), attr, wxSHEET_AttrCol); } // Get the row/col/corner label attributes, if one is not set for the // particular coords, returns the default one. (note: only one corner attr) // if you want the particular attr use GetRow/ColLabelCellAttr wxSheetCellAttr GetRowLabelAttr(int row) const { return GetAttr(wxSheetCoords(row, -1), wxSHEET_AttrAny); } wxSheetCellAttr GetColLabelAttr(int col) const { return GetAttr(wxSheetCoords(-1, col), wxSHEET_AttrAny); } wxSheetCellAttr GetCornerLabelAttr() const { return GetAttr(wxSheetCoords(-1, -1), wxSHEET_AttrAny); } // Get a specific attr the row/col/corner label cell // if none set returns wxNullSheetCellAttr wxSheetCellAttr GetRowLabelCellAttr(int row) const { return GetAttr(wxSheetCoords(row, -1), wxSHEET_AttrCell); } wxSheetCellAttr GetColLabelCellAttr(int col) const { return GetAttr(wxSheetCoords(-1, col), wxSHEET_AttrCell); } // Set a specific attribute for particular row/col/corner label cell void SetRowLabelCellAttr(int row, const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(row, -1), attr, wxSHEET_AttrCell); } void SetColLabelCellAttr(int col, const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(-1, col), attr, wxSHEET_AttrCell); } void SetCornerLabelAttr(const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(-1, -1), attr, wxSHEET_AttrCell); } // Get/Set default attributes for the areas (only one corner attr) // For setting, wxSheetCellAttr::UpdateWith is called with the current default // attr so you so need only set the values that you want to change. wxSheetCellAttr GetDefaultAttr(const wxSheetCoords& coords) const { return GetAttr(coords, wxSHEET_AttrDefault); } wxSheetCellAttr GetDefaultGridCellAttr() const { return GetAttr(wxGridCellSheetCoords, wxSHEET_AttrDefault); } wxSheetCellAttr GetDefaultRowLabelAttr() const { return GetAttr(wxRowLabelSheetCoords, wxSHEET_AttrDefault); } wxSheetCellAttr GetDefaultColLabelAttr() const { return GetAttr(wxColLabelSheetCoords, wxSHEET_AttrDefault); } void SetDefaultAttr(const wxSheetCoords& coords, const wxSheetCellAttr& attr) { SetAttr(coords, attr, wxSHEET_AttrDefault); } void SetDefaultGridCellAttr(const wxSheetCellAttr& attr) { SetAttr(wxGridCellSheetCoords, attr, wxSHEET_AttrDefault); } void SetDefaultRowLabelAttr(const wxSheetCellAttr& attr) { SetAttr(wxRowLabelSheetCoords, attr, wxSHEET_AttrDefault); } void SetDefaultColLabelAttr(const wxSheetCellAttr& attr) { SetAttr(wxColLabelSheetCoords, attr, wxSHEET_AttrDefault); } // These are convienience functions, if for example you want to subclass the // table and modify and return default attr "on the fly" for each cell const wxSheetCellAttr& DoGetDefaultGridAttr() const { return GetSheetRefData()->m_defaultGridCellAttr; } const wxSheetCellAttr& DoGetDefaultRowLabelAttr() const { return GetSheetRefData()->m_defaultRowLabelAttr; } const wxSheetCellAttr& DoGetDefaultColLabelAttr() const { return GetSheetRefData()->m_defaultColLabelAttr; } const wxSheetCellAttr& DoGetDefaultCornerLabelAttr() const { return GetSheetRefData()->m_defaultCornerLabelAttr; } // Get/Set particular attributes for any type of cell/row/col anywhere // The default is to get the attr val for type=wxSHEET_AttrAny meaning that // it'll find a set attr first or return the default attr value as a last resort. // For GetXXX you will receive an an error message if you specify a // particular wxSHEET_AttrCell/Row/Col, but there isn't an attribute set const wxColour& GetAttrBackgroundColour( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; const wxColour& GetAttrForegoundColour( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; const wxFont& GetAttrFont( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; int GetAttrAlignment( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; int GetAttrOrientation( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; int GetAttrLevel( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; bool GetAttrOverflow( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; bool GetAttrOverflowMarker( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; bool GetAttrShowEditor( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; bool GetAttrReadOnly( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; wxSheetCellRenderer GetAttrRenderer( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; wxSheetCellEditor GetAttrEditor( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; // Set attributes for a particular cell/row/col, relies on GetOrCreateAttr() // so it creates and adds the attr to the attr provider if there wasn't one // after setting the particular value. // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col void SetAttrBackgroundColour( const wxSheetCoords& coords, const wxColour& colour, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrForegroundColour( const wxSheetCoords& coords, const wxColour& colour, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrFont( const wxSheetCoords& coords, const wxFont& font, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrAlignment( const wxSheetCoords& coords, int align, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrOrientation( const wxSheetCoords& coords, int orientation, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrLevel( const wxSheetCoords& coords, int level, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrOverflow( const wxSheetCoords& coords, bool allow, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrOverflowMarker( const wxSheetCoords& coords, bool draw_marker, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrShowEditor( const wxSheetCoords& coords, bool show_editor, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrReadOnly( const wxSheetCoords& coords, bool isReadOnly, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrRenderer( const wxSheetCoords& coords, const wxSheetCellRenderer &renderer, wxSheetAttr_Type type = wxSHEET_AttrCell ); void SetAttrEditor( const wxSheetCoords& coords, const wxSheetCellEditor &editor, wxSheetAttr_Type type = wxSHEET_AttrCell ); // helper functions that use SetColAttr to set renderer type // set the format for the data in the column: default is string void SetColFormatBool(int col) { SetColFormatCustom(col, wxSHEET_VALUE_BOOL); } void SetColFormatNumber(int col) { SetColFormatCustom(col, wxSHEET_VALUE_NUMBER); } void SetColFormatFloat(int col, int width = -1, int precision = -1); void SetColFormatCustom(int col, const wxString& typeName); // ------------------------------------------------------------------------ // Get/Set cell, row, col, and corner label values // To completely override this you need only provide Get/SetCellValue // Get/Set cell value, uses coords = -1 notation for row/col/corner labels virtual wxString GetCellValue( const wxSheetCoords& coords ); virtual void SetCellValue( const wxSheetCoords& coords, const wxString& value ); // Is this cell empty, see wxSheetTable virtual bool HasCellValue( const wxSheetCoords& coords ); wxString GetRowLabelValue( int row ) { return GetCellValue(wxSheetCoords(row, -1)); } wxString GetColLabelValue( int col ) { return GetCellValue(wxSheetCoords(-1, col)); } void SetRowLabelValue( int row, const wxString& value ) { SetCellValue(wxSheetCoords(row, -1), value); } void SetColLabelValue( int col, const wxString& value ) { SetCellValue(wxSheetCoords(-1, col), value); } wxString GetCornerLabelValue() { return GetCellValue(wxSheetCoords(-1, -1)); } void SetCornerLabelValue(const wxString& value) { SetCellValue(wxSheetCoords(-1, -1), value); } // ------------------------------------------------------------------------ // Register mapping between data types to Renderers/Editors void RegisterDataType( const wxString& typeName, const wxSheetCellRenderer& renderer, const wxSheetCellEditor& editor ); virtual wxSheetCellEditor GetDefaultEditorForType(const wxString& typeName) const; virtual wxSheetCellRenderer GetDefaultRendererForType(const wxString& typeName) const; // FIXME what is the point of these? virtual wxSheetCellEditor GetDefaultEditorForCell(const wxSheetCoords& coords) const; virtual wxSheetCellRenderer GetDefaultRendererForCell(const wxSheetCoords& coords) const; // ------------------------------------------------------------------------ // Cursor movement and visibility functions // check to see if a cell is either wholly visible (the default arg) or // at least partially visible, uses -1 notation for labels bool IsCellVisible( const wxSheetCoords& coords, bool wholeCellVisible = true ) const; bool IsRowVisible( int row, bool wholeRowVisible = true ) const; bool IsColVisible( int col, bool wholeColVisible = true ) const; // Make this cell visible, uses -1 notation, will not unhide label windows void MakeCellVisible( const wxSheetCoords& coords ); // Get/Set cursor cell, this is the "current" cell where a highlight is drawn // the cursor only applies to the grid cells const wxSheetCoords& GetGridCursorCell() const { return GetSheetRefData()->m_cursorCoords; } int GetGridCursorRow() const { return GetGridCursorCell().GetRow(); } int GetGridCursorCol() const { return GetGridCursorCell().GetCol(); } void SetGridCursorCell( const wxSheetCoords& coords ); bool MoveCursorUp( bool expandSelection ) { return DoMoveCursor(wxSheetCoords(-1, 0), expandSelection); } bool MoveCursorDown( bool expandSelection ) { return DoMoveCursor(wxSheetCoords( 1, 0), expandSelection); } bool MoveCursorLeft( bool expandSelection ) { return DoMoveCursor(wxSheetCoords( 0,-1), expandSelection); } bool MoveCursorRight( bool expandSelection ) { return DoMoveCursor(wxSheetCoords( 0, 1), expandSelection); } bool MoveCursorUpBlock( bool expandSelection ) { return DoMoveCursorBlock(wxSheetCoords(-1, 0), expandSelection); } bool MoveCursorDownBlock( bool expandSelection ) { return DoMoveCursorBlock(wxSheetCoords( 1, 0), expandSelection); } bool MoveCursorLeftBlock( bool expandSelection ) { return DoMoveCursorBlock(wxSheetCoords( 0,-1), expandSelection); } bool MoveCursorRightBlock( bool expandSelection ) { return DoMoveCursorBlock(wxSheetCoords( 0, 1), expandSelection); } bool MoveCursorUpPage( bool expandSelection ) { return DoMoveCursorUpDownPage(true, expandSelection); } bool MoveCursorDownPage( bool expandSelection ) { return DoMoveCursorUpDownPage(false, expandSelection); } virtual bool DoMoveCursor( const wxSheetCoords& relCoords, bool expandSelection ); virtual bool DoMoveCursorBlock( const wxSheetCoords& relDir, bool expandSelection ); virtual bool DoMoveCursorUpDownPage( bool page_up, bool expandSelection ); // ------------------------------------------------------------------------ // Cell/Row/Col selection and deselection, you can only select grid cells // Note: A selection to the # of rows/cols means that the whole row/col is // selected. Otherwise the right/bottom is rows/cols - 1, ie. contained // within the actual number of cells. // If sendEvt a wxEVT_SHEET_RANGE_SELECTED is sent, the SELECTING event // should have been sent by the caller and if vetoed not call these. // All functions (De)Select/Row/Col/Cell, SelectAll go to (De)SelectBlock. // ClearSelection deselects everything and sends a single event with // wxSheetBlock(0,0,rows,cols) to imply everything is cleared. // To override the selection mechanism you only need to override, // HasSelection, IsCell/Row/ColSelected, (De)SelectBlock, and ClearSelection. // Is there any selection, if selecting, includes the active selection block // which is not yet part of underlying selection system virtual bool HasSelection(bool selecting = true) const; // Are these coords within either the selecting block or selection virtual bool IsCellSelected( const wxSheetCoords& coords ) const; bool IsCellSelected( int row, int col ) const { return IsCellSelected(wxSheetCoords(row, col)); } virtual bool IsRowSelected( int row ) const; virtual bool IsColSelected( int col ) const; // Are we currently in the middle of a selection bool IsSelecting() const { return !GetSelectingBlock().IsEmpty(); } void SetSelectionMode(wxSheetSelectionMode_Type selmode); int GetSelectionMode() const { return GetSheetRefData()->m_selectionMode; } bool HasSelectionMode(int mode) { return (GetSelectionMode() & mode) != 0; } virtual bool SelectRow( int row, bool addToSelected = false, bool sendEvt = false ); virtual bool SelectRows( int rowTop, int rowBottom, bool addToSelected = false, bool sendEvt = false ); virtual bool SelectCol( int col, bool addToSelected = false, bool sendEvt = false ); virtual bool SelectCols( int colLeft, int colRight, bool addToSelected = false, bool sendEvt = false ); virtual bool SelectCell( const wxSheetCoords& coords, bool addToSelected = false, bool sendEvt = false ); virtual bool SelectBlock( const wxSheetBlock& block, bool addToSelected = false, bool sendEvt = false ); // selects everything to numRows, numCols virtual bool SelectAll(bool sendEvt = false); virtual bool DeselectRow( int row, bool sendEvt = false ); virtual bool DeselectRows( int rowTop, int rowBottom, bool sendEvt = false ); virtual bool DeselectCol( int col, bool sendEvt = false ); virtual bool DeselectCols( int colLeft, int colRight, bool sendEvt = false ); virtual bool DeselectCell( const wxSheetCoords& coords, bool sendEvt = false ); virtual bool DeselectBlock( const wxSheetBlock& block, bool sendEvt = false ); // clears selection, single deselect event numRows, numCols virtual bool ClearSelection(bool send_event = false); // toggle the selection of a single cell, row, or col // addToSelected applies to a selection only, ignored if a deselection virtual bool ToggleCellSelection( const wxSheetCoords& coords, bool addToSelected = false, bool sendEvt = false ); virtual bool ToggleRowSelection( int row, bool addToSelected = false, bool sendEvt = false ); virtual bool ToggleColSelection( int col, bool addToSelected = false, bool sendEvt = false ); // Get a pointer to the selection mechanism. You are free to do what you // want with it, do a ForceRefresh to update the grid when done. wxSheetSelection* GetSelection() const { return GetSheetRefData()->m_selection; } // During a selection this is the selecting block, else empty const wxSheetBlock& GetSelectingBlock() const { return GetSheetRefData()->m_selectingBlock; } const wxSheetCoords& GetSelectingAnchor() const { return GetSheetRefData()->m_selectingAnchor; } // These are internal use functions to highlight a block during mouse // dragging or keyboard selecting void SetSelectingBlock(const wxSheetBlock& selectingBlock) { GetSheetRefData()->m_selectingBlock = selectingBlock; } void SetSelectingAnchor(const wxSheetCoords& selectingAnchor) { GetSheetRefData()->m_selectingAnchor = selectingAnchor; } // while selecting set and draw m_selectingBlock highlight and clear up last virtual void HighlightSelectingBlock( const wxSheetBlock& selectingBlock ); void HighlightSelectingBlock( const wxSheetCoords& cornerCell, const wxSheetCoords& otherCell ) { HighlightSelectingBlock(wxSheetBlock(cornerCell, otherCell)); } // ------------------------------------------------------------------------ // Copy/Paste functionality for strings // Copy the current selection using CopyCurrentSelectionInternal then // to the wxClipboard using CopyInternalSelectionToClipboard bool CopyCurrentSelectionToClipboard(bool copy_cursor = true, const wxChar& colSep = wxT('\t')); // Copy the current selection to an internal copied selection mechanism // storing both the positions and values of the selected cells, if no // selection and copy_cursor then just copy the cursor value bool CopyCurrentSelectionInternal(bool copy_cursor = true); // Copy the internal selection to the wxClipboard as both a string using // colSep to separate columns and as an internal representation for // pasting back into the wxSheet. bool CopyInternalSelectionToClipboard(const wxChar& colSep = wxT('\t')); // Copy the internal selection to a clipboard string // uses colSep for cols and \n for rows, called by CopySelectionToClipboard wxString CopyInternalSelectionToString(const wxChar& colSep = wxT('\t')); // Copies the string (perhaps from the clipboard) to the internal copied // selection uses colSep for cols and \n for rows, used by PasteFromClipboard bool CopyStringToSelection(const wxString& value, const wxChar& colSep = wxT('\t')); // Tries to get the clipboard data as wxSheet's clipboard data // representation else use CopyStringToSelection to convert a string // using colSep as the column separator and \n as row separator. bool PasteFromClipboard(const wxSheetCoords &topLeft = wxNullSheetCoords, const wxChar& colSep = wxT('\t')); // Paste the internal copied selection at the topLeft coords or if // topLeft = wxNullSheetCoords then if IsSelection use the upper right of // the current selection and only paste into currently selected cells. // If no selection the the cursor is the topLeft cell. virtual bool PasteInternalCopiedSelection(const wxSheetCoords &topLeft = wxNullSheetCoords); // Are the cells being pasted right now, use this in the table's // SetCellValue and AppendXXX to differentiate between a user typing bool CurrentlyPasting() const { return GetSheetRefData()->m_pasting; } // ------------------------------------------------------------------------ // Edit control functions (mostly used internally) // Is/Make the whole sheet editable or readonly bool IsEditable() const { return GetSheetRefData()->m_editable; } void EnableEditing( bool edit ); // enable and show the editor control at the coords, returns sucess, ie. !vetoed bool EnableCellEditControl( const wxSheetCoords& coords ); // hide and disable the editor and save the value if save_value, returns sucess, ie. !vetoed bool DisableCellEditControl( bool save_value ); // is this cell valid and editable bool CanEnableCellControl(const wxSheetCoords& coords) const; // is the cell editor created (may not be shown though) bool IsCellEditControlCreated() const; // is the cell editor valid and shown bool IsCellEditControlShown() const; // Create and show the appropriate editor at the EnableCellEditControl coords // this is called internally by EnableCellEditControl, but if you call // HideCellEditControl and if IsCellEditControlCreated then you can reshow // it with this, returns sucess bool ShowCellEditControl(); // Hide the editor, doesn't destroy it (use DisableCellEditControl) // check if IsCellEditControlShown first, returns sucess bool HideCellEditControl(); // Save the value of the editor, check IsCellEditControlEnabled() first void SaveEditControlValue(); // Get the current editor, !Ok() if !IsCellEditControlCreated() const wxSheetCellEditor& GetEditControl() const { return GetSheetRefData()->m_cellEditor; } // These are the coords of the editor, check IsCellEditControlCreated before using const wxSheetCoords& GetEditControlCoords() const { return GetSheetRefData()->m_cellEditorCoords; } // ------------------------------------------------------------------------ // Drawing functions // Code that does a lot of grid modification can be enclosed // between BeginBatch() and EndBatch() calls to avoid screen flicker // EndBatch's refresh = false will not refresh when batchCount is 0 void BeginBatch() { m_batchCount++; } void EndBatch(bool refresh=true); int GetBatchCount() const { return m_batchCount; } // Use ForceRefresh, rather than wxWindow::Refresh(), to force an // immediate repainting of the grid. No effect if GetBatchCount() > 0 // This function is necessary because wxSheet has a minimal OnPaint() // handler to reduce screen flicker. void ForceRefresh() { BeginBatch(); EndBatch(); } // *** Use these redrawing functions to ensure refed sheets are redrawn *** // Refresh a single cell, can also draw cells for labels using -1 notation // does nothing if cell !visible, or GetBatchCount != 0 // if single_cell then literally draw only the single cell, else draw the // cell to left in case the overflow marker needs to be drawn and the // cells to the right in case this cell overflows. void RefreshCell(const wxSheetCoords& coords, bool single_cell = true); // Refresh a block of cells in any/all of the windows by chopping up the block, // uses -1 notation to refresh labels void RefreshBlock(const wxSheetBlock& block); // Refresh a single row, row = -1 refreshes all col labels, // does nothing if row !visible, or GetBatchCount != 0 void RefreshRow(int row); // Refresh a single col, col = -1 refreshes all row labels, // does nothing if col !visible, or GetBatchCount != 0 void RefreshCol(int col); // Refresh is called using a rect surrounding the block // does nothing if block IsEmpty, !visible, or GetBatchCount != 0 void RefreshGridCellBlock( const wxSheetBlock& block ); // After SetAttr call this can appropriately refresh the wxSheet areas void RefreshAttrChange(const wxSheetCoords& coords, wxSheetAttr_Type type); // ************************************************************************ // Drawing implementation // Refresh an area of the window that calculates the smaller rects for // each individual window (row/col/corner...) and calls Refresh(subRect) // The rect is the logical rect, not the scrolled device rect virtual void Refresh(bool eraseb = true, const wxRect* rect = NULL); // These directly call wxWindow::Refresh for the appropriate windows // The input rect doesn't have to be clipped to the visible window since // this function takes care of that, but it should be in client coords. void RefreshGridWindow(bool eraseb = true, const wxRect* rect = NULL); void RefreshRowLabelWindow(bool eraseb = true, const wxRect* rect = NULL); void RefreshColLabelWindow(bool eraseb = true, const wxRect* rect = NULL); void RefreshCornerLabelWindow(bool eraseb = true, const wxRect* rect = NULL); // Don't use these if you plan to use the splitter since they only act // on this sheet. // These functions are called by the OnPaint handler of these windows // use these to add "extra touches" before or after redrawing. // The dc should be prepared before calling these. virtual void PaintGridWindow( wxDC& dc, const wxRegion& reg ); virtual void PaintRowLabelWindow( wxDC& dc, const wxRegion& reg ); virtual void PaintColLabelWindow( wxDC& dc, const wxRegion& reg ); virtual void PaintCornerLabelWindow( wxDC& dc, const wxRegion& reg ); virtual void PaintSheetWindow( wxDC& dc, const wxRegion& reg ); // draws a bunch of blocks of grid cells onto the given DC virtual void DrawGridCells( wxDC& dc, const wxSheetSelection& blockSel ); // Draw the area below and to right of grid up to scrollbars virtual void DrawGridSpace( wxDC& dc ); // draw the border around a single cell virtual void DrawCellBorder( wxDC& dc, const wxSheetCoords& coords ); // Draw all the grid lines in the region virtual void DrawAllGridLines( wxDC& dc, const wxRegion& reg ); // Draw a single cell virtual void DrawCell( wxDC& dc, const wxSheetCoords& coords ); // Calls DrawCursorCellHighlight if contained within this selection virtual void DrawCursorHighlight( wxDC& dc, const wxSheetSelection& blockSel ); // Draw the cursor cell highlight virtual void DrawCursorCellHighlight(wxDC& dc, const wxSheetCellAttr &attr); // draw wxSheetRowLabelWindow labels virtual void DrawRowLabels( wxDC& dc, const wxArrayInt& rows ); // draw wxSheetColLabelWindow labels virtual void DrawColLabels( wxDC& dc, const wxArrayInt& cols ); // wxSheetCornerLabelWindow label virtual void DrawCornerLabel( wxDC& dc ); // Draw the row/col resizing marker and if newDragPos != -1, set the // new position of the marker virtual void DrawRowColResizingMarker( int newDragPos = -1 ); // Draw the splitter button in the rectangle virtual void DrawSplitterButton(wxDC &dc, const wxRect& rect); // Calculate the Row/ColLabels and Cells exposed for the wxRegion // returns false if none, used for redrawing windows bool CalcRowLabelsExposed( const wxRegion& reg, wxArrayInt& rows ) const; bool CalcColLabelsExposed( const wxRegion& reg, wxArrayInt& cols ) const; bool CalcCellsExposed( const wxRegion& reg, wxSheetSelection& blockSel ) const; int FindOverflowCell( const wxSheetCoords& coords, wxDC& dc ); // helper drawing functions void DrawTextRectangle( wxDC& dc, const wxString& value, const wxRect& rect, int alignment = wxALIGN_LEFT|wxALIGN_TOP, int textOrientation = wxHORIZONTAL ); void DrawTextRectangle( wxDC& dc, const wxArrayString& lines, const wxRect&, int alignment = wxALIGN_LEFT|wxALIGN_TOP, int textOrientation = wxHORIZONTAL ); // Split string by '\n' and add to array, returning the number of lines // returns 0 for empty string. int StringToLines( const wxString& value, wxArrayString& lines ) const; // Get the size of the lines drawn horizontally, returs true if size > 0 bool GetTextBoxSize( wxDC& dc, const wxArrayString& lines, long *width, long *height ) const; // ------------------------------------------------------------------------ // Geometry utility functions, pixel <-> cell etc // Note that all of these functions work with the logical coordinates of // grid cells and labels so you will need to convert from device // coordinates for mouse events etc. // clipToMinMax means that the return value will be within the grid cells // if !clipToMinMax and out of bounds it returns -1. // Use ContainsGridXXX to verify validity, -1 doesn't mean label wxSheetCoords XYToGridCell( int x, int y, bool clipToMinMax = false ) const; int YToGridRow( int y, bool clipToMinMax = false ) const; int XToGridCol( int x, bool clipToMinMax = false ) const; // return the row/col number that the x/y coord is near the edge of, or // -1 if not near an edge, uses WXSHEET_LABEL_EDGE_ZONE // Use ContainsGridXXX to verify validity, -1 doesn't mean label int YToEdgeOfGridRow( int y ) const; int XToEdgeOfGridCol( int x ) const; // Get a rect bounding the cell, handles spanning cells and the label // windows using the -1 notation, getDeviceRect calls CalcScrolledRect wxRect CellToRect( const wxSheetCoords& coords, bool getDeviceRect = false ) const; // Get a rect bounding the block, handles label windows using the -1 notation, // getDeviceRect calls CalcScrolledRect wxRect BlockToRect( const wxSheetBlock& block, bool getDeviceRect = false ) const; // Expand the block by unioning with intersecting spanned cells wxSheetBlock ExpandSpannedBlock( const wxSheetBlock& block ) const; // Convert the block of cells into a wxRect in device coords, expands the // block to contain spanned cells if expand_spanned. // These functions do handle label cells, but if you span the block from a label // into the grid then the rect will overlap the windows, probably not what you want. wxRect BlockToDeviceRect( const wxSheetBlock& block, bool expand_spanned = true ) const; wxRect BlockToLogicalRect( const wxSheetBlock& block, bool expand_spanned = true ) const; // Convert the rect in pixels into a block of cells for the grid // if wholeCell then only include cells in the block that are // wholly contained by the rect wxSheetBlock LogicalGridRectToBlock(const wxRect &rect, bool wholeCell = false) const; // get a block containing all the currently (partially/fully) visible cells wxSheetBlock GetVisibleGridCellsBlock(bool wholeCellVisible = false) const; // Align the size of an object inside the rect using wxALIGN enums // if inside then align it to the left if it would have overflown // always pins size to left hand side wxPoint AlignInRect( int align, const wxRect& rect, const wxSize& size, bool inside=true ) const; // ------------------------------------------------------------------------ // Scrolling for the window, everything is done with pixels // there is no need for scroll units and they only cause sizing problems // Get the scrolled origin of the grid in pixels const wxPoint& GetGridOrigin() const { return m_gridOrigin; } // Set the absolute scrolled origin of the grid window in pixels // this checks validity and ensures proper positioning. // Use x or y = -1 to not change the origin in the x or y direction // Unless setting from a scrollbar event use adjustScrollBars=true virtual void SetGridOrigin(int x, int y, bool adjustScrollBars = true, bool sendEvt=false); void SetGridOrigin(const wxPoint& pt, bool adjustScrollBars = true, bool sendEvt=false) { SetGridOrigin(pt.x, pt.y, adjustScrollBars, sendEvt); } // Get the virtual size of the grid in pixels, includes extra width/height wxSize GetGridVirtualSize(bool add_margin=true) const; // Get the extent of the grid, this may be more than the virtual size if the // grid is smaller than the containing window wxSize GetGridExtent() const; // Same as wxScrolledWindow Calc(Un)ScrolledPosition void CalcScrolledPosition(int x, int y, int *xx, int *yy) const { if (xx) *xx = x - m_gridOrigin.x; if (yy) *yy = y - m_gridOrigin.y; } void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const { if (xx) *xx = x + m_gridOrigin.x; if (yy) *yy = y + m_gridOrigin.y; } wxPoint CalcScrolledPosition(const wxPoint& pt) const { return pt - m_gridOrigin; } wxPoint CalcUnscrolledPosition(const wxPoint& pt) const { return pt + m_gridOrigin; } // returns the scrolled position of the rect, logical -> device coords wxRect CalcScrolledRect(const wxRect &r) const { return wxRect(r.x-m_gridOrigin.x, r.y-m_gridOrigin.y, r.width, r.height); } // returns the unscrolled position of the rect, device -> logical coords wxRect CalcUnscrolledRect(const wxRect &r) const { return wxRect(r.x+m_gridOrigin.x, r.y+m_gridOrigin.y, r.width, r.height); } // Adjust the scrollbars to match the size/origin of the grid window // call this after SetScrollBarMode virtual void AdjustScrollbars(bool calc_win_sizes = true); enum SB_Mode { SB_AS_NEEDED = 0x0, // Show the scrollbars as needed SB_HORIZ_NEVER = 0x1, // Never show horiz scrollbar, even if needed SB_VERT_NEVER = 0x2, // Never show vert scrollbar, even if needed SB_NEVER = SB_HORIZ_NEVER | SB_VERT_NEVER, SB_HORIZ_ALWAYS = 0x4, // Always show horiz scrollbar SB_VERT_ALWAYS = 0x8, // Always show vert scrollbar SB_ALWAYS = SB_HORIZ_ALWAYS | SB_VERT_ALWAYS, SB_HORIZ_MASK = SB_HORIZ_NEVER|SB_HORIZ_ALWAYS, SB_VERT_MASK = SB_VERT_NEVER|SB_VERT_ALWAYS }; int GetScrollBarMode() const { return m_scrollBarMode; } void SetScrollBarMode(int mode) { m_scrollBarMode = mode; } void SetHorizontalScrollBarMode(int mode) { m_scrollBarMode &= (~SB_HORIZ_MASK); m_scrollBarMode |= mode; } void SetVerticalScrollBarMode(int mode) { m_scrollBarMode &= (~SB_VERT_MASK); m_scrollBarMode |= mode; } bool NeedsVerticalScrollBar() const { return GetGridVirtualSize().y > m_gridWin->GetSize().y; } bool NeedsHorizontalScrollBar() const { return GetGridVirtualSize().x > m_gridWin->GetSize().x; } // SetDeviceOrigin for the wxDC as appropriate for these windows virtual void PrepareGridDC( wxDC& dc ); virtual void PrepareRowLabelDC( wxDC& dc ); virtual void PrepareColLabelDC( wxDC& dc ); // ------------------------------------------------------------------------ // Splitting of the grid window - note that the sheet does not split at all // and that only a wxEVT_SHEET_SPLIT_BEGIN event is sent to notify the // parent that splitting should take place, see wxSheetSplitter. // The "splitter" is just two small rectangles at the top of the vertical // scrollbar and right of the horizontal scrollbar. They're only shown // when the scrollbars are shown and if splitting is enabled. // Call CalcWindowSizes after setting to update the display. bool GetEnableSplitVertically() const { return m_enable_split_vert; } bool GetEnableSplitHorizontally() const { return m_enable_split_horiz; } void EnableSplitVertically(bool can_split) { m_enable_split_vert = can_split; } void EnableSplitHorizontally(bool can_split) { m_enable_split_horiz = can_split; } // ------------------------------------------------------------------------ // implementation // helper function to set only the horiz or vert component of orig_align // returns modified alignment, doesn't modify any bits not in wxAlignment // use -1 for hAlign/vAlign to not modify that direction static int SetAlignment(int orig_align, int hAlign, int vAlign); // Do any of the windows of the wxSheet have the focus? bool HasFocus() const; // Accessors for component windows wxSheetChildWindow* GetGridWindow() const { return m_gridWin; } wxSheetChildWindow* GetRowLabelWindow() const { return m_rowLabelWin; } wxSheetChildWindow* GetColLabelWindow() const { return m_colLabelWin; } wxSheetChildWindow* GetCornerLabelWindow() const { return m_cornerLabelWin; } // Get the window with these coords, uses -1 notation wxWindow* GetWindowForCoords( const wxSheetCoords& coords ) const; // ------ event handlers void OnMouse( wxMouseEvent& event ); void OnMouseWheel( wxMouseEvent& event ); void ProcessSheetMouseEvent( wxMouseEvent& event ); void ProcessRowLabelMouseEvent( wxMouseEvent& event ); void ProcessColLabelMouseEvent( wxMouseEvent& event ); void ProcessCornerLabelMouseEvent( wxMouseEvent& event ); void ProcessGridCellMouseEvent( wxMouseEvent& event ); void OnScroll( wxScrollEvent& event ); // End the row/col dragging, returns true if width/height have changed bool DoEndDragResizeRowCol(); // ------ control types enum { wxSHEET_TEXTCTRL = 2100, wxSHEET_CHECKBOX, wxSHEET_CHOICE, wxSHEET_COMBOBOX }; enum { ID_HORIZ_SCROLLBAR = 1, ID_VERT_SCROLLBAR, ID_MOUSE_DRAG_TIMER, ID_GRID_WINDOW, ID_ROW_LABEL_WINDOW, ID_COL_LABEL_WINDOW, ID_CORNER_LABEL_WINDOW }; virtual void CalcWindowSizes(bool adjustScrollBars = true); virtual void Fit() { AutoSize(); } // overridden wxWindow methods // Get the ref counted data the sheet uses, *please* try to not access this // directly if a functions exists to do it for you. wxSheetRefData* GetSheetRefData() const { return (wxSheetRefData*)GetRefData(); } // Create and send wxSheetXXXEvent depending on type and fill extra data // from a wxKeyEvent or wxMouseEvent (if NULL all keydown are set false) // returns EVT_VETOED/SKIPPED/CLAIMED enum { EVT_VETOED = -1, // veto was called on the event EVT_SKIPPED = 0, // no evt handler found or evt was Skip()ed EVT_CLAIMED = 1 // event was handled and not Skip()ed }; int SendEvent( const wxEventType type, const wxSheetCoords& coords, wxEvent* mouseOrKeyEvt = NULL ); int SendRangeEvent( const wxEventType type, const wxSheetBlock& block, bool selecting, bool add, wxEvent* mouseOrKeyEvt = NULL ); // Just send the event returning EVT_VETOED/SKIPPED/CLAIMED int DoSendEvent( wxSheetEvent* event ); enum MouseCursorMode { WXSHEET_CURSOR_SELECT_CELL = 0x0001, WXSHEET_CURSOR_SELECT_ROW = 0x0002, WXSHEET_CURSOR_SELECT_COL = 0x0004, WXSHEET_CURSOR_SELECTING = WXSHEET_CURSOR_SELECT_CELL|WXSHEET_CURSOR_SELECT_ROW|WXSHEET_CURSOR_SELECT_COL, WXSHEET_CURSOR_RESIZE_ROW = 0x0008, WXSHEET_CURSOR_RESIZE_COL = 0x0010, WXSHEET_CURSOR_RESIZING = WXSHEET_CURSOR_RESIZE_ROW|WXSHEET_CURSOR_RESIZE_COL, WXSHEET_CURSOR_SPLIT_VERTICAL = 0x0020, WXSHEET_CURSOR_SPLIT_HORIZONTAL = 0x0040, WXSHEET_CURSOR_SPLITTING = WXSHEET_CURSOR_SPLIT_VERTICAL|WXSHEET_CURSOR_SPLIT_HORIZONTAL }; // Set the m_mouseCursor for the wxCursor and m_mouseCursorMode for behavior // you should always use it and not set m_mouseCursor[Mode] directly! void SetMouseCursorMode( MouseCursorMode mode, wxWindow *win ); // Get the mouse cursor mode, &ed with mask, default returns original value int GetMouseCursorMode(int mask = ~0) const { return (m_mouseCursorMode & mask); } // Is the mouse cursor in the mode? bool HasMouseCursorMode(int mode) const { return GetMouseCursorMode(mode) != 0; } // Set the window that has capture, releases the previous one if necessary // always use this, set with NULL to release mouse void SetCaptureWindow( wxWindow *win ); wxWindow *GetCaptureWindow() const { return m_winCapture; } protected: bool DoUpdateRows(size_t row, int numRows, int update = wxSHEET_UpdateAll ); bool DoUpdateCols(size_t col, int numCols, int update = wxSHEET_UpdateAll ); virtual wxSize DoGetBestSize() const; void OnSize( wxSizeEvent& event ); wxWindow *m_winCapture; // the window that captured the mouse (don't use!) wxSheetChildWindow *m_gridWin; wxSheetChildWindow *m_rowLabelWin; wxSheetChildWindow *m_colLabelWin; wxSheetChildWindow *m_cornerLabelWin; wxScrollBar *m_horizScrollBar; wxScrollBar *m_vertScrollBar; wxPoint m_gridOrigin; // origin of the gridWin in pixels int m_scrollBarMode; bool m_keySelecting; // cell attribute cache wxSheetCellAttr m_cacheAttr; wxSheetCoords m_cacheAttrCoords; int m_cacheAttrType; // invalidates the attribute cache void ClearAttrCache(); // adds an attribute to cache void CacheAttr(const wxSheetCoords& coords, const wxSheetCellAttr &attr, wxSheetAttr_Type type ) const; // looks for an attr in cache, returns true if found bool LookupAttr(const wxSheetCoords& coords, wxSheetAttr_Type type, wxSheetCellAttr &attr) const; bool m_inOnKeyDown; int m_batchCount; bool m_resizing; enum KeyModifiers { NO_MODIFIERS = 0, CTRL_DOWN = 0x0001, SHIFT_DOWN = 0x0002, ALT_DOWN = 0x0004, META_DOWN = 0x0008 // meta is numlock in GTK so it's ignored }; int GetKeyModifiers(wxEvent *mouseOrKeyEvent) const; MouseCursorMode m_mouseCursorMode; MouseCursorMode m_mouseCursor; int m_dragLastPos; int m_dragRowOrCol; bool m_isDragging; wxPoint m_startDragPos; wxPoint m_mousePos; bool m_waitForSlowClick; // mouse timer for smooth scrolling when selecting or resizing off window void StartMouseTimer(); void StopMouseTimer(); void OnMouseTimer( wxTimerEvent &event ); wxTimer *m_mouseTimer; bool m_enable_split_vert; bool m_enable_split_horiz; wxRect m_vertSplitRect; // pos/size of the splitter rect, 0 if not shown wxRect m_horizSplitRect; // pos/size of the splitter rect, 0 if not shown void OnPaint( wxPaintEvent& event ); void OnEraseBackground( wxEraseEvent& ); void OnKeyDown( wxKeyEvent& event ); void OnKeyUp( wxKeyEvent& event ); void OnChar( wxKeyEvent& event ); // let wxWidgets translate numpad keys // ------ functions to get/send data (see also public functions) bool GetModelValues(); bool SetModelValues(); private: void Init(); friend class wxSheetTable; DECLARE_DYNAMIC_CLASS(wxSheet) DECLARE_EVENT_TABLE() DECLARE_NO_COPY_CLASS(wxSheet) }; // ---------------------------------------------------------------------------- // wxSheetEvent // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetEvent : public wxNotifyEvent { public: wxSheetEvent(int id=0, wxEventType type=wxEVT_NULL, wxObject* obj=NULL, const wxSheetCoords &coords = wxNullSheetCoords, const wxPoint &pos = wxPoint(-1, -1), bool sel = true); wxSheetEvent(const wxSheetEvent& event) : wxNotifyEvent(event), m_coords(event.m_coords), m_pos(event.m_pos), m_selecting(event.m_selecting), m_control(event.m_control), m_shift(event.m_shift), m_alt(event.m_alt), m_meta(event.m_meta) { } int GetRow() const { return m_coords.m_row; } int GetCol() const { return m_coords.m_col; } const wxSheetCoords& GetCoords() const { return m_coords; } const wxPoint& GetPosition() const { return m_pos; } bool Selecting() const { return m_selecting; } bool ControlDown() const { return m_control; } bool ShiftDown() const { return m_shift; } bool AltDown() const { return m_alt; } bool MetaDown() const { return m_meta; } // implementation // setup the Ctrl/Shift/Alt/Meta keysDown from a wxKeyEvent or wxMouseEvent // Also mouse position, but the GetEventObject must be of type wxSheet void SetKeysDownMousePos(wxEvent *mouseOrKeyEvent); virtual wxEvent *Clone() const { return new wxSheetEvent(*this); } wxSheetCoords m_coords; wxPoint m_pos; bool m_selecting; bool m_control; bool m_shift; bool m_alt; bool m_meta; DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSheetEvent) }; // ---------------------------------------------------------------------------- // wxSheetRangeSelectEvent - wxEVT_SHEET_RANGE_SELECTING(ED) // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetRangeSelectEvent : public wxSheetEvent { public: wxSheetRangeSelectEvent( int id=0, wxEventType type=wxEVT_NULL, wxObject* obj=NULL, const wxSheetBlock& block=wxNullSheetBlock, bool sel=false, bool add_to_sel=false ); wxSheetRangeSelectEvent(const wxSheetRangeSelectEvent& event) : wxSheetEvent(event), m_block(event.m_block), m_add(event.m_add) { } const wxSheetBlock& GetBlock() const { return m_block; } bool GetAddToSelection() const { return m_add; } void SetBlock( const wxSheetBlock& block ) { m_block = block; } // wxPoint GetPosition() is unused // int GetCoords/Row/Col() is unused // implementation virtual wxEvent *Clone() const { return new wxSheetRangeSelectEvent(*this); } wxSheetBlock m_block; bool m_add; DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSheetRangeSelectEvent) }; // ---------------------------------------------------------------------------- // wxSheetEditorCreatedEvent - wxEVT_SHEET_EDITOR_CREATED // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetEditorCreatedEvent : public wxCommandEvent { public: wxSheetEditorCreatedEvent( int id=0, wxEventType type=wxEVT_NULL, wxObject* obj=NULL, const wxSheetCoords& coords=wxNullSheetCoords, wxWindow* ctrl=NULL ); wxSheetEditorCreatedEvent(const wxSheetEditorCreatedEvent& evt) : wxCommandEvent(evt), m_coords(evt.m_coords), m_ctrl(evt.m_ctrl) { } const wxSheetCoords& GetCoords() const { return m_coords; } wxWindow* GetControl() const { return m_ctrl; } void SetCoords(const wxSheetCoords& coords) { m_coords = coords; } void SetControl(wxWindow* ctrl) { m_ctrl = ctrl; } // implementation virtual wxEvent *Clone() const { return new wxSheetEditorCreatedEvent(*this); } wxSheetCoords m_coords; wxWindow* m_ctrl; DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSheetEditorCreatedEvent) }; // ---------------------------------------------------------------------------- // events // ---------------------------------------------------------------------------- BEGIN_DECLARE_EVENT_TYPES() // The origin of the grid window has changed DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_VIEW_CHANGED, 1592) // The grid cursor is about to be in a new cell, veto or !Skip() to block DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SELECTING_CELL, 1592) // The grid cursor is in a new cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SELECTED_CELL, 1592) // left down click in a grid cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_LEFT_DOWN, 1580) // right down click in a grid cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_RIGHT_DOWN, 1581) // left up click in a grid cell, sent after default processing DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_LEFT_UP, 1580) // right up click in a grid cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_RIGHT_UP, 1581) // left double click in a grid cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_LEFT_DCLICK, 1582) // right double click in a grid cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_RIGHT_DCLICK, 1583) // left down click in a label cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_LEFT_DOWN, 1584) // right down click in a label cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_RIGHT_DOWN, 1585) // left up click in a label cell, sent after default processing DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_LEFT_UP, 1584) // right up click in a label cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_RIGHT_UP, 1585) // left double click in a label cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_LEFT_DCLICK, 1586) // right double click in a label cell DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_RIGHT_DCLICK, 1587) // A row has been resized, sent after default processing DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_ROW_SIZE, 1588) // A col has been resized, sent after default processing DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_COL_SIZE, 1589) // A block of cells is about to be (de)selected (veto to stop) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_RANGE_SELECTING, 1590) // A block of cells has been (de)selected DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_RANGE_SELECTED, 1590) // The value of a cell is about to be changed (veto to stop) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_VALUE_CHANGING, 1591) // The value of a cell has been changed (veto to put old val back) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_VALUE_CHANGED, 1591) // From EnableCellEditControl, the control is about to enabled (can veto) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_EDITOR_ENABLED, 1593) // From DisableCellEditControl, the control is about to disabled (can veto) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_EDITOR_DISABLED, 1594) // From EnableCellEditControl, the edit control has been created DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_EDITOR_CREATED, 1595) END_DECLARE_EVENT_TYPES() typedef void (wxEvtHandler::*wxSheetEventFunction)(wxSheetEvent&); typedef void (wxEvtHandler::*wxSheetRangeSelectEventFunction)(wxSheetRangeSelectEvent&); typedef void (wxEvtHandler::*wxSheetEditorCreatedEventFunction)(wxSheetEditorCreatedEvent&); #define EVT_SHEET_VIEW_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_VIEW_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_SELECTING_CELL(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SELECTING_CELL, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_SELECTED_CELL(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SELECTED_CELL, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_CELL_LEFT_DOWN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_LEFT_DOWN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_CELL_RIGHT_DOWN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_RIGHT_DOWN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_CELL_LEFT_UP(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_LEFT_UP, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_CELL_RIGHT_UP(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_RIGHT_UP, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_CELL_LEFT_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_LEFT_DCLICK, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_CELL_RIGHT_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_RIGHT_DCLICK, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_LABEL_LEFT_DOWN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_LEFT_DOWN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_LABEL_RIGHT_DOWN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_RIGHT_DOWN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_LABEL_LEFT_UP(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_LEFT_UP, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_LABEL_RIGHT_UP(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_RIGHT_UP, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_LABEL_LEFT_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_LEFT_DCLICK, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_LABEL_RIGHT_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_RIGHT_DCLICK, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_ROW_SIZE(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_ROW_SIZE, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_COL_SIZE(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_COL_SIZE, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_RANGE_SELECTING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_RANGE_SELECTING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetRangeSelectEventFunction, &fn), NULL ), #define EVT_SHEET_RANGE_SELECTED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_RANGE_SELECTED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetRangeSelectEventFunction, &fn), NULL ), #define EVT_SHEET_CELL_VALUE_CHANGING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_VALUE_CHANGING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_CELL_VALUE_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_VALUE_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_EDITOR_ENABLED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_EDITOR_ENABLED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_EDITOR_DISABLED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_EDITOR_DISABLED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), #define EVT_SHEET_EDITOR_CREATED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_EDITOR_CREATED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEditorCreatedEventFunction, &fn), NULL ), #if 0 // TODO: implement these ? others ? wxEVT_SHEET_CREATE_CELL; wxEVT_SHEET_CHANGE_LABELS; wxEVT_SHEET_CHANGE_SEL_LABEL; #define EVT_SHEET_CREATE_CELL(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CREATE_CELL, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxSheetEventFunction) &fn, NULL ), #define EVT_SHEET_CHANGE_LABELS(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CHANGE_LABELS, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxSheetEventFunction) &fn, NULL ), #define EVT_SHEET_CHANGE_SEL_LABEL(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CHANGE_SEL_LABEL, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxSheetEventFunction) &fn, NULL ), #endif // 0 #endif // __WX_SHEET_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/sheetatr.h0000644000076500007650000002444211350032206020176 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetatr.h // Purpose: wxSheetAttribute and related classes // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) // Modified by: John Labenski // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski, Michael Bedward // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_SHEETATR_H__ #define __WX_SHEETATR_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "sheetatr.h" #endif #include "wx/sheet/sheetdef.h" #include "wx/font.h" #include "wx/colour.h" // ---------------------------------------------------------------------------- // wxSheetCellAttr : contains all the attributes for a wxSheet cell // // Note: When created all the HasXXX return false, use Copy, Merge, or SetXXX // // The default attr for the different wxSheet areas must be complete so that // when a new attr is assigned you need only set the values you want to be // different than the default's. Unset values are retrieved from the default // attr which gets them from it's def attr and so on, they're chained together. // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellAttr : public wxObject { public: // if create then create with ref data wxSheetCellAttr( bool create = false ); // make a refed copy of the other attribute wxSheetCellAttr( const wxSheetCellAttr& attr ) : wxObject() { Ref(attr); } // Recreate the ref data, unrefing the old bool Create(); void Destroy() { UnRef(); } inline bool Ok() const { return m_refData != NULL; } // Makes a full new unrefed copy of the other, this doesn't have to be created bool Copy(const wxSheetCellAttr& other); // Copies the values from the other, but only if the other has them, this must be created bool UpdateWith(const wxSheetCellAttr& other); // Merges this with the other, copy values of other only this doesn't have them bool MergeWith(const wxSheetCellAttr &mergefrom); // setters void SetForegroundColour(const wxColour& foreColour); void SetBackgroundColour(const wxColour& backColour); void SetFont(const wxFont& font); // wxSheetAttrAlign_Type void SetAlignment(int align); void SetAlignment(int horzAlign, int vertAlign); // wxSheetAttrOrientation_Type void SetOrientation(int orientation); void SetLevel(wxSheetAttrLevel_Type level); void SetOverflow(bool allow); void SetOverflowMarker(bool draw_marker); void SetShowEditor(bool show_editor); void SetReadOnly(bool isReadOnly); void SetRenderer(const wxSheetCellRenderer& renderer); void SetEditor(const wxSheetCellEditor& editor); void SetKind(wxSheetAttr_Type kind); // validation bool HasForegoundColour() const; bool HasBackgroundColour() const; bool HasFont() const; bool HasAlignment() const; bool HasOrientation() const; bool HasLevel() const; bool HasOverflowMode() const; bool HasOverflowMarkerMode() const; bool HasShowEditorMode() const; bool HasReadWriteMode() const; bool HasRenderer() const; bool HasEditor() const; bool HasDefaultAttr() const; // bool HasKind() const - always has kind, default is wxSHEET_AttrCell // does this attr define all the HasXXX properties, except DefaultAttr // if this is true, it's a suitable default attr for an area bool IsComplete() const; // accessors const wxColour& GetForegroundColour() const; const wxColour& GetBackgroundColour() const; const wxFont& GetFont() const; int GetAlignment() const; wxOrientation GetOrientation() const; wxSheetAttrLevel_Type GetLevel() const; bool GetOverflow() const; bool GetOverflowMarker() const; bool GetShowEditor() const; bool GetReadOnly() const; wxSheetCellRenderer GetRenderer(wxSheet* grid, const wxSheetCoords& coords) const; wxSheetCellEditor GetEditor(wxSheet* grid, const wxSheetCoords& coords) const; wxSheetAttr_Type GetKind() const; // any unset values of this attr are retrieved from the default attr // if you try to set the def attr to this, it's ignored // don't bother to link multiple attributes together in a loop, obviously. const wxSheetCellAttr& GetDefaultAttr() const; void SetDefaultAttr(const wxSheetCellAttr& defaultAttr); // operators bool operator == (const wxSheetCellAttr& obj) const { return m_refData == obj.m_refData; } bool operator != (const wxSheetCellAttr& obj) const { return m_refData != obj.m_refData; } wxSheetCellAttr& operator = (const wxSheetCellAttr& obj) { if ( (*this) != obj ) Ref(obj); return *this; } wxSheetCellAttr Clone() const { wxSheetCellAttr obj; obj.Copy(*this); return obj; } wxSheetCellAttr* NewClone() const { return new wxSheetCellAttr(Clone()); } // implementation void SetType(int type, int mask); int GetType(int mask = ~0) const; bool HasType(int type) const { return GetType(type) != 0; } protected: // override wxObject's create a new m_refData virtual wxObjectRefData *CreateRefData() const; // override wxObject's create a new m_refData initialized with the given one virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; DECLARE_DYNAMIC_CLASS(wxSheetCellAttr) }; // ---------------------------------------------------------------------------- // wxSheetCellAttrRefData : data for the wxSheetCellAttr // // only use this as a LAST resort for overriding the behavior // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellAttrRefData : public wxObjectRefData { public: wxSheetCellAttrRefData(); wxSheetCellAttrRefData( const wxSheetCellAttrRefData& data ); virtual ~wxSheetCellAttrRefData(); wxColour m_foreColour, m_backColour; wxFont m_font; // stores wxSheetAttr_Type, align, orient, overflow, show edit, read, level wxUint32 m_attrTypes; // these are pointers since we can't define the edit/ren/attr all at once wxSheetCellRenderer *m_renderer; wxSheetCellEditor *m_editor; wxSheetCellAttr *m_defaultAttr; }; // ---------------------------------------------------------------------------- // wxNullSheetCellAttr - an uncreated wxSheetCellAttr for use when there's no attribute // ---------------------------------------------------------------------------- WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCellAttr) wxNullSheetCellAttr; // ---------------------------------------------------------------------------- // wxArraySheetCellAttr - wxArray of wxSheetCellAttr // wxPairArrayIntSheetCellAttr - int key, wxSheetCellAttr value pairs // wxPairArraySheetCoordsCellAttr - wxSheetCoords key, wxSheetCellAttr value pairs // ---------------------------------------------------------------------------- // Create a 1-D array of wxArraySheetCellAttr for row/col labels WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetCellAttr, wxArraySheetCellAttr, class WXDLLIMPEXP_SHEET); // Create the paired array of attrs for row/col labels DECLARE_PAIRED_INT_DATA_ARRAYS( wxSheetCellAttr, wxArraySheetCellAttr, wxPairArrayIntSheetCellAttr, class WXDLLIMPEXP_SHEET) // Create wxPairArraySheetCoordsCellAttr for storing coords keys and attr values. DECLARE_PAIREDSHEETCOORDS_DATA_ARRAYS(wxSheetCellAttr, wxArraySheetCellAttr, wxPairArraySheetCoordsCellAttr, class WXDLLIMPEXP_SHEET) // ---------------------------------------------------------------------------- // wxSheetCellAttrProvider : for wxSheetTable to retrieve/store cell attr // // implementation note: we separate it from wxSheetTable because we wish to // avoid deriving a new table class if possible, and sometimes it will be // enough to just derive another wxSheetCellAttrProvider instead // // the default implementation is reasonably efficient for the generic case, // but you might still wish to implement your own for some specific situations // if you have performance problems with the stock one or the attribute // properties lend themselves to be calculated on the fly // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellAttrProvider : public wxClientDataContainer { public: wxSheetCellAttrProvider() {} virtual ~wxSheetCellAttrProvider() {} // Get the attribute for the coords of type wxSheetAttr_Type // you must implement these cell coords for grid, row/col/corner labels // see wxSheet::IsGridCell/IsRowLabelCell/IsColLabelCell/IsCornerLabelCell // and all types except wxSHEET_AttrDefault, which sheet should have handled // If type is wxSHEET_AttrCell/Row/Col return wxNullSheetCellAttr if one is // not set. Type wxSHEET_AttrAny is used to merge row/col/cell attr // based on their level. // return wxNullSheetCellAttr if none set for coords and type virtual wxSheetCellAttr GetAttr( const wxSheetCoords& coords, wxSheetAttr_Type type ); // Set the attribute for the coords, see GetAttr for coords and type // if the !attr.Ok() the attr is removed w/o error even if it didn't exist // use wxNullSheetCellAttr to remove attr for coords and type virtual void SetAttr( const wxSheetCoords& coords, const wxSheetCellAttr& attr, wxSheetAttr_Type type ); // Update internal data whenever # rows/cols change (must be called) // this shifts rows/cols and deletes them as appropriate // you can specificly update only some of the attributes by ORing // enum wxSheetUpdate_Type for the attributes. virtual void UpdateRows( size_t pos, int numRows, int update = wxSHEET_UpdateAttributes ); virtual void UpdateCols( size_t pos, int numCols, int update = wxSHEET_UpdateAttributes ); protected: wxPairArraySheetCoordsCellAttr m_cellAttrs; wxPairArrayIntSheetCellAttr m_rowAttrs, m_colAttrs, m_rowLabelAttrs, m_colLabelAttrs; DECLARE_NO_COPY_CLASS(wxSheetCellAttrProvider) }; #endif // __WX_SHEETATR_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/sheetdef.h0000644000076500007650000004775211350032206020157 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetdef.h // Purpose: wxSheet and related classes // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) // Modified by: John Labenski // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski, Michael Bedward // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_SHEETDEF_H__ #define __WX_SHEETDEF_H__ //#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) // #pragma interface "sheetdef.h" //#endif #include "wx/defs.h" #include "wx/datetime.h" #include "wx/sheet/wx24defs.h" // wx2.4 backwards compatibility #include "wx/dynarray.h" #if wxMINOR_VERSION > 4 #include "wx/arrstr.h" #endif #include "wx/sheet/pairarr.h" // ---------------------------------------------------------------------------- // DLLIMPEXP macros // ---------------------------------------------------------------------------- // These are our DLL macros (see the contrib libs like wxPlot) /* #ifdef WXMAKINGDLL_SHEET #define WXDLLIMPEXP_SHEET WXEXPORT #define WXDLLIMPEXP_DATA_SHEET(type) WXEXPORT type #elif defined(WXUSINGDLL) #define WXDLLIMPEXP_SHEET WXIMPORT #define WXDLLIMPEXP_DATA_SHEET(type) WXIMPORT type #else // not making nor using DLL */ #define WXDLLIMPEXP_SHEET #define WXDLLIMPEXP_DATA_SHEET(type) type /* #endif */ // ---------------------------------------------------------------------------- // Two simple macros that do wxCHECK_RET/MSG for the UpdatePos functions // giving reasonable messages to help debugging // ---------------------------------------------------------------------------- #define wxSHEET_CHECKUPDATE_RET(pos, count, origcount) \ wxCHECK_RET((count == 0) || ((int(count) > 0) && (int(pos) <= int(origcount))) || \ ((int(count) < 0) && (int(pos) - int(count) <= int(origcount))), \ wxString::Format(wxT("Updating past end of array, pos %d count %d, orig count %d"), pos, count, origcount)); #define wxSHEET_CHECKUPDATE_MSG(pos, count, origcount, ret) \ wxCHECK_MSG((count == 0) || ((int(count) > 0) && (int(pos) <= int(origcount))) || \ ((int(count) < 0) && (int(pos) - int(count) <= int(origcount))), ret, \ wxString::Format(wxT("Updating past end of array, pos %d count %d, orig count %d"), pos, count, origcount)); // ---------------------------------------------------------------------------- // Complete list of classes implemented by wxSheet // ---------------------------------------------------------------------------- // Windows class WXDLLIMPEXP_SHEET wxSheet; // the spreadsheet widget class WXDLLIMPEXP_SHEET wxSheetChildWindow; // child windows of the sheet class WXDLLIMPEXP_SHEET wxSheetRefData; // internal use sheet data // Events class WXDLLIMPEXP_SHEET wxSheetEvent; // events returned from the sheet class WXDLLIMPEXP_SHEET wxSheetRangeSelectEvent; // cells (de)selected class WXDLLIMPEXP_SHEET wxSheetEditorCreatedEvent; // editor created class WXDLLIMPEXP_SHEET wxSheetSplitterEvent; // events sent from the sheet splitter // Attributes class WXDLLIMPEXP_SHEET wxSheetCellAttr; // attribute for cell/row/col class WXDLLIMPEXP_SHEET wxSheetCellAttrRefData;// refdata for attribute class WXDLLIMPEXP_SHEET wxArraySheetCellAttr; // array of cell attrs class WXDLLIMPEXP_SHEET wxPairArrayIntSheetCellAttr; // int, attr pair array class WXDLLIMPEXP_SHEET wxPairArraySheetCoordsCellAttr; // coords, attr pair array class WXDLLIMPEXP_SHEET wxSheetCellAttrProvider; // provider of attr for row/col/cell class WXDLLIMPEXP_SHEET wxSheetTypeRegistry; // internal use // String containers //class WXDLLIMPEXP_SHEET wxSheetStringArray; // wxArray of wxArrayString class WXDLLIMPEXP_SHEET wxPairArrayIntSheetString; // pair (int, wxString) class WXDLLIMPEXP_SHEET wxArrayPairArrayIntSheetString; // array of (int, str) pair class WXDLLIMPEXP_SHEET wxSheetValueProviderBase; // base class value provider class WXDLLIMPEXP_SHEET wxSheetValueProviderString; // a wxArrayString value provider class WXDLLIMPEXP_SHEET wxSheetValueProviderSparseString; // a string pair array value provider // Coords/Blocks/Selection/Int arrays/Edge arrays class WXDLLIMPEXP_SHEET wxSheetCoords; // cell coordinates class WXDLLIMPEXP_SHEET wxSheetBlock; // rectangular block of cells class WXDLLIMPEXP_SHEET wxSheetSelection; // cell selection container class WXDLLIMPEXP_SHEET wxSheetSelectionIterator; // selection iterator class WXDLLIMPEXP_SHEET wxSheetArrayEdge; // row/col edge container class WXDLLIMPEXP_SHEET wxPairArrayIntInt; // pair of (int, int) // "Widgets" class WXDLLIMPEXP_SHEET wxSheetCellRenderer; // drawing renderer for cell class WXDLLIMPEXP_SHEET wxSheetCellEditor; // cell editor // Tables class WXDLLIMPEXP_SHEET wxSheetTable; // cell value/attr provider // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- // Default parameters for wxSheet #ifdef __WXMSW__ #define WXSHEET_DEFAULT_ROW_HEIGHT 25 #else #define WXSHEET_DEFAULT_ROW_HEIGHT 30 #endif // __WXMSW__ #define WXSHEET_DEFAULT_COL_WIDTH 80 #define WXSHEET_DEFAULT_COL_LABEL_HEIGHT 32 #define WXSHEET_DEFAULT_ROW_LABEL_WIDTH 82 #define WXSHEET_LABEL_EDGE_ZONE 2 #define WXSHEET_MIN_ROW_HEIGHT 15 #define WXSHEET_MIN_COL_WIDTH 15 // type names for grid table values #define wxSHEET_VALUE_STRING _T("string") #define wxSHEET_VALUE_BOOL _T("bool") #define wxSHEET_VALUE_NUMBER _T("long") #define wxSHEET_VALUE_FLOAT _T("double") #define wxSHEET_VALUE_CHOICE _T("choice") #define wxSHEET_VALUE_CHOICEINT _T("choiceint") #define wxSHEET_VALUE_DATETIME _T("datetime") #define wxSHEET_VALUE_LABEL _T("label") // ---------------------------------------------------------------------------- // wxSheet cell drawing scheme, also applies to label cells // ---------------------------------------------------------------------------- // // -------------- <- Top line is bottom of cell above, none if row = 0, GetRowBottom(row-1) // | | <- This is GetRowTop(row) // | (row, col) | // | | // -------------- <- this pixel is GetRowBottom(row), part of this cell // ^^ ^ // || |- Right side is GetColRight(col), part of this cell // || // ||- This is GetColLeft(col) // |-- Left side is cell to left, or none if col = 0, GetColRight(col-1) // // The sheet consists of 4 individual windows each is accessed with coords // using the semantics below. // // ############################################################################ // # corner label # col label | col label | | # // # (-1, -1) # (-1, 0) | (-1, 1) | ... | (-1, GetNumberCols() - 1) # // ############################################################################ // # row label # grid cell | grid cell | | # // # (0, -1) # (0, 0) | (0, 1) | ... | ( 0, GetNumberCols() - 1) # // #--------------#-----------------------------------------------------------# // # row label # grid cell | grid cell | | # // # (1, -1) # (1, 0) | (1, 1) | ... | ( 1, GetNumberCols() - 1) # // #--------------#-----------------------------------------------------------# // # # | | | # // # ... # ... | ... | ... | ... # // #--------------#-----------------------------------------------------------# // # # | | | (GetNumberRows() - 1, # // # # GetNumberRows() - 1 | GetNumberCols() - 1) # // ############################################################################ // ---------------------------------------------------------------------------- // wxSheetCell_Type : enum of the different window cell types // ---------------------------------------------------------------------------- enum wxSheetCell_Type { wxSHEET_CELL_UNKNOWN = 0, // An invalid cell coords wxSHEET_CELL_GRID, // A grid cell row >= 0 && col >= 0 wxSHEET_CELL_ROWLABEL, // A row label cell row >= 0 && col == -1 wxSHEET_CELL_COLLABEL, // A col label cell row == -1 && col >= 0 wxSHEET_CELL_CORNERLABEL // The corner label row == -1 && col == -1 }; // ---------------------------------------------------------------------------- // wxSheetSelectionMode_Type : how selections are made by the mouse and cursor // ---------------------------------------------------------------------------- enum wxSheetSelectionMode_Type { wxSHEET_SelectNone = 0x0001, // don't allow selections by mouse or keyboard // direct calls to the selections work however wxSHEET_SelectCells = 0x0002, // single cells, blocks, rows, and cols wxSHEET_SelectRows = 0x0004, // only rows can be selected wxSHEET_SelectCols = 0x0008, // only cols can be selected }; // ---------------------------------------------------------------------------- // wxSheetMouseDrag_Type : can the mouse or keyboard be used to resize cells // ---------------------------------------------------------------------------- enum wxSheetDragCellSize_Type { wxSHEET_DragLabelRowHeight = 0x0010, // Mouse can resize row heights on label wxSHEET_DragLabelColWidth = 0x0020, // Mouse can resize col widths on label wxSHEET_DragLabelCellSize = (wxSHEET_DragLabelRowHeight|wxSHEET_DragLabelColWidth), wxSHEET_DragLabelRowWidth = 0x0040, // Mouse can resize row label width wxSHEET_DragLabelColHeight = 0x0080, // Mouse can resize col label height wxSHEET_DragLabelSize = (wxSHEET_DragLabelRowWidth|wxSHEET_DragLabelColHeight), wxSHEET_DragGridRowHeight = 0x0100, // Mouse can resize row heights on grid wxSHEET_DragGridColWidth = 0x0200, // Mouse can resize col widths on grid wxSHEET_DragGridCellSize = (wxSHEET_DragGridRowHeight|wxSHEET_DragGridColWidth), wxSHEET_DragCellSize = (wxSHEET_DragLabelCellSize|wxSHEET_DragGridCellSize), wxSHEET_DragSize = (wxSHEET_DragCellSize|wxSHEET_DragLabelSize) }; // ---------------------------------------------------------------------------- // wxSHEET_Update_Type : when redimensioning rows/cols what data containers // should be updated as well. You probably want to do them all, unless you // can ensure that no problems will occur. // ---------------------------------------------------------------------------- enum wxSheetUpdate_Type { wxSHEET_UpdateNone = 0x0000, // update nothing wxSHEET_UpdateGridCellValues = 0x0001, // update the grid cell data container wxSHEET_UpdateRowLabelValues = 0x0002, // update the row label data container wxSHEET_UpdateColLabelValues = 0x0004, // update the col label data container wxSHEET_UpdateLabelValues = wxSHEET_UpdateRowLabelValues|wxSHEET_UpdateColLabelValues, // update the label containers wxSHEET_UpdateValues = wxSHEET_UpdateGridCellValues|wxSHEET_UpdateLabelValues, wxSHEET_UpdateSpanned = 0x0008, // update the spanned cells wxSHEET_UpdateGridCellAttrs = 0x0010, // update grid cell attributes wxSHEET_UpdateRowLabelAttrs = 0x0020, // update row label attributes wxSHEET_UpdateColLabelAttrs = 0x0040, // update col label attributes wxSHEET_UpdateLabelAttrs = wxSHEET_UpdateRowLabelAttrs|wxSHEET_UpdateColLabelAttrs, wxSHEET_UpdateAttributes = wxSHEET_UpdateGridCellAttrs|wxSHEET_UpdateLabelAttrs, // update the attr container wxSHEET_UpdateSelection = 0x0100, // update the selection wxSHEET_UpdateAll = (wxSHEET_UpdateValues|wxSHEET_UpdateSpanned|wxSHEET_UpdateAttributes|wxSHEET_UpdateSelection), wxSHEET_UpdateType_Mask = wxSHEET_UpdateAll }; // ---------------------------------------------------------------------------- // wxSheetCellAttr_Type : contains all the attributes for a wxSheet cell // ---------------------------------------------------------------------------- enum wxSheetAttr_Type { // A default attr, used when no particular one is set, all areas have def attr wxSHEET_AttrDefault = 0x00010, // The attr for a single cell coords, applies to all areas wxSHEET_AttrCell = 0x00020, // The attr for a row of cells, only applies to the grid cells // not label attrs, they only have default or single cell wxSHEET_AttrRow = 0x00040, // The attr for a col of cells, only applies to the grid cells // not label attrs, they only have default or single cell wxSHEET_AttrCol = 0x00080, // Only for getting attrs, get an attr that may be merged from cell/row/col // attrs, if none of those then resort to default attr for area // this is the best choice for getting an attr since it's guaranteed to work wxSHEET_AttrAny = wxSHEET_AttrDefault|wxSHEET_AttrCell|wxSHEET_AttrRow|wxSHEET_AttrCol, wxSHEET_AttrType_Mask = wxSHEET_AttrAny }; // ---------------------------------------------------------------------------- // Alignment of the text (or whatever) for a sheet cell attribute enum wxSheetAttrAlign_Type { // wxALIGN_TOP=wxALIGN_LEFT=wxALIGN_NOT=0, use these for unset wxSHEET_AttrAlignHorizUnset = 0x01000, wxSHEET_AttrAlignVertUnset = 0x02000, wxSHEET_AttrAlignUnset = (wxSHEET_AttrAlignHorizUnset|wxSHEET_AttrAlignVertUnset), wxSHEET_AttrAlignCenterHoriz = wxALIGN_CENTER_HORIZONTAL, // = 0x0100, wxSHEET_AttrAlignLeft = wxALIGN_LEFT, // = wxALIGN_NOT, wxSHEET_AttrAlignTop = wxALIGN_TOP, // = wxALIGN_NOT, wxSHEET_AttrAlignRight = wxALIGN_RIGHT, // = 0x0200, wxSHEET_AttrAlignBottom = wxALIGN_BOTTOM, // = 0x0400, wxSHEET_AttrAlignCenterVert = wxALIGN_CENTER_VERTICAL, // = 0x0800, wxSHEET_AttrAlignCenter = wxALIGN_CENTER, // = (wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL), wxSHEET_AttrAlignType_Mask = (wxALIGN_MASK|wxSHEET_AttrAlignUnset), // = 0x0f00 // A bit mask for the wxALIGN_XXX enums for extracting horiz and vert alignments wxSHEET_AttrAlignHoriz_Mask = (wxALIGN_LEFT|wxALIGN_RIGHT|wxALIGN_CENTER_HORIZONTAL|wxSHEET_AttrAlignHorizUnset), wxSHEET_AttrAlignVert_Mask = (wxALIGN_TOP|wxALIGN_BOTTOM|wxALIGN_CENTER_VERTICAL|wxSHEET_AttrAlignVertUnset) }; // ---------------------------------------------------------------------------- // Orientation of the text (or whatever) for a sheet cell attribute enum wxSheetAttrOrientation_Type { wxSHEET_AttrOrientUnset = 0, wxSHEET_AttrOrientHoriz = wxHORIZONTAL, // 0x0004 Horizontally orientated wxSHEET_AttrOrientVert = wxVERTICAL, // 0x0008 Vertically orientated wxSHEET_AttrOrientType_Mask = (wxSHEET_AttrOrientHoriz|wxSHEET_AttrOrientVert) }; // ---------------------------------------------------------------------------- // Level of the attribute if there are multiple attrs per cell // default ordering if all have same level is cell->row->col // default attributes for the wxSheet are initialized to wxSHEET_AttrLevelBottom enum wxSheetAttrLevel_Type { wxSHEET_AttrLevelUnset = 0, wxSHEET_AttrLevelBottom = 0x0010000, wxSHEET_AttrLevelMiddle = 0x0020000, wxSHEET_AttrLevelTop = 0x0040000, wxSHEET_AttrLevelType_Mask = (wxSHEET_AttrLevelBottom|wxSHEET_AttrLevelMiddle|wxSHEET_AttrLevelTop) }; // ---------------------------------------------------------------------------- // Read/Write mode of an attribute enum wxSheetAttrRead_Type { wxSHEET_AttrReadUnset = 0, wxSHEET_AttrReadWrite = 0x0100000, wxSHEET_AttrReadOnly = 0x0200000, wxSHEET_AttrReadType_Mask = (wxSHEET_AttrReadWrite|wxSHEET_AttrReadOnly) }; // ---------------------------------------------------------------------------- // Can the cell contents overflow in the cells to the right? enum wxSheetAttrOverflow_Type { wxSHEET_AttrOverflowUnset = 0, wxSHEET_AttrOverflow = 0x0400000, wxSHEET_AttrOverflowNot = 0x0800000, wxSHEET_AttrOverflowType_Mask = (wxSHEET_AttrOverflow|wxSHEET_AttrOverflowNot) }; // ---------------------------------------------------------------------------- // If the cell contents overflows then should a |> tick mark be drawn to show it enum wxSheetAttrOverflowMarker_Type { wxSHEET_AttrOverflowMarkerUnset = 0, wxSHEET_AttrOverflowMarker = 0x1000000, wxSHEET_AttrOverflowMarkerNot = 0x2000000, wxSHEET_AttrOverflowMarkerType_Mask = (wxSHEET_AttrOverflowMarker|wxSHEET_AttrOverflowMarkerNot) }; // ---------------------------------------------------------------------------- // Should the editors always be shown FIXME not implemented enum wxSheetAttrShowEditor_Type { wxSHEET_AttrShowEditorUnset = 0, wxSHEET_AttrShowEditor = 0x4000000, wxSHEET_AttrShowEditorNot = 0x8000000, wxSHEET_AttrShowEditorType_Mask = (wxSHEET_AttrShowEditor|wxSHEET_AttrShowEditorNot) }; // ---------------------------------------------------------------------------- // DECLARE_PAIREDSHEETCOORDS_DATA_ARRAYS // Create a pairing of wxSheetCoords and another class that will be sorted // for a quicker lookup. This macro also includes additional functions // UpdateRows(size_t pos, int numRows), UpdateCols(size_t pos, int numCols) // for when for when rows/cols are inserted/deleted // ---------------------------------------------------------------------------- #include "wx/sheet/sheetsel.h" #define DECLARE_PAIREDSHEETCOORDS_DATA_ARRAYS(Tval, TvalArray, name, classexp) \ DECLARE_PAIRED_DATA_ARRAYS_BASE(wxSheetCoords, wxArraySheetCoords, Tval, TvalArray, name, classexp) \ public: \ bool UpdateRows( size_t pos, int numRows ); \ bool UpdateCols( size_t pos, int numCols ); \ }; #define DEFINE_PAIREDSHEETCOORDS_DATA_ARRAYS(Tval, name) \ DEFINE_PAIRED_DATA_ARRAYS(wxSheetCoords, Tval, name) \ bool name::UpdateRows( size_t pos_, int numRows ) \ { \ if (numRows == 0) return false; \ int n, count = GetCount(), pos = pos_; \ bool done = false, remove = numRows < 0; \ for ( n = 0; n < count; n++ ) \ { \ wxSheetCoords& coords = GetItemKey(n); \ if (coords.m_row >= pos) \ { \ if (remove && (coords.m_row < pos - numRows)) \ { done = true; RemoveAt(n); count--; n--; } \ else \ { done = true; coords.m_row += numRows; } \ } \ } \ return done; \ } \ bool name::UpdateCols( size_t pos_, int numCols ) \ { \ if (numCols == 0) return false; \ int n, count = GetCount(), pos = pos_; \ bool done = false, remove = numCols < 0; \ for ( n = 0; n < count; n++ ) \ { \ wxSheetCoords& coords = GetItemKey(n); \ if (coords.m_col >= pos) \ { \ if (remove && (coords.m_col < pos - numCols)) \ { done = true; RemoveAt(n); count--; n--; } \ else \ { done = true; coords.m_col += numCols; } \ } \ } \ return done; \ } // ---------------------------------------------------------------------------- // DECLARE_SHEETOBJREFDATA_COPY_CLASS for Renderers and Editors // ---------------------------------------------------------------------------- // classes must define a "bool Copy(const classname& other)" function to copy all // the data in the class so that Clone can create a "new" copied instance. #define DECLARE_SHEETOBJREFDATA_COPY_CLASS(classname, basename) \ DECLARE_DYNAMIC_CLASS(classname) \ public: \ virtual basename * Clone() const { classname * aclass = new classname(); aclass->Copy( * ((classname * )this)); return (basename * )aclass; } #endif // __WX_SHEETDEF_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/sheetedg.h0000644000076500007650000001046211350032206020144 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetedg.h // Purpose: wxSheetArrayEdge // Author: John Labenski // Modified by: // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_SHEETEDG_H__ #define __WX_SHEETEDG_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "sheetedg.h" #endif #include "wx/sheet/sheetdef.h" // ---------------------------------------------------------------------------- // wxPairArrayIntInt - pair array of (int, int) // used to store the min col widths for rows and cols // ---------------------------------------------------------------------------- DECLARE_PAIRED_INT_DATA_ARRAYS( int, wxArrayInt, wxPairArrayIntInt, class WXDLLIMPEXP_SHEET ) // ---------------------------------------------------------------------------- // wxSheetArrayEdge - a wxArrayInt container that sums its values, starts at 0 // Used in the wxSheet to lookup the pixel position of the cells // Automatically creates the arrays as necessary and deletes them if not. // Tries to clear arrays whenever possible to save memory // Stores only the maxes (rights/bottoms) of the edges, but can be used // to get their mins (lefts/tops) and sizes (widths/heights). // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetArrayEdge { public: // Create an array of initial 'count' edges with default_size wxSheetArrayEdge( size_t count = 0, size_t default_size = 1, size_t min_allowed_size = 0 ); // Get the number of edges int GetCount() const { return m_count; } // Find the index of the element that corresponds to this coord // if clipToMinMax return the min or max edge element, else -1 for out of bounds int FindIndex(int val, bool clipToMinMax) const; // Find the index of the element whose max edge is within +/- edge_size int FindMaxEdgeIndex(int val, int edge_size = WXSHEET_LABEL_EDGE_ZONE) const; // Get the minimum of the element (left or top edge) int GetMin(size_t index) const; // Get the maximum of the element (right or bottom edge) int GetMax(size_t index) const; // Get the size of the element (width or height) // note : GetSize(n) = GetMax(n) - GetMin(n) + 1; // eg. 0123|4567|89 for index 1 : min = 4, max = 7, size = 4 = max-min+1 int GetSize(size_t index) const; // Set the size of the element (width or height) void SetSize(size_t item, int size); // Get the default size to use between the edges int GetDefaultSize() const { return m_default_size; } // Set the default size to use between edges, used when inserting // if resizeExisting then make all equal widths void SetDefaultSize(int default_size, bool resizeExisting = false); // Get the minimum size for this index, = GetMinAllowedSize unless set higher int GetMinSize(size_t index) const; // Set the minimum size for this index, must be >= min allowed size void SetMinSize(size_t index, int size); // Get the min allowed size for all elements int GetMinAllowedSize() const { return m_min_allowed_size; } // set the min allowed size, resize the existing sizes to match the min size // if resizeExisting and return if anything was done bool SetMinAllowedSize(int min_allowed_size, bool resizeExisting = false); // Clear the number of edges to zero void Clear() { m_data.Clear(); m_count = 0; } // Update the number of edges by inserting at pos if num > 0, else deleting // inserts use the defaut size. void UpdatePos(size_t pos, int num); protected: bool CheckMinimize(); // maybe we don't need the array anymore void InitArray(); // init array to the default size int m_count; // number of elements int m_default_size; // default size to init with int m_min_allowed_size; // overall min allowed size wxArrayInt m_data; // maxes of each index, filled as needed wxPairArrayIntInt m_minSizes; // min sizes for specific indexes }; #endif // __WX_SHEETEDG_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/sheetedt.h0000644000076500007650000004654311350032206020172 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetedt.h // Purpose: wxSheet controls // Author: Paul Gammans, Roger Gammans // Modified by: John Labenski // Created: 11/04/2001 // RCS-ID: $Id$ // Copyright: (c) John Labenski, The Computer Surgery (paul@compsurg.co.uk) // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_SHEETEDT_H__ #define __WX_SHEETEDT_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "sheetedt.h" #endif #include "wx/sheet/sheetdef.h" #include "wx/datetime.h" #include "wx/bitmap.h" class WXDLLIMPEXP_SHEET wxSheetCellEditorRefData; class WXDLLEXPORT wxWindow; class WXDLLEXPORT wxCheckBox; class WXDLLEXPORT wxComboBox; class WXDLLEXPORT wxTextCtrl; class WXDLLEXPORT wxSpinCtrl; // ---------------------------------------------------------------------------- // wxSheetCellEditorEvtHandler - an event handler for the editors that // forwards the keydown and char events to the sheet. // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellEditorEvtHandler : public wxEvtHandler { public: wxSheetCellEditorEvtHandler() : m_sheet(NULL), m_editor(NULL) { } wxSheetCellEditorEvtHandler(wxSheet* sheet, const wxSheetCellEditor &editor); void OnKeyDown(wxKeyEvent& event); void OnChar(wxKeyEvent& event); void OnDestroy(wxWindowDestroyEvent& event); wxSheet *m_sheet; // This is a pointer, not a refed editor since editor's destructor // pops event handler which deletes this and we don't want recursion wxSheetCellEditorRefData *m_editor; private: DECLARE_DYNAMIC_CLASS(wxSheetCellEditorEvtHandler) DECLARE_EVENT_TABLE() DECLARE_NO_COPY_CLASS(wxSheetCellEditorEvtHandler) }; // ---------------------------------------------------------------------------- // wxSheetCellEditor // ---------------------------------------------------------------------------- // This class is responsible for providing and manipulating the in-place edit // controls for the grid. The refdata instances of wxSheetCellEditor // (actually, instances of derived classes since it is an ABC) can be // associated with the cell attributes for individual cells, rows, columns, or // even for the entire grid (the default). // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellEditor : public wxObject { public: wxSheetCellEditor( wxSheetCellEditorRefData *editor = NULL ); wxSheetCellEditor( const wxSheetCellEditor& editor ) { Ref(editor); } void Destroy() { UnRef(); } bool Ok() const { return m_refData != NULL; } // Is this editor ready to use (typically means the control is created) bool IsCreated() const; // Is the control currently shown bool IsShown() const; // Get a pointer to the control wxWindow* GetControl() const; // Destroy the old control (if any) and set the new one void SetControl(wxWindow* control); // Destroy the control, doesn't fail even if the control isn't created void DestroyControl(); // Creates the actual edit control using the parent, id, and // pushing the evtHandler onto it if !NULL. void CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet); // Size and position the edit control, uses attr.GetAlignment if Ok. void SetSize(const wxRect& rect, const wxSheetCellAttr& attr); // get the preferred size of the editor for its contents wxSize GetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, const wxSheetCoords& coords); // Show or hide the edit control, use the specified attributes to set // colours/fonts for it if attr is Ok. void Show(bool show, const wxSheetCellAttr &attr); // Draws the part of the cell not occupied by the control: the base class // version just fills it with background colour from the attribute void PaintBackground(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // Fetch the value from the table and prepare the edit control // to begin editing. Set the focus to the edit control. void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); // Complete the editing of the current cell. Returns true if the value has // changed. If necessary, the control may be destroyed. bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); // Reset the value in the control back to its starting value void ResetValue(); // return true to allow the given key to start editing: the base class // version only checks that the event has no modifiers. The derived // classes are supposed to do "if ( base::IsAcceptedKey() && ... )" in // their IsAcceptedKey() implementation, although, of course, it is not a // mandatory requirment. // // NB: if the key is F2 (special), editing will always start and this // method will not be called at all (but StartingKey() will) bool IsAcceptedKey(wxKeyEvent& event); // If the editor is enabled by pressing keys on the grid, this will be // called to let the editor do something about that first key if desired void StartingKey(wxKeyEvent& event); // if the editor is enabled by clicking on the cell, this method will be // called void StartingClick(); // Some types of controls on some platforms may need some help // with the Return key. void HandleReturn(wxKeyEvent& event); // the wxSheetCellEditorEvtHandler passes the key event here first // return false to stop default EvtHandler processing bool OnKeyDown(wxKeyEvent& event); // the wxSheetCellEditorEvtHandler passes the key event here first // return false to stop default EvtHandler processing bool OnChar(wxKeyEvent& event); // interpret renderer parameters: arbitrary string whose interpretation is // left to the derived classes void SetParameters(const wxString& params); // Get the current value of the control as a string wxString GetValue() const; // Get the value that the editor started with wxString GetInitValue() const; bool Copy(const wxSheetCellEditor& other); // operators bool operator == (const wxSheetCellEditor& obj) const { return m_refData == obj.m_refData; } bool operator != (const wxSheetCellEditor& obj) const { return m_refData != obj.m_refData; } wxSheetCellEditor& operator = (const wxSheetCellEditor& obj) { if ( (*this) != obj ) Ref(obj); return *this; } wxSheetCellEditor Clone() const { wxSheetCellEditor obj; obj.Copy(*this); return obj; } wxSheetCellEditor* NewClone() const { return new wxSheetCellEditor(Clone()); } DECLARE_DYNAMIC_CLASS(wxSheetCellEditor) }; WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCellEditor) wxNullSheetCellEditor; // ---------------------------------------------------------------------------- // wxSheetCellEditorRefData // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellEditorRefData : public wxObject, public wxObjectRefData { public: wxSheetCellEditorRefData() : m_control(NULL) {} virtual ~wxSheetCellEditorRefData(); virtual bool IsCreated() const { return (GetControl() != NULL); } virtual bool IsShown() const; wxWindow* GetControl() const { return m_control; } virtual void SetControl(wxWindow* control); virtual void DestroyControl(); virtual void CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet); virtual void SetSize(const wxRect& rect, const wxSheetCellAttr &attr); // get the preferred size of the cell for its contents virtual wxSize GetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, const wxSheetCoords& coords); virtual void Show(bool show, const wxSheetCellAttr &attr); virtual void PaintBackground(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); virtual void BeginEdit(const wxSheetCoords& WXUNUSED(coords), wxSheet* WXUNUSED(grid)) {} virtual bool EndEdit(const wxSheetCoords& WXUNUSED(coords), wxSheet* WXUNUSED(grid)) { return false; } virtual void ResetValue() {} virtual bool IsAcceptedKey(wxKeyEvent& event); virtual void StartingKey(wxKeyEvent& event) { event.Skip(); } virtual bool OnKeyDown(wxKeyEvent& WXUNUSED(event)) { return true; } virtual bool OnChar(wxKeyEvent& WXUNUSED(event)) { return true; } virtual void StartingClick() {} virtual void HandleReturn(wxKeyEvent& event) { event.Skip(); } virtual void SetParameters(const wxString& WXUNUSED(params)) {} virtual wxString GetValue() const { return wxEmptyString; } virtual wxString GetInitValue() const { return wxEmptyString; } bool Copy(const wxSheetCellEditorRefData& WXUNUSED(other)) { return true; } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellEditorRefData, wxSheetCellEditorRefData) wxWindow* m_control; // the control we show on screen }; //----------------------------------------------------------------------------- // wxSheetCellTextEditorRefData - the editor for string/text data //----------------------------------------------------------------------------- #if wxUSE_TEXTCTRL class WXDLLIMPEXP_SHEET wxSheetCellTextEditorRefData : public wxSheetCellEditorRefData { public: wxSheetCellTextEditorRefData() : m_maxChars(0) {} virtual void CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet); virtual void SetSize(const wxRect& rect, const wxSheetCellAttr &attr); virtual void PaintBackground(wxSheet& , const wxSheetCellAttr& , wxDC& , const wxRect& , const wxSheetCoords& , bool ) {} virtual bool IsAcceptedKey(wxKeyEvent& event); virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); virtual void ResetValue(); virtual void StartingKey(wxKeyEvent& event); virtual void HandleReturn(wxKeyEvent& event); virtual bool OnChar(wxKeyEvent& event); // parameters string format is "max_width" virtual void SetParameters(const wxString& params); virtual wxString GetValue() const; virtual wxString GetInitValue() const { return m_startValue; } bool Copy(const wxSheetCellTextEditorRefData& other) { return wxSheetCellEditorRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellTextEditorRefData, wxSheetCellEditorRefData) // parts of our virtual functions reused by the derived classes void DoBeginEdit(const wxString& startValue); void DoResetValue(const wxString& startValue); wxTextCtrl *GetTextCtrl() const { return (wxTextCtrl *)GetControl(); } size_t m_maxChars; // max number of chars allowed wxString m_startValue; int m_maxLength; // largest length in the textctrl yet }; // ---------------------------------------------------------------------------- // wxSheetCellAutoWrapStringEditorRefData // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellAutoWrapStringEditorRefData : public wxSheetCellTextEditorRefData { public: wxSheetCellAutoWrapStringEditorRefData() : wxSheetCellTextEditorRefData() { } virtual void CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet); bool Copy(const wxSheetCellAutoWrapStringEditorRefData& other) { return wxSheetCellTextEditorRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellAutoWrapStringEditorRefData, wxSheetCellEditorRefData) }; #endif // wxUSE_TEXTCTRL //----------------------------------------------------------------------------- // wxSheetCellNumberEditorRefData : the editor for numeric (long) data //----------------------------------------------------------------------------- #if defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) class WXDLLIMPEXP_SHEET wxSheetCellNumberEditorRefData : public wxSheetCellTextEditorRefData { public: // specify the range - if min == max == -1, no range checking is done wxSheetCellNumberEditorRefData(int min = -1, int max = -1) : m_min(min), m_max(max), m_startValue(0) {} virtual void CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet); virtual bool IsAcceptedKey(wxKeyEvent& event); virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); virtual void ResetValue(); virtual void StartingKey(wxKeyEvent& event); // parameters string format is "min,max" virtual void SetParameters(const wxString& params); virtual wxString GetValue() const; int GetValueInt() const; virtual wxString GetInitValue() const; // if HasRange(), we use wxSpinCtrl - otherwise wxTextCtrl bool HasRange() const { return m_min != m_max; } bool Copy(const wxSheetCellNumberEditorRefData& other); DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellNumberEditorRefData, wxSheetCellEditorRefData) wxSpinCtrl *GetSpinCtrl() const { return (wxSpinCtrl *)GetControl(); } int m_min, m_max; long m_startValue; }; #endif //defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) //----------------------------------------------------------------------------- // wxSheetCellFloatEditorRefData: the editor for floating point numbers (double) data //----------------------------------------------------------------------------- #if wxUSE_TEXTCTRL class WXDLLIMPEXP_SHEET wxSheetCellFloatEditorRefData : public wxSheetCellTextEditorRefData { public: wxSheetCellFloatEditorRefData(int width = -1, int precision = -1) : m_width(width), m_precision(precision), m_startValue(0) {} virtual void CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet); virtual bool IsAcceptedKey(wxKeyEvent& event); virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); virtual void ResetValue(); virtual void StartingKey(wxKeyEvent& event); // parameters string format is "width,precision" virtual void SetParameters(const wxString& params); // string representation of a double value virtual wxString GetInitValue() const { return GetStringValue(m_startValue); } virtual wxString GetStringValue(double value) const; bool Copy(const wxSheetCellFloatEditorRefData& other); DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellFloatEditorRefData, wxSheetCellEditorRefData) int m_width, m_precision; double m_startValue; }; #endif // wxUSE_TEXTCTRL //----------------------------------------------------------------------------- // wxSheetCellBoolEditorRefData: the editor for boolean data //----------------------------------------------------------------------------- #if wxUSE_CHECKBOX class WXDLLIMPEXP_SHEET wxSheetCellBoolEditorRefData : public wxSheetCellEditorRefData { public: wxSheetCellBoolEditorRefData() : m_startValue(false) {} virtual void CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet); virtual void SetSize(const wxRect& rect, const wxSheetCellAttr &attr); virtual void Show(bool show, const wxSheetCellAttr &attr); virtual bool IsAcceptedKey(wxKeyEvent& event); virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); virtual void ResetValue(); virtual void StartingClick(); virtual wxString GetValue() const; bool Copy(const wxSheetCellBoolEditorRefData& other) { return wxSheetCellEditorRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellBoolEditorRefData, wxSheetCellEditorRefData) wxCheckBox *GetCheckBox() const { return (wxCheckBox *)GetControl(); } bool m_startValue; }; #endif // wxUSE_CHECKBOX //----------------------------------------------------------------------------- // wxSheetCellChoiceEditorRefData: choose from a list of strings //----------------------------------------------------------------------------- #if wxUSE_COMBOBOX class WXDLLIMPEXP_SHEET wxSheetCellChoiceEditorRefData : public wxSheetCellEditorRefData { public: // if !allowOthers, user can't type a string not in choices array wxSheetCellChoiceEditorRefData(size_t count = 0, const wxString choices[] = NULL, bool allowOthers = false); wxSheetCellChoiceEditorRefData(const wxArrayString& choices, bool allowOthers = false); virtual void CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet); virtual void PaintBackground(wxSheet& grid, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); virtual void ResetValue(); // parameters string format is "item1[,item2[...,itemN]]" virtual void SetParameters(const wxString& params); virtual wxString GetValue() const; bool Copy(const wxSheetCellChoiceEditorRefData& other); DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellChoiceEditorRefData, wxSheetCellEditorRefData) wxComboBox *GetComboBox() const { return (wxComboBox *)GetControl(); } wxString m_startValue; wxArrayString m_choices; bool m_allowOthers; }; // ---------------------------------------------------------------------------- // wxSheetCellEnumEditorRefData // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellEnumEditorRefData : public wxSheetCellChoiceEditorRefData { public: wxSheetCellEnumEditorRefData( const wxString& choices = wxEmptyString ); virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); bool Copy(const wxSheetCellEnumEditorRefData& other) { return wxSheetCellChoiceEditorRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellEnumEditorRefData, wxSheetCellEditorRefData) long int m_startint; }; #endif // wxUSE_COMBOBOX #endif //__WX_SHEETEDT_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/sheetren.h0000644000076500007650000004120111350032206020164 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetren.h // Purpose: wxSheet controls // Author: Paul Gammans, Roger Gammans // Modified by: John Labenski // Created: 11/04/2001 // RCS-ID: $Id$ // Copyright: (c) John Labenski, The Computer Surgery (paul@compsurg.co.uk) // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_SHEETREN_H__ #define __WX_SHEETREN_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "sheetren.h" #endif #include "wx/sheet/sheetdef.h" #include "wx/datetime.h" #include "wx/bitmap.h" class WXDLLIMPEXP_SHEET wxSheetCellRendererRefData; // ---------------------------------------------------------------------------- // wxSheetCellRenderer: // ---------------------------------------------------------------------------- // This class is responsible for actually drawing the cell in the sheet. // You may pass it to a wxSheetCellAttr to change the format of one given cell // or to wxSheet::SetDefaultRenderer() to change the view of all default cells. // // Rendering is done by the wxObject::m_refData which must be derived from // wxSheetCellRendererRefData. All the functions are passed directly to the // ref counted renderer. // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellRenderer : public wxObject { public: wxSheetCellRenderer(wxSheetCellRendererRefData *renderer = NULL); wxSheetCellRenderer( const wxSheetCellRenderer& renderer ) { Ref(renderer); } void Destroy() { UnRef(); } bool Ok() const { return m_refData != NULL; } // draw the given cell on the provided DC inside the given rectangle // using the style specified by the attribute and the default or selected // state corresponding to the isSelected value. void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // get the preferred size of the cell for its contents wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords); // interpret renderer parameters: arbitrary string whose interpretation is // left to the derived classes void SetParameters(const wxString& params); bool Copy(const wxSheetCellRenderer& other); // operators bool operator == (const wxSheetCellRenderer& obj) const { return m_refData == obj.m_refData; } bool operator != (const wxSheetCellRenderer& obj) const { return m_refData != obj.m_refData; } wxSheetCellRenderer& operator = (const wxSheetCellRenderer& obj) { if ( (*this) != obj ) Ref(obj); return *this; } wxSheetCellRenderer Clone() const { wxSheetCellRenderer obj; obj.Copy(*this); return obj; } wxSheetCellRenderer* NewClone() const { return new wxSheetCellRenderer(Clone()); } DECLARE_DYNAMIC_CLASS(wxSheetCellRenderer) }; WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCellRenderer) wxNullSheetCellRenderer; // ---------------------------------------------------------------------------- // wxSheetCellRendererRefData - base class for rendering a cell // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellRendererRefData : public wxObjectRefData, public wxObject { public: wxSheetCellRendererRefData() {} // this pure virtual function has a default implementation which will // prepare the DC using the given attribute: it will draw the cell rectangle // with the bg colour from attr and set the dc's text colour and font virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // get the preferred size of the cell for its contents virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords); // Get a string representation of the cell value virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); // interpret renderer parameters: arbitrary string whose interpretation is // left to the derived classes virtual void SetParameters(const wxString& WXUNUSED(params)) {} // always define Copy for DECLARE_SHEETOBJREFDATA_COPY_CLASS bool Copy(const wxSheetCellRendererRefData& WXUNUSED(other)) { return true; } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellRendererRefData, wxSheetCellRendererRefData) }; // ---------------------------------------------------------------------------- // wxSheetCellStringRendererRefData // ---------------------------------------------------------------------------- // the default renderer for the cells containing string data class WXDLLIMPEXP_SHEET wxSheetCellStringRendererRefData : public wxSheetCellRendererRefData { public: wxSheetCellStringRendererRefData(); // draw the string virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // return the string extent virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords); void DoDraw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // set the text colours before drawing void SetTextColoursAndFont(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, bool isSelected); // calc the string extent for given string/font wxSize DoGetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxString& text); bool Copy(const wxSheetCellStringRendererRefData& other) { return wxSheetCellRendererRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellStringRendererRefData, wxSheetCellRendererRefData) }; // ---------------------------------------------------------------------------- // wxSheetCellAutoWrapStringRendererRefData // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellAutoWrapStringRendererRefData : public wxSheetCellStringRendererRefData { public: wxSheetCellAutoWrapStringRendererRefData() : wxSheetCellStringRendererRefData() { } virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords); wxArrayString GetTextLines( wxSheet& sheet, wxDC& dc, const wxSheetCellAttr& attr, const wxRect& rect, const wxSheetCoords& coords); bool Copy(const wxSheetCellAutoWrapStringRendererRefData& other) { return wxSheetCellStringRendererRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellAutoWrapStringRendererRefData, wxSheetCellRendererRefData) }; // ---------------------------------------------------------------------------- // wxSheetCellNumberRendererRefData // ---------------------------------------------------------------------------- // the default renderer for the cells containing numeric (long) data class WXDLLIMPEXP_SHEET wxSheetCellNumberRendererRefData : public wxSheetCellStringRendererRefData { public: wxSheetCellNumberRendererRefData() {} virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); bool Copy(const wxSheetCellNumberRendererRefData& other) { return wxSheetCellStringRendererRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellNumberRendererRefData, wxSheetCellRendererRefData) }; // ---------------------------------------------------------------------------- // wxSheetCellFloatRendererRefData // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellFloatRendererRefData : public wxSheetCellStringRendererRefData { public: wxSheetCellFloatRendererRefData(int width = -1, int precision = -1) : m_width(width), m_precision(precision) { } // get/change formatting parameters "%[width].[precision]f" int GetWidth() const { return m_width; } void SetWidth(int width) { m_width = width; m_format.clear(); } int GetPrecision() const { return m_precision; } void SetPrecision(int precision) { m_precision = precision; m_format.clear(); } virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // parameters string format is "width[,precision]" virtual void SetParameters(const wxString& params); virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); bool Copy(const wxSheetCellFloatRendererRefData& other); DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellFloatRendererRefData, wxSheetCellRendererRefData) protected: int m_width, m_precision; wxString m_format; }; // ---------------------------------------------------------------------------- // wxSheetCellBitmapRendererRefData // ---------------------------------------------------------------------------- enum wxSHEET_BMPREN_Type { // The position of the bitmap relative to the text (if any) wxSHEET_BMPREN_BMPLEFT = 0x000000, wxSHEET_BMPREN_BMPRIGHT = 0x010000, wxSHEET_BMPREN_BMPABOVE = 0x020000, wxSHEET_BMPREN_BMPBELOW = 0x040000 }; class WXDLLIMPEXP_SHEET wxSheetCellBitmapRendererRefData : public wxSheetCellStringRendererRefData { public: wxSheetCellBitmapRendererRefData(const wxBitmap& bitmap = wxNullBitmap, int align = 0) : m_bitmap(bitmap), m_align(align) {} // draw a the bitmap virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // return the bitmap size virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords); // Get/Set the bitmap to draw wxBitmap GetBitmap() const { return m_bitmap; } void SetBitmap(const wxBitmap& bitmap) { m_bitmap = bitmap; } // Get/Set the bitmap alignment, wxALIGN_XXX | wxSHEET_BMPREN_Type | wxGROW // The wxSHEET_BMPREN_Type determines the relative positions of bmp and text // The wxALIGN_XXX sets the alignment of the bitmap in it's area of the cell // wxGROW will expand or shrink bitmap instead of clipping it // The cell attribute's alignment sets the alignment of the text in it's area of the cell int GetAlignment() const { return m_align; } void SetAlignment(int align) { m_align = align; } bool Copy(const wxSheetCellBitmapRendererRefData& other) { SetBitmap(other.GetBitmap()); return wxSheetCellStringRendererRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellBitmapRendererRefData, wxSheetCellRendererRefData) wxBitmap m_bitmap; int m_align; }; // ---------------------------------------------------------------------------- // wxSheetCellBoolRendererRefData // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellBoolRendererRefData : public wxSheetCellRendererRefData { public: wxSheetCellBoolRendererRefData() {} // draw a check mark or nothing virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // return the checkmark size virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords); bool Copy(const wxSheetCellBoolRendererRefData& other) { return wxSheetCellRendererRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellBoolRendererRefData, wxSheetCellRendererRefData) protected: static wxSize ms_sizeCheckMark; }; // ---------------------------------------------------------------------------- // wxSheetCellDateTimeRendererRefData // ---------------------------------------------------------------------------- #if wxUSE_DATETIME // the default renderer for the cells containing Time and dates.. class WXDLLIMPEXP_SHEET wxSheetCellDateTimeRendererRefData : public wxSheetCellStringRendererRefData { public: wxSheetCellDateTimeRendererRefData(wxString outFormat = wxDefaultDateTimeFormat, //_T("%c"), wxString inFormat = wxDefaultDateTimeFormat) : m_outFormat(outFormat), m_inFormat(inFormat), m_dateTime(wxDefaultDateTime), m_tz(wxDateTime::Local) {} virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // parameters string format is "width[,precision]" virtual void SetParameters(const wxString& params); wxString GetInFormat() const { return m_inFormat; } wxString GetOutFormat() const { return m_outFormat; } void SetInFormat(const wxString& inFormat) { m_inFormat = inFormat; } void SetOutFormat(const wxString& outFormat) { m_outFormat = outFormat; } virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); bool Copy(const wxSheetCellDateTimeRendererRefData& other); DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellDateTimeRendererRefData, wxSheetCellRendererRefData) protected: wxString m_outFormat; wxString m_inFormat; wxDateTime m_dateTime; wxDateTime::TimeZone m_tz; }; #endif // wxUSE_DATETIME // ---------------------------------------------------------------------------- // wxSheetCellEnumRendererRefData - renderers Time and dates.. // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCellEnumRendererRefData : public wxSheetCellStringRendererRefData { public: wxSheetCellEnumRendererRefData( const wxString& choices = wxEmptyString ); virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); // parameters string format is "item1[,item2[...,itemN]]" virtual void SetParameters(const wxString& params); wxArrayString& GetChoices() { return m_choices; } virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); bool Copy(const wxSheetCellEnumRendererRefData& other); DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellEnumRendererRefData, wxSheetCellRendererRefData) protected: wxArrayString m_choices; }; // ---------------------------------------------------------------------------- // wxSheetCellRolColLabelRendererRefData // ---------------------------------------------------------------------------- // the default renderer for the cells containing string data class WXDLLIMPEXP_SHEET wxSheetCellRolColLabelRendererRefData : public wxSheetCellStringRendererRefData { public: wxSheetCellRolColLabelRendererRefData() {} virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected); bool Copy(const wxSheetCellRolColLabelRendererRefData& other) { return wxSheetCellStringRendererRefData::Copy(other); } DECLARE_SHEETOBJREFDATA_COPY_CLASS( wxSheetCellRolColLabelRendererRefData, wxSheetCellRendererRefData) }; #endif //__WX_SHEETREN_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/sheetsel.h0000644000076500007650000005240011350032206020166 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetsel.h // Purpose: wxSheetSelection // Author: John Labenski // Modified by: // Created: 20/02/2000 // RCS-ID: $$ // Copyright: (c) John Labenski, Stefan Neis // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_SHEETSEL_H__ #define __WX_SHEETSEL_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "sheetsel.h" #endif #include "wx/sheet/sheetdef.h" // ---------------------------------------------------------------------------- // wxSheetCoords: location of a cell in the grid // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetCoords { public: wxSheetCoords() : m_row(0), m_col(0) {} wxSheetCoords( int row, int col ) : m_row(row), m_col(col) {} // default copy ctor is ok int GetRow() const { return m_row; } int GetCol() const { return m_col; } void SetRow( int row ) { m_row = row; } void SetCol( int col ) { m_col = col; } void Set( int row, int col ) { m_row = row; m_col = col; } void ShiftRow( int row ) { m_row += row; } void ShiftCol( int col ) { m_col += col; } void Shift( int rows, int cols ) { m_row += rows; m_col += cols; } void SwapRowCol() { int tmp = m_row; m_row = m_col; m_col = tmp; } // returns coords shifted by the # of rows and cols wxSheetCoords GetShifted( int rows, int cols ) const { return wxSheetCoords(m_row+rows, m_col+cols); } // return coords with row and col swapped wxSheetCoords GetSwapped() const { return wxSheetCoords(m_col, m_row); } // Get the type of coords as enum for use in a switch statement wxSheetCell_Type GetCellCoordsType() const; // helper functions to determine what type of cell it is, not check validity bool IsGridCell() const { return (m_row >= 0) && (m_col >= 0); } bool IsLabelCell() const { return (m_row >= -1) && (m_col >= -1) && ((m_row == -1) || (m_col == -1)); } bool IsRowLabelCell() const { return (m_row >= 0) && (m_col == -1); } bool IsColLabelCell() const { return (m_row == -1) && (m_col >= 0); } bool IsCornerLabelCell() const { return (m_row == -1) && (m_col == -1); } // Convert this sheet coords to a row/col/corner label coords // eg. for row labels : sheetCell(-1, 5) -> rowLabelCell(0, 5) wxSheetCoords SheetToRowLabel() const { return wxSheetCoords( m_row, -1-m_col); } wxSheetCoords SheetToColLabel() const { return wxSheetCoords(-1-m_row, m_col); } wxSheetCoords SheetToCornerLabel() const { return wxSheetCoords(-1-m_row, -1-m_col); } wxSheetCoords GetCellCoords(wxSheetCell_Type type) const; wxSheetCoords& SetCellCoords(wxSheetCell_Type type); // Shift the cell if greater than row/col by numRows/numCols. // if this row/col is < the update row/col do nothing, return false // if this row/col is >= the update row/col + labs(num) then shift by num // if this row/col is >= the update row/col && < row/col + labs(num) // if num > 0 then shift it // if num < 0 it should be deleted, but shift it to row/col - 1 bool UpdateRows( size_t row, int numRows ); bool UpdateCols( size_t col, int numCols ); // operators wxSheetCoords& operator=(const wxSheetCoords& other) { m_row = other.m_row; m_col = other.m_col; return *this; } // arithmetic operations (component wise) wxSheetCoords operator+(const wxSheetCoords& c) const { return wxSheetCoords(m_row + c.m_row, m_col + c.m_col); } wxSheetCoords operator-(const wxSheetCoords& c) const { return wxSheetCoords(m_row - c.m_row, m_col - c.m_col); } wxSheetCoords& operator+=(const wxSheetCoords& c) { m_row += c.m_row; m_col += c.m_col; return *this; } wxSheetCoords& operator-=(const wxSheetCoords& c) { m_row -= c.m_row; m_col -= c.m_col; return *this; } bool operator == (const wxSheetCoords& other) const { return (m_row == other.m_row) && (m_col == other.m_col); } bool operator != (const wxSheetCoords& other) const { return !(*this == other); } // > and < operators use row for first comparison then col bool operator < (const wxSheetCoords& other) const { return (m_row < other.m_row) || ((m_row == other.m_row) && (m_col < other.m_col)); } bool operator <= (const wxSheetCoords& other) const { return (*this < other) || (*this == other); } bool operator > (const wxSheetCoords& other) const { return !(*this <= other); } bool operator >= (const wxSheetCoords& other) const { return !(*this < other); } int m_row; int m_col; }; // wxArraySheetCoords - a wxObjectArray of wxSheetCoords WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetCoords, wxArraySheetCoords, class WXDLLIMPEXP_SHEET); // ---------------------------------------------------------------------------- // wxSheetBlock: a rectangular block of cells // ---------------------------------------------------------------------------- enum wxSheetBlockExtra_Type { wxSHEET_BLOCK_NONE = 0, wxSHEET_BLOCK_TOP = 0x0001, wxSHEET_BLOCK_BOTTOM = 0x0002, wxSHEET_BLOCK_LEFT = 0x0004, wxSHEET_BLOCK_RIGHT = 0x0008, wxSHEET_BLOCK_ALL = 0x0010 }; class WXDLLIMPEXP_SHEET wxSheetBlock { public: wxSheetBlock() : m_row(0), m_col(0), m_height(0), m_width(0) {} wxSheetBlock(int row, int col, int height, int width) : m_row(row), m_col(col), m_height(height), m_width(width) {} // make a block from two corner coords, block will be upright wxSheetBlock( const wxSheetCoords& coords1, const wxSheetCoords& coords2, bool make_upright = true ); wxSheetBlock( const wxSheetCoords& tl, int height, int width ) : m_row(tl.m_row), m_col(tl.m_col), m_height(height), m_width(width) {} // Get the coord values of the block int GetLeft() const { return m_col; } int GetRight() const { return m_col + m_width - 1; } int GetTop() const { return m_row; } int GetBottom() const { return m_row + m_height - 1; } int GetWidth() const { return m_width; } int GetHeight() const { return m_height; } wxSheetCoords GetLeftTop() const { return wxSheetCoords(m_row, m_col); } wxSheetCoords GetLeftBottom() const { return wxSheetCoords(GetBottom(), m_col); } wxSheetCoords GetRightTop() const { return wxSheetCoords(m_row, GetRight()); } wxSheetCoords GetRightBottom() const { return wxSheetCoords(GetBottom(), GetRight()); } wxSheetCoords GetSize() const { return wxSheetCoords(m_height, m_width); } // get an array of coords going left to right, top to bottom wxArraySheetCoords GetArrayCoords() const; // Set the coord values of the block // set the edges, the rest of the block stays in the same place void SetLeft( int left ) { m_width += m_col - left; m_col = left; } void SetTop( int top ) { m_height += m_row - top; m_row = top; } void SetRight( int right ) { m_width = right - m_col + 1; } void SetBottom( int bottom ) { m_height = bottom - m_row + 1; } void SetWidth( int width ) { m_width = width; } void SetHeight( int height ) { m_height = height; } void SetLeftTop(const wxSheetCoords& lt) { SetTop(lt.m_row); SetLeft(lt.m_col); } void SetLeftBottom(const wxSheetCoords& lb) { SetBottom(lb.m_row); SetLeft(lb.m_col); } void SetRightTop(const wxSheetCoords& rt) { SetTop(rt.m_row); SetRight(rt.m_col); } void SetRightBottom(const wxSheetCoords& rb) { SetBottom(rb.m_row); SetRight(rb.m_col); } // Set the coords keeping the rest of the block the same void SetLeftCoord( int left ) { m_col = left; } void SetTopCoord( int top ) { m_row = top; } void SetRightCoord( int right ) { m_col = right - m_width + 1; } void SetBottomCoord( int bottom ) { m_row = bottom - m_height + 1; } void SetLeftTopCoords(const wxSheetCoords& lt) { SetTopCoord(lt.m_row); SetLeftCoord(lt.m_col); } void SetLeftBottomCoords(const wxSheetCoords& lb) { SetBottomCoord(lb.m_row); SetLeftCoord(lb.m_col); } void SetRightTopCoords(const wxSheetCoords& rt) { SetTopCoord(rt.m_row); SetRightCoord(rt.m_col); } void SetRightBottomCoords(const wxSheetCoords& rb) { SetBottomCoord(rb.m_row); SetRightCoord(rb.m_col); } void Set( int row, int col, int height, int width ) { m_row = row; m_col = col; m_height = height; m_width = width; } void SetCoords( int top, int left, int bottom, int right ) { m_row=top; m_col=left; m_height=bottom-top+1; m_width=right-left+1; } void SetSize(const wxSheetCoords& size) { m_height = size.m_row; m_width = size.m_col; } // Get a block of this that is upright wxSheetBlock GetAligned() const; bool IsEmpty() const { return (m_width < 1) || (m_height < 1); } bool IsOneCell() const { return (m_width == 1) && (m_height == 1); } bool Contains( int row, int col ) const { return (row >= m_row) && (col >= m_col) && (row <= GetBottom()) && (col <= GetRight()); } bool Contains( const wxSheetCoords &coord ) const { return Contains(coord.m_row, coord.m_col); } bool Contains( const wxSheetBlock &b ) const { return !IsEmpty() && !b.IsEmpty() && (m_row <= b.m_row) && (m_col <= b.m_col) && (b.GetBottom() <= GetBottom()) && (b.GetRight() <= GetRight()); } // do these two blocks intersect (overlap) each other bool Intersects( const wxSheetBlock &b ) const { return !Intersect(b).IsEmpty(); } //!IsEmpty() && !b.IsEmpty() && //(wxMax(m_col, b.m_col) <= wxMin(GetRight(), b.GetRight())) && //(wxMax(m_row, b.m_row) <= wxMin(GetBottom(), b.GetBottom())); } // returns a block that is an intersection of these two blocks wxSheetBlock Intersect( const wxSheetBlock &other ) const; // union these two blocks wxSheetBlock Union( const wxSheetBlock &other ) const; // expands the union of the two, if one block is empty, return other wxSheetBlock ExpandUnion( const wxSheetBlock &other ) const; // Unlike Intersects this also includes just touching the other block bool Touches(const wxSheetBlock &block) const { return !IsEmpty() && !block.IsEmpty() && block.Intersects(wxSheetBlock(m_row-1, m_col-1, m_height+2, m_width+2)); } // returns a mix of enum wxSheetBlockExtra_Type of what sides of the two // blocks are matched int SideMatches(const wxSheetBlock& block) const { return (m_row == block.m_row ? wxSHEET_BLOCK_TOP : 0) | (m_col == block.m_col ? wxSHEET_BLOCK_LEFT : 0) | (GetBottom() == block.GetBottom() ? wxSHEET_BLOCK_BOTTOM : 0) | (GetRight() == block.GetRight() ? wxSHEET_BLOCK_RIGHT : 0); } // Try to combine these blocks, they must touch and fit to make a single larger block // this block is expanded if possible, returns success bool Combine(const wxSheetBlock &block); // test combining the input block with this one, returning the // remainder of block in top, bottom, left, right - each may be IsEmpty() // returns enum wxSheetBlockExtra_Type Or'ed together specifying which // blocks have been filled or all of the block may be combined // returns false if blocks don't touch or this block already contains block // |---------------------------| // | top | // |---------------------------| // | left |block| right | // |---------------------------| // | bottom | // |---------------------------| int Combine( const wxSheetBlock &block, wxSheetBlock &top, wxSheetBlock &bottom, wxSheetBlock &left, wxSheetBlock &right ) const; // test removal of a portion or all of this contained in block returning the // remainder of this in top, bottom, left, right - each may be IsEmpty() // returns false if nothing to delete, this cell is not changed int Delete( const wxSheetBlock &block, wxSheetBlock &top, wxSheetBlock &bottom, wxSheetBlock &left, wxSheetBlock &right ) const; // shift the block if greater than row/col by numRows/numCols or empty it // if it's inside the deletion bool UpdateRows( size_t row, int numRows ); bool UpdateCols( size_t col, int numCols ); // operators bool operator == (const wxSheetBlock& b) const { return (m_row == b.m_row) && (m_height == b.m_height) && (m_col == b.m_col) && (m_width == b.m_width); } bool operator != (const wxSheetBlock& b) const { return !(*this == b); } // returns -1 if this block is more to the top left, 0 is equal, 1 if lower and to right int CmpTopLeft(const wxSheetBlock& b) const; // returns -1 if this block is more to the right then bottom, 0 is equal, 1 if to the left and higher int CmpRightBottom(const wxSheetBlock& b) const; // goes top left to bottom right and then by height and width (allows sorting) bool operator < (const wxSheetBlock& b) const { if (m_row < b.m_row) return true; else if (m_row > b.m_row) return false; if (m_col < b.m_col) return true; else if (m_col > b.m_col) return false; if (m_height < b.m_height) return true; else if (m_height > b.m_height) return false; if (m_width < b.m_width) return true; //else if (m_width > b.m_width) return false; return false; } bool operator <= (const wxSheetBlock& other) const { return (*this == other) || (*this < other); } bool operator > (const wxSheetBlock& other) const { return !(*this <= other); } bool operator >= (const wxSheetBlock& other) const { return !(*this < other); } protected: int m_row, m_col, m_height, m_width; }; // For comparisons... WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCoords) wxNullSheetCoords; // (-2, -2) WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCoords) wxGridCellSheetCoords; // ( 0, 0) WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCoords) wxRowLabelSheetCoords; // ( 0, -1) WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCoords) wxColLabelSheetCoords; // (-1, 0) WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCoords) wxCornerLabelSheetCoords; // (-1, -1) WXDLLIMPEXP_DATA_SHEET(extern const wxSheetBlock) wxNullSheetBlock; // (0, 0, 0, 0) // wxArraySheetBlock - a wxObjectArray of wxSheetBlocks WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetBlock, wxArraySheetBlock, class WXDLLIMPEXP_SHEET); // ---------------------------------------------------------------------------- // wxSheetSelection // ---------------------------------------------------------------------------- enum wxSheetSelection_Type { wxSHEET_SELECTION_NONE = 0, // allow multiple selections to occur, this will cause the // wxSheetSelection::Index to return the first occurance of possible many wxSHEET_SELECTION_MULTIPLE_SEL = 0x0001 }; class WXDLLIMPEXP_SHEET wxSheetSelection { public: wxSheetSelection( int options = wxSHEET_SELECTION_NONE ); wxSheetSelection( const wxSheetSelection& other ) { Copy( other ); } wxSheetSelection( const wxSheetBlock& block, int options = wxSHEET_SELECTION_NONE ); // Make a full copy of the source void Copy(const wxSheetSelection &source); int GetOptions() const { return m_options; } void SetOptions(int options) { m_options = options; } bool HasSelection() const { return GetCount() != 0; } int GetCount() const { return m_blocks.GetCount(); } bool IsMinimzed() const { return m_minimized; } bool Clear() { if (GetCount() != 0) { m_blocks.Clear(); return true; } return false; } bool Empty() { if (GetCount() != 0) { m_blocks.Empty(); return true; } return false; } const wxArraySheetBlock& GetBlockArray() const { return m_blocks; } const wxSheetBlock& GetBlock( size_t index ) const; const wxSheetBlock& Item( size_t index ) const { return GetBlock(index); } // Get a block that bounds the selection const wxSheetBlock& GetBoundingBlock() const { return m_bounds; } // Set the outer bounds of the selection, trimming it down as necessary void SetBoundingBlock(const wxSheetBlock& block); // do any of the blocks contain the elements bool Contains( int row, int col ) const { return Index(row,col) != wxNOT_FOUND; } bool Contains( const wxSheetCoords &c ) const { return Contains(c.GetRow(), c.GetCol()); } bool Contains( const wxSheetBlock &b ) const; // Get the index of a block that fully contains element or wxNOT_FOUND int Index( int row, int col ) const; int Index( const wxSheetCoords &c ) const { return Index(c.GetRow(), c.GetCol()); } int Index( const wxSheetBlock &b ) const; // Get the first index of the block that intersects input block or wxNOT_FOUND int IndexIntersects( const wxSheetBlock &b ) const; // Add the block to the selection, returns false if nothing was done // use combineNow=false to make quick additions, when done call Minimize() // addedBlocks (if !NULL) will be filled with the actual changed selections // by removing the previous selections from the input block bool SelectBlock( const wxSheetBlock &block, bool combineNow = true, wxArraySheetBlock *addedBlocks = NULL ); // Remove the block to the selection, return false if nothing was done // use combineNow=false to make quick additions, when done call Minimize() // deletedBlocks (if !NULL) contains the input block, FIXME // [it should contain only the parts of the input block that were // deleted in the selection, but the speed would greatly suffer, // unlike SelectBlock which uses an array in the selection process] bool DeselectBlock( const wxSheetBlock &block, bool combineNow = true, wxArraySheetBlock *deletedBlocks = NULL ); // Update the number of rows/cols. In numRows/Cols > 0 insert them else // remove them. bool UpdateRows( size_t row, int numRows ); bool UpdateCols( size_t col, int numCols ); // Operators inline wxSheetBlock operator[](size_t index) const { return GetBlock(index); } wxSheetSelection& operator = (const wxSheetSelection& other) { Copy(other); return *this; } // implementation // Find where to insert this block int FindInsertIndex(const wxSheetBlock& block) const; // Find the index in the array that starts at this row int FindTopRow(int row) const; // Combine the blocks if possible and Sort() them, returns if any were combined // only need to call this if you've called (De)SelectBlock(block, false) bool Minimize(); // Calls DoDoMinimize on array until it returns false bool DoMinimize( wxArraySheetBlock &blocks ) const; // DoMinimize calls this internally so that it doesn't recurse // generic routine using if (b1.Combine(b2)) remove b2 to cleanup array bool DoDoMinimize( wxArraySheetBlock &blocks ) const; protected: int InsertBlock(const wxSheetBlock& block); void CalculateBounds(); wxArraySheetBlock m_blocks; wxSheetBlock m_bounds; bool m_minimized; int m_options; }; // ---------------------------------------------------------------------------- // wxSheetSelectionIterator - iterates through a wxSheetSelection cell by cell // ---------------------------------------------------------------------------- enum wxSheetSelectionIter_Type { wxSSI_FORWARD, // iterate left to right by cols and then down by rows wxSSI_REVERSE // iterate bottom to top by rows and then left by cols }; enum wxSheetSelectionIterGet_Type { wxSHEET_SELECTIONITER_GET_END = 0, wxSHEET_SELECTIONITER_GET_LEFTTOP = 0x0001, wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM = 0x0002, wxSHEET_SELECTIONITER_GET_NEXTROW = 0x0004, wxSHEET_SELECTIONITER_GET_NEXTCOL = 0x0008 }; class WXDLLIMPEXP_SHEET wxSheetSelectionIterator { public : wxSheetSelectionIterator( const wxSheetSelection &sel, wxSheetSelectionIter_Type type = wxSSI_FORWARD ); wxSheetSelectionIterator( const wxArraySheetBlock &blocks, wxSheetSelectionIter_Type type = wxSSI_FORWARD ); // resets the iterating to start at the beginning void Reset(wxSheetSelectionIter_Type type); // What direction are we iterating in wxSheetSelectionIter_Type GetIterType() const { return (wxSheetSelectionIter_Type)m_type; } // Get next cell in the selection, returns wxSheetSelectionIterGet_Type, 0 at end wxSheetSelectionIterGet_Type GetNext(wxSheetCoords &coords); // checks if this row and col are in this selection bool IsInSelection(const wxSheetCoords &c) const { return IsInSelection(c.m_row, c.m_col); } bool IsInSelection( int row, int col ) const; protected : wxSheetSelectionIterGet_Type GetNextForward(wxSheetCoords &coords); wxSheetSelectionIterGet_Type GetNextReverse(wxSheetCoords &coords); int m_block_index; int m_type; wxSheetCoords m_coords; wxArraySheetBlock m_blocks; }; #endif // __WXSHEETSEL_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/sheetspt.h0000644000076500007650000003175011350032206020216 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetspt.h // Purpose: wxSheetSplitter and related classes // Author: John Labenski // Modified by: // Created: 4/1/2004 // RCS-ID: $Id$ // Copyright: (c) John Labenski // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_SHEETSPT_H__ #define __WX_SHEETSPT_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "sheetspt.h" #endif #include "wx/sheet/sheet.h" #include "wx/splitter.h" // ---------------------------------------------------------------------------- // wxSheetSplitter - a 4 way splitter class for the wxSheet // // To use the wxSheetSplitter, create an instance and a single child wxSheet. // Attach the wxSheet to the splitter using Initialize() and the splitter // will create and ref additional sheets when the user splits the sheet. When // the user unsplits the added sheets are destroyed. The TopLeft sheet // is always the sheet that you Initialized it with, even if that is the sheet // that is hidden by the user. The scrollbars are set to be shown as necessary // and splitting is not allowed when the scrollbars are not shown. // // There are a few ways you can provide the new wxSheets that are required // when splitting. You'll need to do this if your sheet is derived and // the logic has been changed otherwise the splitter just uses a "new wxSheet." // 1) Subclass wxSheetSplitter and override the virtual function // wxSheet* wxSheetSplitter::CreateSheet(wxWindowID id) to return your own. // 2) Intercept the wxEVT_SHEET_SPLIT_CREATE_SHEET sent from the wxSheetSplitter // and replace the event.Get/SetEventObject with a *new* wxSheet with the // wxSheetSplitter (the original event.GetEventObject) as the parent. // Note that event.GetExtraLong is the preferred id, probably wxID_ANY. // 3) In your subclassed wxSheet override the virtual wxSheet* wxSheet::Clone // function to return a new instance of your wxSheet. // ---------------------------------------------------------------------------- enum wxSheetSplitMode_Type { wxSHEET_SPLIT_NONE = 0, wxSHEET_SPLIT_VERTICAL, wxSHEET_SPLIT_HORIZONTAL }; // These window styles are used from wxSplitterWindow //#define wxSP_NOBORDER 0x0000 //#define wxSP_NOSASH 0x0010 //#define wxSP_PERMIT_UNSPLIT 0x0040 //#define wxSP_LIVE_UPDATE 0x0080 //#define wxSP_3DSASH 0x0100 //#define wxSP_3DBORDER 0x0200 //#define wxSP_NO_XP_THEME 0x0400 //#define wxSP_BORDER wxSP_3DBORDER //#define wxSP_3D (wxSP_3DBORDER | wxSP_3DSASH) class WXDLLIMPEXP_SHEET wxSheetSplitter : public wxWindow { public: wxSheetSplitter() : wxWindow() { Init(); } wxSheetSplitter(wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxSP_3D|wxSP_3DBORDER, const wxString& name = wxT("wxSheetSplitter")) { Init(); Create(parent, id, pos, size, style, name); } bool Create(wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxSP_3D|wxSP_3DBORDER, const wxString& name = wxT("wxSheetSplitter")); virtual ~wxSheetSplitter(); virtual bool Destroy(); // Initialize the splitter with one window, the splitter must be sheet's parent void Initialize(wxSheet* sheet); // Will the splitting buttons be shown for vert/horiz splitting // you can still call SplitVertically/Horizontally however bool GetEnableSplitVertically() const { return m_enable_split_vert; } bool GetEnableSplitHorizontally() const { return m_enable_split_horiz; } void EnableSplitVertically(bool can_split) { m_enable_split_vert = can_split; } void EnableSplitHorizontally(bool can_split) { m_enable_split_horiz = can_split; } bool IsSplitHorizontally() const { return m_tlSheet && m_trSheet; } bool IsSplitVertically() const { return m_tlSheet && m_blSheet; } // Split the windows either vertically or horizontally virtual void SplitVertically(int y_pos, bool sendEvt = false); virtual void SplitHorizontally(int x_pos, bool sendEvt = false); // Unsplit the windows, note that the bottom/right window is the one // that's actually removed, but the origin of the top/left will be set to // that if !remove_bottom/right so it'll look like the top/left was removed virtual void UnsplitVertically(bool remove_bottom = true, bool sendEvt = false); virtual void UnsplitHorizontally(bool remove_right = true, bool sendEvt = false); // Get the position of the sash, 0 if not split int GetHorizontalSplitPosition() const { return m_splitPos.x; } int GetVerticalSplitPosition() const { return m_splitPos.y; } // Split, unsplit, and set the sash position // If pos <= 0 unsplit and set the origin of the left/top to val of right/bottom // If pos >= GetClientSize().GetWidth/Height() unsplit // If unsplit and pos in valid range then split // If split then move the sash to the position virtual void SetVerticalSplitPosition(int y_pos, bool sendEvt = false); virtual void SetHorizontalSplitPosition(int x_pos, bool sendEvt = false); // The top left window is the window you Initialized this with wxSheet* GetTopLeftSheet() const { return m_tlSheet; } // The top right is valid when split vertically wxSheet* GetTopRightSheet() const { return m_trSheet; } // the bottom left sheet is valid when split horizontally wxSheet* GetBottomLeftSheet() const { return m_blSheet; } // The bottom right sheet is valid when split vertically and horizontally wxSheet* GetBottomRightSheet() const { return m_brSheet; } // Get the width of the sash int GetSashSize() const; // Get the size of the border around the window int GetBorderSize() const; // For the given sash position adjust it so that it's valid for the // window given the min size and if it can unsplit. int GetAdjustedVerticalSashPosition(int pos) const; int GetAdjustedHorizontalSashPosition(int pos) const; // implementation void OnViewChanged(wxSheetEvent& event); void OnSplit(wxSheetSplitterEvent& event); void OnMouse( wxMouseEvent& event ); void OnPaint( wxPaintEvent& event ); void DrawSash(wxDC &dc); void DrawSashTracker(int x, int y); // returns wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL int SashHitTest(const wxPoint& pt) const; // Set the cursor to use wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL void SetMouseCursor(int sheet_split_mode); // setup the configuration of the sheets (hide/show labels/scrollbars) void ConfigureWindows(); // Position the windows in this window void LayoutWindows(); // Send the event and returns true if it wasn't vetoed bool SendEvent( wxEventType type, bool vert_split ); bool DoSendEvent( wxSheetSplitterEvent& event ); protected: // Override this to return a derived wxSheet of your own making // if you don't want to use the wxEVT_SHEET_SPLIT_CREATE_SHEET event virtual wxSheet* CreateSheet(wxWindowID id = wxID_ANY); // Overriding these functions are optional, they call CreateSheet to get a // sheet to use and then properly initialize by hiding the labels and // scrollbars as necessary. virtual wxSheet* CreateTopRightSheet(wxWindowID id = wxID_ANY); virtual wxSheet* CreateBottomLeftSheet(wxWindowID id = wxID_ANY); virtual wxSheet* CreateBottomRightSheet(wxWindowID id = wxID_ANY); void OnSize( wxSizeEvent& event ); wxSheet *m_tlSheet; wxSheet *m_trSheet; wxSheet *m_blSheet; wxSheet *m_brSheet; wxPoint m_mousePos; // mouse pos for sash tracker wxPoint m_splitPos; // current position of the splitter int m_splitMode; // currently active sash wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL int m_splitCursor; // currently active cursor wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL //int m_sash_width; FIXME maybe be backwards compatible to 2.4? bool m_enable_split_vert; bool m_enable_split_horiz; wxSize m_minSize; private: void Init(); WX_DECLARE_CONTROL_CONTAINER(); DECLARE_DYNAMIC_CLASS(wxSheetSplitter) DECLARE_EVENT_TABLE() DECLARE_NO_COPY_CLASS(wxSheetSplitter) }; // ---------------------------------------------------------------------------- // wxSheetSplitterEvent // ---------------------------------------------------------------------------- class WXDLLEXPORT wxSheetSplitterEvent : public wxNotifyEvent { public: wxSheetSplitterEvent(int id = 0, wxEventType type = wxEVT_NULL) : wxNotifyEvent(type, id), m_sash_pos(0), m_vert_split(false) {} wxSheetSplitterEvent(const wxSheetSplitterEvent& event) : wxNotifyEvent(event), m_sash_pos(event.m_sash_pos), m_vert_split(event.m_vert_split) { } // Get the current sash position, see also IsVerticalSplit for which sash. int GetSashPosition() const { return m_sash_pos; } // Set the sash position, during a wxEVT_SHEET_SPLIT_CHANGING you may // replace the current value with a different one to force a new position. void SetSashPosition(int pos) { m_sash_pos = pos; } // Does this event pertain to a vertical or horizontal splitting bool IsVerticalSplit() const { return m_vert_split; } // The sheet is valid only for the wxEVT_SHEET_SPLIT_BEGIN event type wxSheet* GetSheet() const { return wxDynamicCast(GetEventObject(), wxSheet); } // The sheet splitter is valid for the rest of the splitter events wxSheetSplitter* GetSheetSplitter() const { return wxDynamicCast(GetEventObject(), wxSheetSplitter); } // implementation virtual wxEvent *Clone() const { return new wxSheetSplitterEvent(*this); } int m_sash_pos; bool m_vert_split; }; BEGIN_DECLARE_EVENT_TYPES() // The splitter buttons in the sheet have been clicked to begin splitting // this event comes from the wxSheet itself when the begins to drag the // mouse on the splitter boxes. DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_BEGIN, 1800) // The splitter sash position is changing DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_CHANGING, 1801) // The splitter sash position has changed DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_CHANGED, 1802) // The splitter sash position has been double clicked on, will unsplit DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_DOUBLECLICKED, 1803) // The splitter has been unsplit DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_UNSPLIT, 1804) // The splitter is splitting and is about to create a new wxSheet. // You can provide your own wxSheet derived class by calling // event.SetEventObject(new MySheet(event.GetSheetSplitter(), ...)) // where the parent of the sheet you provide is the wxSheetSplitter // which is the original event.GetEventObject. The sender wxSheetSplitter // takes ownership of the new wxSheet and destroys it when unsplit. // Please see the function wxSheetSplitter::CreateSheet for more info. // You cannot veto this event since it occurs too late in the chain of splitting, // use veto on wxEVT_SHEET_SPLIT_BEGIN to stop it in the first place. DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_CREATE_SHEET, 1805) END_DECLARE_EVENT_TYPES() typedef void (wxEvtHandler::*wxSheetSplitterEventFunction)(wxSheetSplitterEvent&); #define EVT_SHEET_SPLIT_BEGIN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_BEGIN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), #define EVT_SHEET_SPLIT_CHANGING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_CHANGING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), #define EVT_SHEET_SPLIT_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), #define EVT_SHEET_SPLIT_DOUBLECLICKED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_DOUBLECLICKED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), #define EVT_SHEET_SPLIT_UNSPLIT(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_UNSPLIT, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), #define EVT_SHEET_SPLIT_CREATE_SHEET(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_CREATE_SHEET, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), #endif // __WX_SHEETSPT_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/sheettbl.h0000644000076500007650000005464411350032206020200 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheettbl.h // Purpose: wxSheet and related classes // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) // Modified by: John Labenski // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski, Michael Bedward // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_SHEETTBL_H__ #define __WX_SHEETTBL_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "sheettbl.h" #endif #include "wx/sheet/sheetdef.h" // =========================================================================== // wxSheetData - data containers and providers for the table // =========================================================================== // ---------------------------------------------------------------------------- // wxArrayStringUpdatePos - an UpdatePos function for wxArrayString // // Update the position of the values in the array, by inserting wxEmptyStrings // or deleting them. If no_error then don't error out for invalid values. // no_error may be useful for arrays that are filled only to the last set value // and not to the full extent, therefore an insert beyond the end of this // array should simply be ignored. // ---------------------------------------------------------------------------- bool wxArrayStringUpdatePos(wxArrayString& arr, size_t pos, int num, bool no_error = false); // ---------------------------------------------------------------------------- // wxSheetStringArray (wxGridStringArray) a 2d array of wxStrings // ---------------------------------------------------------------------------- #if wxUSE_GRID #include "wx/grid.h" // get wxGridStringArray from grid typedef wxGridStringArray wxSheetStringArray; #else // !wxUSE_GRID WX_DECLARE_OBJARRAY_WITH_DECL(wxArrayString, wxSheetStringArray, class WXDLLIMPEXP_SHEET); #endif // wxUSE_GRID // ---------------------------------------------------------------------------- // wxSheetCellValueProviderBase - base class for a data container for wxSheet cells // this class must be subclassed - see wxSheetCellData(Sparse)String // ---------------------------------------------------------------------------- // wxSheetCellValueProvider_Type - values for the wxSheetCellValueProvider options enum wxSheetValueProvider_Type { wxSHEET_ValueProviderColPref = 0x0001 // optimize for more cols than rows }; class WXDLLIMPEXP_SHEET wxSheetValueProviderBase : public wxObject { public: wxSheetValueProviderBase(size_t numRows = 0u, size_t numCols = 0u, int options = 0) :m_numRows(numRows), m_numCols(numCols), m_options(options) {} virtual ~wxSheetValueProviderBase() {} // Get the size of the data structure (override this as necessary) // note: these are called often so you may wish to set member vars as necessary // all base class calls that require the number of rows/cols use these functions // if you change the number you must alert the sheet - see wxSheetTable::UpdateSheetXXX virtual int GetNumberRows() const { return m_numRows; } virtual int GetNumberCols() const { return m_numCols; } bool ContainsCell(const wxSheetCoords& coords) const { return (coords.m_row >= 0) && (coords.m_col >= 0) && (coords.m_row < GetNumberRows()) && (coords.m_col < GetNumberCols()); } // Get/SetValue for a single cell virtual wxString GetValue( const wxSheetCoords& coords ) const = 0; virtual void SetValue( const wxSheetCoords& coords, const wxString& value ) = 0; // Is this cell empty - defaults ueries if the string is empty virtual bool HasValue( const wxSheetCoords& coords ) const { return !GetValue(coords).IsEmpty(); } // Get the first cell to the left that is not empty, or just return col - 1 // this is used for optimizing redrawing virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const { return coords.m_col - 1; } // Clear all values to be `empty` virtual void ClearValues() {} // Clear all values and set the number of rows/cols to 0 // default implementation uses UpdateRows/Cols(0, -numRows/Cols) virtual void Clear(); // Update number of rows/cols virtual bool UpdateRows( size_t row, int numRows ) = 0; virtual bool UpdateCols( size_t col, int numCols ) = 0; // Get/Set options - usage depends on the subclassed version int GetOptions() const { return m_options; } bool HasOption(int mask) const { return (GetOptions() & mask) != 0; } virtual void SetOptions(int options) { m_options = options; } // make this an identical copy of other // the default copies using Get/SetValue and sets only if HasValue virtual void Copy(const wxSheetValueProviderBase& other); virtual wxSheetValueProviderBase& operator = (const wxSheetValueProviderBase& data) { Copy(data); return *this; } protected: int m_numRows, m_numCols; int m_options; DECLARE_ABSTRACT_CLASS(wxSheetValueProviderBase); }; // ---------------------------------------------------------------------------- // wxSheetCellStringData - a size optimized container of a 2D array of wxStrings // the arrays are filled only to the extent that they're used (Jagged 2d array) // it takes the option wxSHEET_ValueProviderColPref // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetValueProviderString : public wxSheetValueProviderBase { public: wxSheetValueProviderString(size_t numRows = 0u, size_t numCols = 0u, int options = 0); //virtual int GetNumberRows() const { return m_numRows; } //virtual int GetNumberCols() const { return m_numCols; } virtual wxString GetValue( const wxSheetCoords& coords ) const; virtual void SetValue( const wxSheetCoords& coords, const wxString& value ); //virtual bool HasValue( const wxSheetCoords& coords ) const; virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const; virtual void ClearValues() { m_data.Clear(); } virtual void Clear() { m_data.Clear(); m_numRows = m_numCols = 0; } virtual bool UpdateRows( size_t row, int numRows ); virtual bool UpdateCols( size_t col, int numCols ); //int GetOptions() const { return m_options; } //bool HasOptions(int mask) const { return (m_options & mask) != 0; } virtual void SetOptions(int options); // implementation const wxSheetStringArray& GetData() const { return m_data; } wxSheetStringArray& GetData() { return m_data; } protected: bool DoUpdateRows( size_t row, int numRows ); bool DoUpdateCols( size_t col, int numCols ); wxSheetStringArray m_data; DECLARE_ABSTRACT_CLASS(wxSheetValueProviderString); }; // ---------------------------------------------------------------------------- // wxPairArrayIntSheetString - an (int, wxString) pair array for row/col labels // and for grid cols // wxArrayPairArrayIntSheetString - an array of (int, wxString) pair arrays // wxPairArrayIntPairArraySheetString - a pair array of (int, wxPairArrayIntSheetString) // stores the strings for the sparse table // ---------------------------------------------------------------------------- DECLARE_PAIRED_INT_DATA_ARRAYS( wxString, wxArrayString, wxPairArrayIntSheetString, class WXDLLIMPEXP_SHEET) // ---------------------------------------------------------------------------- WX_DECLARE_OBJARRAY_WITH_DECL(wxPairArrayIntSheetString, wxArrayPairArrayIntSheetString, class WXDLLIMPEXP_SHEET); // ---------------------------------------------------------------------------- DECLARE_PAIRED_INT_DATA_ARRAYS( wxPairArrayIntSheetString, wxArrayPairArrayIntSheetString, wxPairArrayIntPairArraySheetString, class WXDLLIMPEXP_SHEET) // ---------------------------------------------------------------------------- // wxSheetCellStringSparseData - a sparse wxString data container class // best used when you expect it to be less than about 3/4 full or so // since it stores an int for each row and an (int, wxString) for each col // it takes the option wxSHEET_ValueProviderColPref // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetValueProviderSparseString : public wxSheetValueProviderBase { public: wxSheetValueProviderSparseString(size_t numRows = 0u, size_t numCols = 0u, int options = 0); //virtual int GetNumberRows() const { return m_numRows; } //virtual int GetNumberCols() const { return m_numCols; } virtual wxString GetValue( const wxSheetCoords& coords ) const; virtual void SetValue( const wxSheetCoords& coords, const wxString& value ); virtual bool HasValue( const wxSheetCoords& coords ) const; virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const; virtual void ClearValues() { m_data.Clear(); } virtual void Clear() { m_data.Clear(); m_numRows = m_numCols = 0; } virtual bool UpdateRows( size_t row, int numRows ); virtual bool UpdateCols( size_t col, int numCols ); virtual void SetOptions(int options); // implementation void RemoveEmpty(); // if there are no cols then might as well remove row const wxPairArrayIntPairArraySheetString& GetData() const { return m_data; } wxPairArrayIntPairArraySheetString& GetData() { return m_data; } protected: bool DoUpdateRows( size_t row, int numRows ); bool DoUpdateCols( size_t col, int numCols ); wxPairArrayIntPairArraySheetString m_data; DECLARE_ABSTRACT_CLASS(wxSheetValueProviderSparseString); }; // The wxSheetValueProviderHashString is probably not for everyone // UpdateRows/Cols functions are hard to implement reasonably // This is mostly a proof of concept and will probably be removed // since it's performance is not impressive. #define wxSHEET_USE_VALUE_PROVIDER_HASH #ifdef wxSHEET_USE_VALUE_PROVIDER_HASH // ---------------------------------------------------------------------------- // wxSheetValueProviderHashString - a wxHasMap wxString data container class // best used when you expect it to be less than about 3/4 full or so // since it stores an int for each row and an (int, wxString) for each col // it takes the option wxSHEET_ValueProviderColPref // ---------------------------------------------------------------------------- #include "wx/hashmap.h" WX_DECLARE_HASH_MAP( int, wxString, wxIntegerHash, wxIntegerEqual, wxSheetStringHash ); WX_DECLARE_HASH_MAP( int, wxSheetStringHash, wxIntegerHash, wxIntegerEqual, wxSheetStringHashStringHash ); class WXDLLIMPEXP_SHEET wxSheetValueProviderHashString : public wxSheetValueProviderBase { public: wxSheetValueProviderHashString(size_t numRows = 0u, size_t numCols = 0u, int options = 0); //virtual int GetNumberRows() const { return m_numRows; } //virtual int GetNumberCols() const { return m_numCols; } virtual wxString GetValue( const wxSheetCoords& coords ) const; virtual void SetValue( const wxSheetCoords& coords, const wxString& value ); virtual bool HasValue( const wxSheetCoords& coords ) const; virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const; virtual void ClearValues() { m_data.clear(); } virtual void Clear() { m_data.clear(); m_numRows = m_numCols = 0; } virtual bool UpdateRows( size_t row, int numRows ); virtual bool UpdateCols( size_t col, int numCols ); virtual void SetOptions(int options); // implementation const wxSheetStringHashStringHash& GetData() const { return m_data; } wxSheetStringHashStringHash& GetData() { return m_data; } protected: bool DoUpdateRows( size_t row, int numRows ); bool DoUpdateCols( size_t col, int numCols ); wxSheetStringHashStringHash m_data; DECLARE_ABSTRACT_CLASS(wxSheetValueProviderHashString); }; #endif // wxSHEET_USE_VALUE_PROVIDER_HASH // ---------------------------------------------------------------------------- // wxSheetTable - data provider table for the wxSheet you may want to subclass // this to optimize it for your purposes // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetTable : public wxObject, public wxClientDataContainer { public: wxSheetTable( wxSheet *sheet = NULL ); virtual ~wxSheetTable(); // Set/Get the wxSheet "owner" of this data virtual void SetView( wxSheet *sheet ) { m_view = sheet; } virtual wxSheet* GetView() const { return m_view; } // ------------------------------------------------------------------------ // Get the number of rows and cols // the default uses the number of rows/cols in GetCellData() virtual int GetNumberRows(); virtual int GetNumberCols(); // determine if row/col/coords is in 0 to GetNumberRows/Cols-1 bool ContainsGridRow( int row ) { return (row >= 0) && (row < GetNumberRows()); } bool ContainsGridCol( int col ) { return (col >= 0) && (col < GetNumberCols()); } bool ContainsGridCell(const wxSheetCoords& coords) { return ContainsGridRow(coords.m_row) && ContainsGridCol(coords.m_col); } // returns true if the coords are within the row/col label cells bool ContainsRowLabelCell( const wxSheetCoords& coords ) { return (coords.m_col == -1) && ContainsGridRow(coords.m_row); } bool ContainsColLabelCell( const wxSheetCoords& coords ) { return (coords.m_row == -1) && ContainsGridCol(coords.m_col); } // ------------------------------------------------------------------------ // Cell value handling // GetValue as a string, coords use -1 notatation for label cells // you must have set the value providers for cell values or subclass // this and return values on the fly. // the label will return a default value if no provider is set virtual wxString GetValue( const wxSheetCoords& coords ); // SetValue as a string, coords use -1 notatation for label cells // you must have previously set containers virtual void SetValue( const wxSheetCoords& coords, const wxString& value ); // Is this cell empty, uses container's HasValue or !GetValue().IsEmpty() virtual bool HasValue( const wxSheetCoords& coords ); // renderer helper, returns first col < coords.m_col that's !empty // or just return the previous col if you can't implement that virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ); // Clear the values of the grid, the defaut can be used to clear // ORed together different enum wxSheetUpdate_Type virtual void ClearValues(int update = wxSHEET_UpdateValues); // default GetRow/ColLabelValue returns numbers for rows and A-AZ for cols // GetValue is routed to these functions if no value providers for the // labels are set. wxString GetDefaultRowLabelValue( int row ) const; wxString GetDefaultColLabelValue( int col ) const; // Specific data type determination and value access // try to return GetValue as a long, returns 0 on failure virtual long GetValueAsLong( const wxSheetCoords& coords ); // try to return GetValue as a double, returns 0 on failure virtual double GetValueAsDouble( const wxSheetCoords& coords ); // try to return GetValue as a bool, // false is "", "0", "f", "false" w/ no case, true otherwise virtual bool GetValueAsBool( const wxSheetCoords& coords ); // Set the cell's value as a long "%ld", double "%g", or bool "0" or "1" // the default converts them to a string and calls SetValue virtual void SetValueAsLong( const wxSheetCoords& coords, long value ); virtual void SetValueAsDouble( const wxSheetCoords& coords, double value ); virtual void SetValueAsBool( const wxSheetCoords& coords, bool value ); // For user defined types you must cast the void* pointer to your datatype // as well as delete it. // The default implementation does nothing and gives an error if used virtual void* GetValueAsCustom( const wxSheetCoords& coords, const wxString& typeName ); virtual void SetValueAsCustom( const wxSheetCoords& coords, const wxString& typeName, void* value ); // Returns whether the type is supported, default is wxSHEET_VALUE_STRING virtual bool CanGetValueAs( const wxSheetCoords& coords, const wxString& typeName ); // Can you set the value as type? default returns CanGetValueAs virtual bool CanSetValueAs( const wxSheetCoords& coords, const wxString& typeName ); // Get the type name for the cell, default returns wxEmptyString, if you // return one of wxSHEET_VALUE_XXX the attributes will return an // appropriate renderer and editor virtual wxString GetTypeName( const wxSheetCoords& coords ); // Get/Set value providers, may be NULL. // The GridCellValueProvider is required unless you have subclassed // the table and override GetValue yourself. The label providers // are not necesary and GetDefaultRow/ColLabelValue will be called. // The providers will be deleted when done if is_owner = true. virtual wxSheetValueProviderBase* GetGridCellValueProvider() const { return m_gridCellValues; } virtual wxSheetValueProviderBase* GetRowLabelValueProvider() const { return m_rowLabelValues; } virtual wxSheetValueProviderBase* GetColLabelValueProvider() const { return m_colLabelValues; } void SetGridCellValueProvider(wxSheetValueProviderBase* gridCellValues, bool is_owner); void SetRowLabelValueProvider(wxSheetValueProviderBase* rowLabelValues, bool is_owner); void SetColLabelValueProvider(wxSheetValueProviderBase* colLabelValues, bool is_owner); // ------------------------------------------------------------------------ // Attribute handling // by default forwarded to wxSheetCellAttrProvider if any. May be // overridden to handle attributes directly in the table. // See wxSheetCellAttrProvider for coords and type meaning virtual wxSheetCellAttr GetAttr( const wxSheetCoords& coords, wxSheetAttr_Type kind ); // See wxSheetCellAttrProvider for coords and type meaning virtual void SetAttr( const wxSheetCoords& coords, const wxSheetCellAttr &attr, wxSheetAttr_Type kind ); // get the currently used attr provider (may be NULL) virtual wxSheetCellAttrProvider* GetAttrProvider() const { return m_attrProvider; } // Set the attr provider to use - take ownership if is_owner void SetAttrProvider(wxSheetCellAttrProvider *attrProvider, bool is_owner); // ------------------------------------------------------------------------ // Cell spanning - cells may overlap neighbor cells to the right and below, // hiding the cells they cover. // By default, the internal selection is created for you, however in a // subclassed table you may return NULL so long as you don't call // SetCellSpan or handle it yourself. // Note: this code should be as efficient as possible since it's called // numerous times during drawing. It would be nice to have two virtual // functions Get/Set and use them exculsively, but direct access to the // selection's array is decidedly faster under many circumstances. // See DrawAllGridLines and ExpandSpannedBlock for examples // Are there any spanned cells at all? virtual bool HasSpannedCells(); // Get a block of the cell, unless a spanned cell it's of size 1,1 // note: the top left of block is the 'owner' cell of coords virtual wxSheetBlock GetCellBlock( const wxSheetCoords& coords ); // Set the span of a cell, must be 1x1 or greater. // To remove a spanned cell set it to a cell of size 1x1 // For grid cells the whole block must be contained within the grid cells // and if the block intersects a previously spanned cell block the top left // corners must match up. // Row and Col labels can span cells as well, spanned row labels must have a // width of 1 and a height of >= 1, col labels a height of 1 and width >= 1 virtual void SetCellSpan( const wxSheetBlock& block ); virtual wxSheetSelection* GetSpannedBlocks() const { return m_spannedCells; } // Set the attr provider to use - take ownership if is_owner void SetSpannedBlocks(wxSheetSelection *spannedCells, bool is_owner); // ------------------------------------------------------------------------ // Update the number of rows cols // if numRows/Cols < 0 delete, else append if row/col == the current // number of rows/cols, else insert at row/col virtual bool UpdateRows( size_t row, int numRows, int update = wxSHEET_UpdateAll ); virtual bool UpdateCols( size_t col, int numCols, int update = wxSHEET_UpdateAll ); // If you have a pure virtual table and you merely want to alert the sheet // that the number of rows/cols have changed then call this function. // It compares the wxSheetTable::GetNumberRows/Cols to // wxSheet::GetNumberRows/Cols and either appends Rows/Cols or deletes // them from the end. // You probably won't want to use this if you've set attributes for // particular cells since this only appends and deletes from the end. bool UpdateSheetRowsCols(int update = wxSHEET_UpdateAll ); protected: // return update functions back to the sheet calling DoUpdateRows/Cols // if you subclass this you must make sure this is called bool UpdateSheetRows( size_t row, int numRows, int update = wxSHEET_UpdateAll ); bool UpdateSheetCols( size_t col, int numCols, int update = wxSHEET_UpdateAll ); wxSheet *m_view; // 'parent' wxSheet wxSheetCellAttrProvider *m_attrProvider; // attribute provider, if any bool m_own_attr_provider; wxSheetValueProviderBase *m_gridCellValues; // grid cell values bool m_own_grid_cell_values; wxSheetValueProviderBase *m_rowLabelValues; // row label values bool m_own_row_label_values; wxSheetValueProviderBase *m_colLabelValues; // col label values bool m_own_col_label_values; wxString m_cornerLabelValue; // single corner label value wxSheetSelection* m_spannedCells; // spanned blocks bool m_own_spanned_cells; DECLARE_ABSTRACT_CLASS(wxSheetTable); DECLARE_NO_COPY_CLASS(wxSheetTable) }; #endif // __WX_SHEETTBL_H__ gambit-0.2010.09.01/src/labenski/include/wx/sheet/wx24defs.h0000644000076500007650000000415211350032206020021 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: wx24defs.h // Purpose: Definitions to make a program using wxWidgets >= 2.5 work in 2.4 // Author: John Labenski // Modified by: // Created: 3/10/04 // RCS-ID: // Copyright: (c) John Labenski // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #ifndef __WX_WX24DEFS_H__ #define __WX_WX24DEFS_H__ // Include any headers that we need to redefine macros for #include "wx/defs.h" #include "wx/object.h" #include "wx/event.h" #include "wx/dynarray.h" //----------------------------------------------------------------------------- // wxWidgets 2.4 compatibility with code from >= 2.5 #ifndef WXDLLIMPEXP_ADV #define WXDLLIMPEXP_ADV WXDLLEXPORT #endif #ifndef DECLARE_NO_ASSIGN_CLASS #define DECLARE_NO_ASSIGN_CLASS(classname) \ private: \ classname& operator=(const classname&); #endif #ifndef WX_DECLARE_OBJARRAY_WITH_DECL #define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, expmode) WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLEXPORT) #endif #ifndef WX_DEFINE_ARRAY_WITH_DECL_PTR #define WX_DEFINE_ARRAY_WITH_DECL_PTR(T, name, decl) WX_DEFINE_ARRAY(T, name) #endif #ifndef WX_DEFINE_ARRAY_PTR #define WX_DEFINE_ARRAY_PTR(T, name) WX_DEFINE_ARRAY(T, name) #endif #ifndef DECLARE_EXPORTED_EVENT_TYPE #define DECLARE_EXPORTED_EVENT_TYPE(expdecl, name, value) DECLARE_LOCAL_EVENT_TYPE(name, value) #endif #ifndef wxStaticCastEvent #define wxStaticCastEvent(type, val) (type) val #endif #ifndef wxFULL_REPAINT_ON_RESIZE #define wxFULL_REPAINT_ON_RESIZE 0 #endif // ---------------------------------------------------------------------------- #if !wxCHECK_VERSION(2,5,0) // wxMenuItemList::compatibility_iterator was wxMenuItemList::Node* #define compatibility_iterator Node* #endif #ifndef wxSL_INVERSE // !wxCHECK_VERSION(2,5,3) // FIXME temp fix until 2.5.4 #define wxDefaultDateTimeFormat wxT("%c") #endif // wxInvalidDateTime #endif //__WX_WX24DEFS_H__ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/0000777000076500007650000000000011441457114017041 500000000000000gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/0000777000076500007650000000000011441457127020504 500000000000000gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/copy.xpm0000644000076500007650000000072511350032206022106 00000000000000/* XPM */ static const char *copy_xpm[] = { /* columns rows colors chars-per-pixel */ "16 15 4 1", " c None", ". c Black", "X c Gray100", "o c #000080", /* pixels */ " ", " ...... ", " .XXXX.. ", " .XXXX.X. ", " .X..X.oooooo ", " .XXXXXoXXXXoo ", " .X....oXXXXoXo ", " .XXXXXoX..Xoooo", " .X....oXXXXXXXo", " .XXXXXoX.....Xo", " ......oXXXXXXXo", " oX.....Xo", " oXXXXXXXo", " ooooooooo", " " }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/cut.xpm0000644000076500007650000000070511350032206021725 00000000000000/* XPM */ static const char *cut_xpm[] = { /* columns rows colors chars-per-pixel */ "16 15 3 1", " c None", ". c Black", "X c #000080", /* pixels */ " ", " . . ", " . . ", " . . ", " .. .. ", " . . ", " ... ", " . ", " X.X ", " X XXX ", " XXX X X ", " X X X X ", " X X X X ", " X X XX ", " XX " }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/find.xpm0000644000076500007650000000063511350032206022054 00000000000000/* XPM */ static const char *find_xpm[]={ "16 15 4 1", ". c None", "# c #000000", "b c #808080", "a c #ffffff", "................", "....##...##.....", "....##...##.....", "...####.####....", "...#a##.a###....", "..###########...", ".##a####a#####..", ".##a##b#a#####..", ".##a##b#a#####..", ".######.######..", ".#a###...#a###..", ".#a###...#a###..", ".#####...#####..", "................", "................"}; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/findnext.xpm0000644000076500007650000000066011350032206022751 00000000000000/* XPM */ static const char *findnext_xpm[]={ "16 15 5 1", ". c None", "# c #000000", "c c #000080", "b c #808080", "a c #ffffff", "....##...##.....", "....##...##.....", "...####.####....", "...#a##.a###....", "..###########...", ".##a####a#####..", ".##a##b#a#####..", ".##a##b#a#####..", ".######.######..", ".#a###...#a###..", ".#a###...#a###..", ".#####...#####..", "................", "...cc..cc..cc...", "...cc..cc..cc..."}; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/grab.xpm0000644000076500007650000000066111350032206022046 00000000000000/* XPM */ static const char *grab_xpm[]={ "16 16 4 1", ". c None", "a c #000000", "# c #000040", "b c #ffffff", "................", "................", "................", "....#aa##a##....", "...abbabbabbaa..", "...abbabbabbab#.", ".aa.abbbbbbbabba", "abbaabbbbbbbbbba", "abbbabbbbbbbbba.", ".abbbbbbbbbbbba.", "..abbbbbbbbbbba.", "..abbbbbbbbbba..", "...abbbbbbbbba..", "....abbbbbbba...", ".....abbbbbba...", ".....abbbbbba..."}; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/hand.xpm0000644000076500007650000000064211350032206022044 00000000000000/* XPM */ static const char *hand_xpm[] = { "16 16 3 1", " c None", "a c Black", "c c #FFFFFF", " aa ", " aa accaaa ", " accaaccacca ", " accaaccacca a ", " accaccaccaaca", " accaccaccacca", " aa acccccccacca", "accaacccccccccca", "acccaccccccccca ", " acccccccccccca ", " accccccccccca ", " acccccccccca ", " accccccccca ", " accccccca ", " acccccca ", " acccccca "}; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/help.xpm0000644000076500007650000000072211350032206022061 00000000000000/* XPM */ static const char *help_xpm[] = { /* columns rows colors chars-per-pixel */ "16 15 4 1", " c None", ". c Black", "X c Blue", "o c #000080", /* pixels */ " ", " ...... ", " .XXXXX.. ", " .XX...oX.. ", " .X.. .X.. ", " .X.. .XX.. ", " .. .XX.. ", " .XX.. ", " .X.. ", " .X.. ", " .o.. ", " .. ", " .XX.. ", " .XX.. ", " ... " }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/new.xpm0000644000076500007650000000076711350032206021733 00000000000000/* XPM */ static const char *new_xpm[] = { /* columns rows colors chars-per-pixel */ "16 16 5 1", " c None", "a c Black", "b c #C0C0C0", "d c #FFFFFF", "e c #808080", /* pixels */ " ", " aaaaaaaa ", " abbbbbbaa ", " abdddddada ", " abdddddaaaa ", " abddddddddae ", " abddddddddae ", " abddddddddae ", " abddddddddae ", " abddddddddae ", " abddddddddae ", " abddddddddae ", " abddddddddae ", " abddddddddae ", " aaaaaaaaaaae ", " eeeeeeeeeee " }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/open.xpm0000644000076500007650000000074311350032206022075 00000000000000/* XPM */ static const char *open_xpm[] = { /* columns rows colors chars-per-pixel */ "16 15 5 1", " c None", ". c Black", "X c Yellow", "o c Gray100", "O c #bfbf00", /* pixels */ " ", " ... ", " . . .", " ..", " ... ...", " .XoX....... ", " .oXoXoXoXo. ", " .XoXoXoXoX. ", " .oXoX..........", " .XoX.OOOOOOOOO.", " .oo.OOOOOOOOO. ", " .X.OOOOOOOOO. ", " ..OOOOOOOOO. ", " ........... ", " " }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/paste.xpm0000644000076500007650000000076311350032206022252 00000000000000/* XPM */ static const char *paste_xpm[] = { /* columns rows colors chars-per-pixel */ "16 15 6 1", " c None", ". c Black", "X c Yellow", "o c #808080", "O c #000080", "+ c Gray100", /* pixels */ " ", " .... ", " .....XX..... ", ".ooo.X..X.ooo. ", ".oo. .oo. ", ".oo........oo. ", ".oooooooooooo. ", ".oooooOOOOOOO. ", ".oooooO+++++OO ", ".oooooO+++++O+O ", ".oooooO+OOO+OOO ", ".oooooO+++++++O ", ".oooooO+OOOOO+O ", " .....O+++++++O ", " OOOOOOOOO " }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/preview.xpm0000644000076500007650000000074411350032206022616 00000000000000/* XPM */ static const char *preview_xpm[] = { /* columns rows colors chars-per-pixel */ "16 15 5 1", " c Black", ". c None", "X c Gray100", "o c #808080", "O c Cyan", /* pixels */ " .......", " XXXXXXX ......", " XXXXXXX . .....", " XXXXXXX ....", " XXXXXXXXXX ....", " XXXXXXX ....", " XXXXXX o..o ...", " XXXXX oOO.oo ..", " XXXXX .O..o. ..", " XXXXX ....o. ..", " XXXXX o..Ooo ..", " XXXXXX o..o o..", " XXXXXXX o .", " XXXXXXXXXX . ", " .. " }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/print.xpm0000644000076500007650000000074411350032206022271 00000000000000/* XPM */ static const char *print_xpm[] = { /* columns rows colors chars-per-pixel */ "16 15 5 1", " c None", ". c Black", "X c Gray100", "o c #808000", "O c Yellow", /* pixels */ " ", " ......... ", " .XXXXXXXX. ", " .X.....X. ", " .XXXXXXXX. ", " .X.....X.... ", " .XXXXXXXX. . .", " .......... . ..", ". . . .", "............. .", ". ooo . . ", ". OOO ... ", "............. . ", " . . . ", " ........... " }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/question.xpm0000644000076500007650000000062211350032206022777 00000000000000/* XPM */ static const char *question_xpm[]={ "16 15 3 1", ". c None", "# c #000000", "a c #ffff00", "................", ".....######.....", "....#aaaaa##....", "...#aa###aa##...", "...#a##..#a##...", "...#a##.#aa##...", "....##.#aa##....", "......#aa##.....", "......#a##......", "......#a##......", "......#a##......", ".......##.......", "......#aa##.....", "......#aa##.....", ".......###......"}; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/redo.xpm0000644000076500007650000000076211350032206022066 00000000000000/* XPM */ static const char *redo_xpm[] = { /* width height num_colors chars_per_pixel */ " 16 15 3 1", /* colors */ "# c None", ". c #000080", "a c #808080", /* pixels */ "################", "################", "################", "################", "###a....########", "##a.####..###.##", "##.#######.#..##", "##.########...##", "##.#######....##", "##a.#####.....##", "###.a###########", "################", "################", "################", "################" }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/replace.xpm0000644000076500007650000000065711350032206022553 00000000000000/* XPM */ static const char *replace_xpm[]={ "16 15 5 1", ". c None", "# c #000000", "c c #000080", "b c #808080", "a c #ffffff", "....##...##.....", "....##...##.....", "...####.####....", "...#a##.a###....", "..###########...", ".##a####a#####..", ".##a##b#a#####..", ".##a##b#a#####..", ".######.######..", ".#a###...#a###..", ".#a###...#a###..", ".#####...#####..", "...c......ccc...", "..c.c.ccc..c....", "..c.c.....ccc..."}; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/saveall.xpm0000644000076500007650000000064011350032206022557 00000000000000/* XPM */ static const char *saveall_xpm[]={ "16 15 4 1", ". c None", "# c #000000", "a c #808000", "b c #c0c0c0", "....###########.", "....#a#bbbbb#b#.", "..#############.", "..#a#bbbbb#b#a#.", "#############a#.", "#a#bbbbb#b#a#a#.", "#a#bbbbb###a#a#.", "#a#bbbbb#a#a#a#.", "#a#bbbbb#a#a#a#.", "#aa#####aa#a#a#.", "#aaaaaaaaa#a###.", "#aa######a#a#...", "#aa####b#a###...", "#aa####b#a#.....", ".##########b...."}; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/saveas.xpm0000644000076500007650000000074611350032206022421 00000000000000/* XPM */ static const char *saveas_xpm[] = { /* columns rows colors chars-per-pixel */ "16 15 5 1", " c None", ". c Black", "X c #808000", "o c #808080", "r c #FF0000", /* pixels */ " ", " ...........rr. ", " .X. r. . ", " .X. r r ... ", " .X. r r .X. ", " .X. r .X. ", " .X. .X. ", " .X. .X. ", " .XX........oX. ", " .XXXXXXXXXXXX. ", " .XX.........X. ", " .XX...... .X. ", " .XX...... .X. ", " .XX...... .X. ", " ............. " }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/spell.xpm0000644000076500007650000000073711350032206022256 00000000000000/* XPM */ static const char *spell_xpm[]={ "16 16 7 1", ". c None", "# c #000000", "b c #000080", "c c #008080", "e c #808080", "a c #d9d9d9", "d c #ffffff", ".##############.", "##abbbbbbbbbbbb#", "#abbbbbbbbbbbbb#", "#abcdcbddabadab#", "#abdbdbdbdbdbdb#", "#abdddbdddbdbbb#", "#abdbdbdbdbdbdb#", "#abdbdbddabadab#", "#abbbbbbbbbbbbb#", "#abbbbbbbbbbbbb#", "#abbbbbbbbbbbbb#", "#a##############", "##babababababab#", "#aaeaeaeaeaeaea#", "#eaaeaeaeaeaeae#", ".###############"}; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bitmaps/undo.xpm0000644000076500007650000000073111350032206022076 00000000000000/* XPM */ static const char *undo_xpm[] = { /* width height num_colors chars_per_pixel */ "16 15 3 1", /* colors */ "# c None", ". c #000080", "a c #808080", /* pixels */ "################", "################", "################", "################", "########....a###", "##.###..####.a##", "##..#.#######.##", "##...########.##", "##....#######.##", "##.....#####.a##", "###########a.###", "################", "################", "################", "################" }; gambit-0.2010.09.01/src/labenski/include/wx/wxthings/block.h0000644000076500007650000005414511350032206020217 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: block.h // Purpose: Rectangular selection storage classes for ints and doubles // Author: John Labenski // Created: 07/01/02 // Copyright: (c) John Labenski, 2004 // License: wxWidgets ///////////////////////////////////////////////////////////////////////////// #ifndef __wxBLOCK_H__ #define __wxBLOCK_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "block.h" #endif #include "wx/geometry.h" #include "wx/wxthings/thingdef.h" //#define USE_wxRANGE #ifdef USE_wxRANGE #include "wx/wxthings/range.h" #endif // Note: Why are these not just wxRect2DXXX with m_x and m_width? // because the double blocks need to match up at the edges and x+width // does not always exactly equal the edge of an adjoining block class WXDLLIMPEXP_THINGS wxBlockInt; class WXDLLIMPEXP_THINGS wxBlockDouble; class WXDLLIMPEXP_THINGS wxBlockIntSelection; class WXDLLIMPEXP_THINGS wxBlockDoubleSelection; #include "wx/dynarray.h" WX_DECLARE_OBJARRAY(wxBlockInt, wxArrayBlockInt); WX_DECLARE_OBJARRAY(wxBlockDouble, wxArrayBlockDouble); WX_DECLARE_OBJARRAY(wxBlockIntSelection, wxArrayBlockIntSelection); WX_DECLARE_OBJARRAY(wxBlockDoubleSelection, wxArrayBlockDoubleSelection); //============================================================================= // wxBlockXXX constants //============================================================================= // wxEmptyBlockXXX = (0,0,-1,-1) WXDLLIMPEXP_DATA_THINGS(extern const wxBlockInt) wxEmptyBlockInt; WXDLLIMPEXP_DATA_THINGS(extern const wxBlockDouble) wxEmptyBlockDouble; //============================================================================= // wxBlockXXX sorting functions //============================================================================= enum wxBlockSort_Type { wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT, wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT, wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT, wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT, wxBLOCKSORT_SMALLEST_TO_LARGEST, wxBLOCKSORT_LARGEST_TO_SMALLEST }; // functions to sort an array of blocks from any corner extern void wxArrayBlockIntSort(wxArrayBlockInt &blocks, wxBlockSort_Type type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT); extern void wxArrayBlockDoubleSort(wxArrayBlockDouble &blocks, wxBlockSort_Type type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT); //============================================================================= // wxBlockInt - a rectangle bounded by the corner points that can combine with // other wxBlockInts //============================================================================= class WXDLLIMPEXP_THINGS wxBlockInt { public: inline wxBlockInt(wxInt32 x1=0, wxInt32 y1=0, wxInt32 x2=0, wxInt32 y2=0) : m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2) {} inline wxBlockInt(const wxRect2DInt &rect) : m_x1(rect.m_x), m_y1(rect.m_y), m_x2(rect.GetRight()), m_y2(rect.GetBottom()) {} inline wxInt32 GetLeft() const { return m_x1; } inline wxInt32 GetRight() const { return m_x2; } inline wxInt32 GetTop() const { return m_y1; } inline wxInt32 GetBottom() const { return m_y2; } inline wxInt32 GetWidth() const { return m_x2 - m_x1 + 1; } inline wxInt32 GetHeight() const { return m_y2 - m_y1 + 1; } inline wxPoint2DInt GetLeftTop() const { return wxPoint2DInt(m_x1, m_y1); } inline wxPoint2DInt GetLeftBottom() const { return wxPoint2DInt(m_x1, m_y2); } inline wxPoint2DInt GetRightTop() const { return wxPoint2DInt(m_x2, m_y1); } inline wxPoint2DInt GetRightBottom() const { return wxPoint2DInt(m_x2, m_y2); } inline wxRect2DInt GetRect2DInt() const { return wxRect2DInt(m_x1, m_y1, m_x2-m_x1+1, m_y2-m_y1+1); } inline void SetRect2DInt(const wxRect2DInt &r) { m_x1=r.m_x; m_y1=r.m_y, m_x2=r.GetRight(); m_y2=r.GetBottom(); } inline bool Contains( wxInt32 x, wxInt32 y ) const { return ((x >= m_x1) && (x <= m_x2) && (y >= m_y1) && (y <= m_y2)); } inline bool Contains( const wxPoint2DInt &pt ) const { return Contains(pt.m_x, pt.m_y); } inline bool Contains( const wxBlockInt &b ) const { return ((m_x1 <= b.m_x1) && (b.m_x2 <= m_x2) && (m_y1 <= b.m_y1) && (b.m_y2 <= m_y2)); } inline bool Intersects( const wxBlockInt &b ) const { return (wxMax(m_x1, b.m_x1)<=wxMin(m_x2, b.m_x2)) && (wxMax(m_y1, b.m_y1)<=wxMin(m_y2, b.m_y2)); } inline void Intersect( const wxBlockInt &otherBlock ) { Intersect( *this, otherBlock, this ); } inline void Intersect( const wxBlockInt &src1 , const wxBlockInt &src2 , wxBlockInt *dest ) const { dest->m_x1 = wxMax(src1.m_x1, src2.m_x1); dest->m_x2 = wxMin(src1.m_x2, src2.m_x2); dest->m_y1 = wxMax(src1.m_y1, src2.m_y1); dest->m_y2 = wxMin(src1.m_y2, src2.m_y2); } inline void Union( const wxBlockInt &otherBlock ) { Union(*this, otherBlock, this); } inline void Union( const wxBlockInt &src1, const wxBlockInt &src2, wxBlockInt *dest ) const { dest->m_x1 = wxMin(src1.m_x1, src2.m_x1); dest->m_x2 = wxMax(src1.m_x2, src2.m_x2); dest->m_y1 = wxMin(src1.m_y1, src2.m_y1); dest->m_y2 = wxMax(src1.m_y2, src2.m_y2); } // is this block larger than input block, return 1 = larger, 0 = equal, -1 = smaller int IsLarger(const wxBlockInt &b) const { wxInt32 width = m_x2 - m_x1 + 1, height = m_y2 - m_y1 + 1, b_width = b.m_x2 - b.m_x1 + 1, b_height = b.m_y2 - b.m_y1 + 1; if ((width <= 0) || (height <= 0)) return (b_width > 0) && (b_height > 0) ? -1 : 0; if ((b_width <= 0) || (b_height <= 0)) return (width > 0) && (height > 0) ? 1 : 0; wxDouble w_bw = wxDouble(width)/b_width, bh_h = wxDouble(b_height)/height; return (w_bw == bh_h) ? 0 : ((w_bw > bh_h) ? 1 : -1); } bool IsEmpty() const { return (m_x1 > m_x2) || (m_y1 > m_y2); } // Unlike Intersects this also includes just touching the other block bool Touches(const wxBlockInt &block) const; // Try to combine these blocks, they must touch and fit to make a single larger block // this block is expanded if possible bool Combine(const wxBlockInt &block); // test combining the input block with this one, returning the // remainder of block in top, bottom, left, right - each may be IsEmpty() // returns false if blocks don't touch or this block already contains block // |---------------------------| // | top | // |---------------------------| // | left |block| right | // |---------------------------| // | bottom | // |---------------------------| bool Combine( const wxBlockInt &block, wxBlockInt &top, wxBlockInt &bottom, wxBlockInt &left, wxBlockInt &right) const; // test removal of a portion or all of this contained in block returning the // remainder in top, bottom, left, right - each may be IsEmpty() // returns false if nothing to delete, this cell is not changed bool Delete(const wxBlockInt &block, wxBlockInt &top, wxBlockInt &bottom, wxBlockInt &left, wxBlockInt &right) const; // operators inline bool operator == (const wxBlockInt& b) { return (m_x1==b.m_x1) && (m_y1==b.m_y1) && (m_x2==b.m_x2) && (m_y2==b.m_y2); } inline bool operator != (const wxBlockInt& b) { return !(*this == b); } wxInt32 m_x1, m_y1, m_x2, m_y2; }; //============================================================================= // wxBlockDouble //============================================================================= class WXDLLIMPEXP_THINGS wxBlockDouble { public: inline wxBlockDouble(wxDouble x1=0, wxDouble y1=0, wxDouble x2=0, wxDouble y2=0) : m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2) {} inline wxBlockDouble(const wxRect2DDouble &rect) { m_x1=rect.m_x; m_y1=rect.m_y; m_x2=rect.GetRight(); m_y2=rect.GetBottom(); } inline wxDouble GetLeft() const { return m_x1; } inline wxDouble GetRight() const { return m_x2; } inline wxDouble GetTop() const { return m_y1; } inline wxDouble GetBottom() const { return m_y2; } inline wxDouble GetWidth() const { return m_x2 - m_x1; } inline wxDouble GetHeight() const { return m_y2 - m_y1; } inline wxPoint2DDouble GetLeftTop() const { return wxPoint2DDouble(m_x1, m_y1); } inline wxPoint2DDouble GetLeftBottom() const { return wxPoint2DDouble(m_x1, m_y2); } inline wxPoint2DDouble GetRightTop() const { return wxPoint2DDouble(m_x2, m_y1); } inline wxPoint2DDouble GetRightBottom() const { return wxPoint2DDouble(m_x2, m_y2); } inline wxRect2DDouble GetRect2DDouble() const { return wxRect2DDouble(m_x1, m_y1, m_x2-m_x1, m_y2-m_y1); } inline void SetRect2DDouble(const wxRect2DDouble &r) { m_x1=r.m_x; m_y1=r.m_y, m_x2=r.GetRight(); m_y2=r.GetBottom(); } inline bool Contains( wxDouble x, wxDouble y ) const { return ((x >= m_x1) && (x <= m_x2) && (y >= m_y1) && (y <= m_y2)); } inline bool Contains( const wxPoint2DDouble &pt ) const { return Contains(pt.m_x, pt.m_y); } inline bool Contains( const wxBlockDouble &b ) const { return ((m_x1 <= b.m_x1) && (b.m_x2 <= m_x2) && (m_y1 <= b.m_y1) && (b.m_y2 <= m_y2)); } inline bool Intersects( const wxBlockDouble &b ) const { return (wxMax(m_x1, b.m_x1)m_x1 = wxMax(src1.m_x1, src2.m_x1); dest->m_x2 = wxMin(src1.m_x2, src2.m_x2); dest->m_y1 = wxMax(src1.m_y1, src2.m_y1); dest->m_y2 = wxMin(src1.m_y2, src2.m_y2); } inline void Union( const wxBlockDouble &otherBlock ) { Union( *this, otherBlock, this ); } inline void Union( const wxBlockDouble &src1, const wxBlockDouble &src2, wxBlockDouble *dest ) const { dest->m_x1 = wxMin(src1.m_x1, src2.m_x1); dest->m_x2 = wxMax(src1.m_x2, src2.m_x2); dest->m_y1 = wxMin(src1.m_y1, src2.m_y1); dest->m_y2 = wxMax(src1.m_y2, src2.m_y2); } // is this block larger than input block, return 1 - larger, 0 = equal, -1 smaller int IsLarger(const wxBlockDouble &b) const { wxDouble width = m_x2 - m_x1, height = m_y2 - m_y1, b_width = b.m_x2 - b.m_x1, b_height = b.m_y2 - b.m_y1; if ((width <= 0) || (height <= 0)) return (b_width > 0) && (b_height > 0) ? -1 : 0; if ((b_width <= 0) || (b_height <= 0)) return (width > 0) && (height > 0) ? 1 : 0; wxDouble w_bw = width/b_width, bh_h = b_height/height; return (w_bw == bh_h) ? 0 : ((w_bw > bh_h) ? 1 : -1); } inline bool IsEmpty() const { return (m_x1 > m_x2) || (m_y1 > m_y2); } // Unlike Intersects this also includes just touching the other block bool Touches(const wxBlockDouble &block) const; // Try to combine these blocks, they must touch and fit to make a single larger block // this block is expanded if possible bool Combine(const wxBlockDouble &block); // test combining the input block with this one, returning the // remainder of block in top, bottom, left, right - each may be IsEmpty() // returns false if blocks don't touch or this block already contains block // |---------------------------| // | top | // |---------------------------| // | left |block| right | // |---------------------------| // | bottom | // |---------------------------| bool Combine( const wxBlockDouble &block, wxBlockDouble &top, wxBlockDouble &bottom, wxBlockDouble &left, wxBlockDouble &right) const; // test removal of a portion or all of this contained in block returning the // remainder in top, bottom, left, right - each may be IsEmpty() // returns false if nothing to delete, this cell is not changed bool Delete( const wxBlockDouble &block, wxBlockDouble &top, wxBlockDouble &bottom, wxBlockDouble &left, wxBlockDouble &right) const; // operators inline bool operator == (const wxBlockDouble& b) { return (m_x1==b.m_x1) && (m_y1==b.m_y1) && (m_x2==b.m_x2) && (m_y2==b.m_y2); } inline bool operator != (const wxBlockDouble& b) { return !(*this == b); } wxDouble m_x1, m_y1, m_x2, m_y2; }; //============================================================================= // wxBlockIntSelection - ordered 2D array of wxBlockInts, combines to minimize size // blocks never overlap each other //============================================================================= class WXDLLIMPEXP_THINGS wxBlockIntSelection { public : wxBlockIntSelection(wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) : m_sort(sort_type) {} wxBlockIntSelection(const wxBlockIntSelection &blocks, wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) : m_sort(sort_type) { Copy(blocks); } // Make a full copy of the source void Copy(const wxBlockIntSelection &source) { m_blocks.Clear(); WX_APPEND_ARRAY(m_blocks, source.GetBlockArray()); m_sort = source.GetSortType(); } inline int GetCount() const { return m_blocks.GetCount(); } inline void Clear() { m_blocks.Clear(); } wxArrayBlockInt GetBlockArray() const { return m_blocks; } #ifdef USE_wxRANGE // Get an array of ranges cutting though these blocks wxArrayRangeInt GetBlockCol(int col) const; wxArrayRangeInt GetBlockRow(int row) const; #endif wxBlockInt GetBlock( int index ) const; inline wxBlockInt Item( int index ) const { return GetBlock(index); } // Get a block that bounds the selection wxBlockInt GetBoundingBlock() const; // do any of the blocks contains elements inline bool Contains( int x, int y ) const { return Index(x,y) != wxNOT_FOUND; } inline bool Contains( const wxPoint2DInt &pt ) const { return Index(pt) != wxNOT_FOUND; } inline bool Contains( const wxBlockInt &b ) const { return Index(b) != wxNOT_FOUND; } // what is the index of a block that contains element int Index( int x, int y ) const; inline int Index( const wxPoint2DInt &pt ) const { return Index(pt.m_x, pt.m_y); } int Index( const wxBlockInt &b ) const; // Sorts the blocks according to the wxBlockIntSort_Type void Sort(wxBlockSort_Type type = wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT); wxBlockSort_Type GetSortType() const { return m_sort; } // Add the block to the selection, returns false if nothing was done // use combineNow=false to make quick additions, when done call Minimize() // addedBlocks (if !NULL) will be filled with the actual changed selections // by removing the previous selections from the input block bool SelectBlock( const wxBlockInt &block, bool combineNow=true, wxArrayBlockInt *addedBlocks=NULL); // Remove the block to the selection, return false if nothing was done // use combineNow=false to make quick additions, when done call Minimize() bool DeselectBlock( const wxBlockInt &block, bool combineNow=true); // Try to combine the blocks if possible, returns if anything was done // only need to call this if you've called (De)SelectBlock(..., false) bool Minimize(); // Operators inline wxBlockInt operator[](int index) const { return GetBlock(index); } //wxBlockIntSelection& operator = (const wxBlockIntSelection& other) { Copy(other); return *this; } // generic routine using if (b1.Combine(b2)) remove b2 to cleanup array // sort top_left_bottom_right first (internal use) static bool DoMinimize( wxArrayBlockInt &blocks ); // DoMinimize calls this internally static bool DoDoMinimize( wxArrayBlockInt &blocks ); protected : wxArrayBlockInt m_blocks; wxBlockSort_Type m_sort; }; //============================================================================= // wxBlockDoubleSelection - ordered 2D array of wxBlockDoubles, combines to minimze size // blocks never overlap each other //============================================================================= class WXDLLIMPEXP_THINGS wxBlockDoubleSelection { public : wxBlockDoubleSelection(wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) : m_sort(sort_type) {} wxBlockDoubleSelection(const wxBlockDoubleSelection &blocks, wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) : m_sort(sort_type) { Copy(blocks); } // Make a full copy of the source void Copy(const wxBlockDoubleSelection &source) { m_blocks.Clear(); WX_APPEND_ARRAY(m_blocks, source.GetBlockArray()); m_sort = source.GetSortType(); } inline int GetCount() const { return m_blocks.GetCount(); } inline void Clear() { m_blocks.Clear(); } wxArrayBlockDouble GetBlockArray() const { return m_blocks; } #ifdef USE_wxRANGE // Get an array of ranges cutting though these blocks wxArrayRangeDouble GetBlockCol(wxDouble col) const; wxArrayRangeDouble GetBlockRow(wxDouble row) const; #endif wxBlockDouble GetBlock( int index ) const; inline wxBlockDouble Item( int index ) const { return GetBlock(index); } // Get a block that bounds the selection wxBlockDouble GetBoundingBlock() const; // do any of the blocks contains elements inline bool Contains( wxDouble x, wxDouble y ) const { return Index(wxPoint2DDouble(x,y)) != wxNOT_FOUND; } inline bool Contains( const wxPoint2DInt &pt ) const { return Index(pt) != wxNOT_FOUND; } inline bool Contains( const wxBlockDouble &b ) const { return Index(b) != wxNOT_FOUND; } // what is the index of a block that contains element int Index( wxDouble x, wxDouble y ) const; inline int Index( const wxPoint2DDouble &pt ) const { return Index(pt.m_x, pt.m_y); } int Index( const wxBlockDouble &b ) const; // Sorts the blocks according to the wxBlockIntSort_Type void Sort(wxBlockSort_Type type = wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT); wxBlockSort_Type GetSortType() const { return m_sort; } // Add the block to the selection, returns false if nothing was done // use combineNow=false to make quick additions, when done call Minimize() bool SelectBlock( const wxBlockDouble &block, bool combineNow=true); // Remove the block to the selection, return false if nothing was done // use combineNow=false to make quick additions, when done call Minimize() bool DeselectBlock( const wxBlockDouble &block, bool combineNow=true); // Try to combine the blocks if possible, returns if anything was done // only need to call this if you've called (De)SelectBlock(..., false) bool Minimize(); // Operators inline wxBlockDouble operator[](int index) const { return GetBlock(index); } //wxBlockIntSelection& operator = (const wxBlockIntSelection& other) { Copy(other); return *this; } // generic routine using if (b1.Combine(b2)) remove b2 to cleanup array // sort top_left_bottom_right first (internal use) static bool DoMinimize( wxArrayBlockDouble &blocks ); // DoMinimize calls this internally static bool DoDoMinimize( wxArrayBlockDouble &blocks ); protected : wxArrayBlockDouble m_blocks; wxBlockSort_Type m_sort; }; //============================================================================= // wxBlockIntSelectionIterator - iterates through a wxBlockIntSelection //============================================================================= enum wxBISI_Type { wxBISI_POINT, // wxBlockIntSelectionIterator::SetType go point by point wxBISI_BLOCK // go block by block }; class WXDLLIMPEXP_THINGS wxBlockIntSelectionIterator { public : wxBlockIntSelectionIterator( const wxBlockIntSelection &sel, wxBISI_Type type = wxBISI_POINT ); wxBlockIntSelectionIterator( const wxArrayBlockInt &blocks, wxBISI_Type type = wxBISI_POINT ); // resets the iterating to start at the beginning void Reset(); // Set the method to get the blocks, either point by point or each whole block // also resets the iteration to the beginning void SetType( wxBISI_Type type ) { m_type = type; Reset(); } wxBISI_Type GetType() const { return m_type; } // Get next selection, returns false if at end (only valid for wxBISI_point) bool GetNext(wxPoint2DInt &pt); // Get next selection, returns false if at end (only valid for wxBISI_block) bool GetNext(wxBlockInt &block); // checks if this row and col are in this selection bool IsInSelection(const wxPoint2DInt &pt) const; inline bool IsInSelection( int x, int y ) const { return IsInSelection(wxPoint2DInt(x,y)); } protected : wxBISI_Type m_type; int m_block_index; wxPoint2DInt m_pt; wxArrayBlockInt m_blocks; }; //============================================================================= // wxBlockDoubleSelectionIterator - iterates through a wxBlockDoubleSelection //============================================================================= class WXDLLIMPEXP_THINGS wxBlockDoubleSelectionIterator { public : wxBlockDoubleSelectionIterator( const wxBlockDoubleSelection &sel ); wxBlockDoubleSelectionIterator( const wxArrayBlockDouble &blocks ); // resets the iterating to start at the beginning void Reset(); // Get next selection, returns false if at the end bool GetNext(wxBlockDouble &block); // checks if this row and col are in this selection bool IsInSelection(const wxPoint2DDouble &pt) const; inline bool IsInSelection( int x, int y ) const { return IsInSelection(wxPoint2DDouble(x,y)); } protected : size_t m_block_index; wxArrayBlockDouble m_blocks; }; #endif // __wxBLOCK_H__ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/bmpcombo.h0000644000076500007650000001716211350032206020721 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: wxBitmapComboBox // Purpose: A wxComboBox type button for bitmaps and strings // Author: John Labenski // Modified by: // Created: 11/05/2002 // Copyright: (c) John Labenski // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// /* wxBitmapComboBox is a wxComboBox widget for bitmaps You Append some bitmaps either individually or with an array. Since bitmaps are refed this should be a fast process and you don't have to keep them around. The size of the items is calculated from the max bitmap and max label so that they will all line up nicely. It acts just like a wxComboBox otherwise, sends a EVT_COMBOBOX when selections are made with either the mouse on the pulldown list or by pressing the up/down arrows. */ #ifndef _WX_BMPCOMBO_H_ #define _WX_BMPCOMBO_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "bmpcombo.h" #endif #include "wx/wxthings/thingdef.h" #include "wx/wxthings/dropdown.h" class WXDLLEXPORT wxMenu; class WXDLLEXPORT wxBitmap; class WXDLLEXPORT wxKeyEvent; class WXDLLEXPORT wxPaintEvent; class WXDLLEXPORT wxDC; class WXDLLIMPEXP_THINGS wxCustomButton; class WXDLLIMPEXP_THINGS wxBitmapComboPopupChild; class WXDLLIMPEXP_THINGS wxBitmapComboLabel; enum wxBitmapComboBox_Style { // Position of the labels relative to the bitmaps, use only one wxBMPCOMBO_LEFT = wxCB_DROPDOWN, wxBMPCOMBO_RIGHT = wxCB_SIMPLE }; class WXDLLIMPEXP_THINGS wxBitmapComboBox : public DropDownBase { public: wxBitmapComboBox() : DropDownBase() { Init(); } // Compatible with a wxComboBox, uses strings only wxBitmapComboBox(wxWindow *parent, wxWindowID id, const wxString& value = wxEmptyString, // used only if first choice is !null const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, int n = 0, const wxString choices[] = (const wxString *) NULL, long style = wxBMPCOMBO_RIGHT, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxBitmapComboBox")) :DropDownBase() { Init(); if ((n > 0) || (!value.IsEmpty())) { if ((n > 0) && choices) { for (int i=0; iSetChild(win) in your DoShowPopup function. Additionally, you'll want to put a window to the left of the dropdown button. You need to subclass this to make a new control. You need to override these function in DropDownBase DoGetBestSize() let wxWidgets know how big this control wants to be DoGetBestDropHeight(max) - max is the # pixels to bottom of screen, you probably want it smaller so return that height, return -1 if you don't want the popup shown. DoShowPopup() - this is called from ShowPopup after creating the m_popupWin. Create your child window with the popup as the parent and call GetPopupWindow()->SetChild(win). Make sure you call DropDownBase::DoShowPopup() to have the popup window shown. */ #ifndef _WX_DROPDOWNBASE_H_ #define _WX_DROPDOWNBASE_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "dropdown.h" #endif #include "wx/popupwin.h" #include "wx/wxthings/thingdef.h" class WXDLLEXPORT wxTimer; class WXDLLEXPORT wxTimerEvent; class WXDLLEXPORT wxCustomButton; class WXDLLIMPEXP_THINGS DropDownPopup; #define DROPDOWN_DROP_WIDTH 14 // these are the default sizes #define DROPDOWN_DROP_HEIGHT 22 //----------------------------------------------------------------------------- // DropDownBase generic combobox type widget that drops down a DropDownPopup //----------------------------------------------------------------------------- class WXDLLIMPEXP_THINGS DropDownBase : public wxControl { public: DropDownBase() : wxControl() { Init(); } DropDownBase( wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("DropDownBase")) : wxControl() { Init(); Create(parent, id, pos, size, style, val, name); } virtual ~DropDownBase(); bool Create(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("DropDownBase")); virtual bool ShowPopup(); virtual void HidePopup(); bool IsPopupShown(); // implementation void OnDropButton( wxCommandEvent &event ); wxCustomButton* GetDropDownButton() { return m_dropdownButton; } // Get the popup window, NULL when not shown DropDownPopup* GetPopupWindow() { return m_popupWin; } protected: virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); void OnSize( wxSizeEvent& event ); virtual wxSize DoGetBestSize() const; virtual bool DoShowPopup(); // override to set the height of the dropdown box // input max_height is height from bottom of ctrl to bottom of screen // return < 1 to not have the popup displayed virtual int DoGetBestDropHeight(int max_height) { return max_height; } wxCustomButton *m_dropdownButton; DropDownPopup *m_popupWin; private: void Init(); DECLARE_DYNAMIC_CLASS(DropDownBase) DECLARE_EVENT_TABLE() }; //----------------------------------------------------------------------------- // DropDownPopup generic popup window, call SetChild //----------------------------------------------------------------------------- #ifdef GAMBIT_UNUSED class WXDLLIMPEXP_THINGS DropDownPopup : public wxPopupTransientWindow { public: DropDownPopup() : wxPopupTransientWindow() { Init(); } DropDownPopup(DropDownBase *parent, int style = wxBORDER_NONE) : wxPopupTransientWindow() { Init(); Create(parent, style); } virtual ~DropDownPopup(); bool Create(DropDownBase *parent, int style = wxBORDER_NONE); virtual void Popup(wxWindow *focus = NULL); virtual void Dismiss(); virtual bool ProcessLeftDown(wxMouseEvent& event); virtual void SetChild(wxWindow *child); virtual wxWindow *GetChild() const { return m_childWin; } bool m_ignore_popup; protected: // start/stop timer shat pushes and pops handler when the mouse goes over // the scrollbars (if any) of the child window void StartTimer(); void StopTimer(); void PushPopupHandler(wxWindow* child); void PopPopupHandler(wxWindow* child); void OnMouse( wxMouseEvent& event ); void OnKeyDown( wxKeyEvent &event ); void OnTimer( wxTimerEvent& event ); void OnIdle( wxIdleEvent& event ); wxPoint m_mouse; // last/current mouse position wxWindow *m_childWin; // store our own child pointer DropDownBase *m_owner; wxTimer *m_timer; // timer for tracking mouse position bool m_popped_handler; // state of the event handler private: void Init(); DECLARE_DYNAMIC_CLASS(DropDownPopup) DECLARE_EVENT_TABLE() }; #endif // GAMBIT_UNUSED #endif // _WX_DROPDOWNBASE_H_ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/filebrws.h0000644000076500007650000003516511350032206020743 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: filebrws.h // Purpose: A file browser widget with tree and/or list control views // Author: John Labenski // Created: 07/01/02 // Copyright: John Labenski, 2002 // License: wxWidgets ///////////////////////////////////////////////////////////////////////////// #ifndef __WX_FILEBROWSER_H__ #define __WX_FILEBROWSER_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "filebrws.h" #endif #include "wx/listctrl.h" #include "wx/dirctrl.h" #include "wx/filedlg.h" #include "wx/textdlg.h" #include "wx/generic/filedlgg.h" #include "wx/things/thingdef.h" class WXDLLEXPORT wxCheckBox; class WXDLLEXPORT wxComboBox; class WXDLLEXPORT wxTreeEvent; class WXDLLEXPORT wxSplitterWindow; class WXDLLEXPORT wxGenericDirCtrl; class WXDLLEXPORT wxListCtrl; class WXDLLEXPORT wxListEvent; class WXDLLEXPORT wxToolBar; class WXDLLEXPORT wxBitmapButton; class WXDLLEXPORT wxConfigBase; class WXDLLEXPORT wxFileCtrl; class WXDLLEXPORT wxFileName; class WXDLLIMPEXP_THINGS wxFileBrowser; #include "wx/dynarray.h" WX_DECLARE_OBJARRAY(wxFileData, wxArrayFileData); //---------------------------------------------------------------------------- // MultilineTextDialog : wxTextEntryDialog for multiple lines //---------------------------------------------------------------------------- class MultilineTextDialog : public wxTextEntryDialog { public: MultilineTextDialog(wxWindow *parent, const wxString& message, const wxString& caption = wxGetTextFromUserPromptStr, const wxString& value = wxEmptyString, long style = 0, const wxPoint& pos = wxDefaultPosition); }; //---------------------------------------------------------------------------- // wxFileBrowserEvent : events for the wxFileBrowser //---------------------------------------------------------------------------- // wxEVT_FILEBROWSER_FILE_SELECTED - a file has been selected (single click) // wxEVT_FILEBROWSER_FILE_ACTIVATED - a file has been double clicked or enter pressed // wxEVT_FILEBROWSER_DIR_SELECTED - a dir has been selected (single click) // wxEVT_FILEBROWSER_DIR_ACTIVATED - a dir has been double clicked or enter pressed BEGIN_DECLARE_EVENT_TYPES() DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_THINGS, wxEVT_FILEBROWSER_FILE_SELECTED, wxEVT_USER_FIRST + 1000) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_THINGS, wxEVT_FILEBROWSER_FILE_ACTIVATED, wxEVT_USER_FIRST + 1001) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_THINGS, wxEVT_FILEBROWSER_DIR_SELECTED, wxEVT_USER_FIRST + 1002) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_THINGS, wxEVT_FILEBROWSER_DIR_ACTIVATED, wxEVT_USER_FIRST + 1003) END_DECLARE_EVENT_TYPES() class WXDLLIMPEXP_THINGS wxFileBrowserEvent : public wxCommandEvent { public: wxFileBrowserEvent( wxEventType commandType = wxEVT_NULL, wxFileBrowser *fileBrowser = NULL, wxWindowID id = wxID_ANY ); wxFileBrowserEvent( const wxFileBrowserEvent &event ) : wxCommandEvent(event) {} // Get the full path + filename wxString GetFilePath() const { return GetString(); } void SetFilePath(const wxString &filepath) { SetString(filepath); } virtual wxEvent *Clone() const { return new wxFileBrowserEvent(*this); } private: DECLARE_ABSTRACT_CLASS(wxFileBrowserEvent) }; typedef void (wxEvtHandler::*wxFileBrowserEventFunction)(wxFileBrowserEvent&); #define wxFileBrowserEventHandler(func) \ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxFileBrowserEventFunction, &func) #define wx__DECLARE_FILEBROWSEREVT(evt, id, fn) wx__DECLARE_EVT1( evt, id, wxFileBrowserEventHandler(fn)) #define EVT_FILEBROWSER_FILE_SELECTED(id, fn) wx__DECLARE_FILEBROWSEREVT( wxEVT_FILEBROWSER_FILE_SELECTED, id, fn ) #define EVT_FILEBROWSER_FILE_ACTIVATED(id, fn) wx__DECLARE_FILEBROWSEREVT( wxEVT_FILEBROWSER_FILE_ACTIVATED, id, fn ) #define EVT_FILEBROWSER_DIR_SELECTED(id, fn) wx__DECLARE_FILEBROWSEREVT( wxEVT_FILEBROWSER_DIR_SELECTED, id, fn ) #define EVT_FILEBROWSER_DIR_ACTIVATED(id, fn) wx__DECLARE_FILEBROWSEREVT( wxEVT_FILEBROWSER_DIR_ACTIVATED, id, fn ) //---------------------------------------------------------------------------- // wxFileBrowser //---------------------------------------------------------------------------- enum wxFileBrowserStyles_Type { // note: these are wxListCtrl styles to allow normal wxWindow styles to work wxFILEBROWSER_TREE = wxLC_SORT_DESCENDING, // treectrl view wxFILEBROWSER_LIST = wxLC_LIST, // listctrl view wxFILEBROWSER_DETAILS = wxLC_REPORT, // listctrl details view wxFILEBROWSER_SMALL_ICON = wxLC_SMALL_ICON, // listctrl icon view wxFILEBROWSER_LARGE_ICON = wxLC_ICON, // NOT IMPL listctrl large icon wxFILEBROWSER_PREVIEW = wxLC_SORT_ASCENDING, // NOT implemented wxFILEBROWSER_SPLIT_VERTICAL = wxLC_NO_HEADER, // tree and listctrl are // split vertically else horizontal wxFILEBROWSER_SHOW_FOLDERS = wxLC_NO_SORT_HEADER, // when showing listview also show // the folders in the treectrl wxFILEBROWSER_VIEW_MASK = wxFILEBROWSER_TREE|wxFILEBROWSER_LIST|wxFILEBROWSER_DETAILS|wxFILEBROWSER_SMALL_ICON|wxFILEBROWSER_LARGE_ICON|wxFILEBROWSER_PREVIEW, wxFILEBROWSER_STYLE_MASK = wxFILEBROWSER_VIEW_MASK|wxFILEBROWSER_SPLIT_VERTICAL|wxFILEBROWSER_SHOW_FOLDERS }; class WXDLLIMPEXP_THINGS wxFileBrowser : public wxControl { public : wxFileBrowser() : wxControl() { Init(); } wxFileBrowser( wxWindow* parent, const wxWindowID id, const wxString& dir = wxDirDialogDefaultFolderStr, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxFILEBROWSER_DETAILS, const wxString& filter = wxFileSelectorDefaultWildcardStr, int defaultFilter = 0, const wxString& name = wxT("wxFileBrowser")) : wxControl() { Init(); Create(parent, id, dir, pos, size, style, filter, defaultFilter, name); } virtual ~wxFileBrowser(); bool Create( wxWindow* parent, const wxWindowID id, const wxString& dir = wxDirDialogDefaultFolderStr, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxFILEBROWSER_DETAILS, const wxString& filter = wxFileSelectorDefaultWildcardStr, int defaultFilter = 0, const wxString& name = wxT("wxFileBrowser") ); // Get the current dir (not file), optionally add a trailing platform dependent '/' or '\' wxString GetPath(bool add_wxFILE_SEP_PATH = false) const; // Go to a directory, returns sucess bool SetPath(const wxString &dirName); // go to a dir or send an EVT_FILEBROWSER_FILE_ACTIVATED if a filename bool OpenFilePath(const wxString &filePath); // Go to a higher directory, returns sucess bool CanGoUpDir() const; bool GoUpDir(); // Go to your "Home" folder "~/" in unix, "My Documents" in MSW bool GoToHomeDir(); // Go forwards and backwards through the recent dir history bool CanGoPathHistoryForward(); bool CanGoPathHistoryBackward(); bool GoPathHistoryForward(); bool GoPathHistoryBackward(); // Add a new path to the history paths at the current index void AddPathHistory(const wxString& path); // Set the file filter to one of the filter combobox items bool SetFilter(int comboItem); // Set all the file filters, deleting previous and select one bool SetFilters(const wxString &filters, int select = 0); // Add or set the file filter, "All Files (*)|*", it must have a "|" in it bool AddFilter(const wxString &filter); // Get the current file filter wxString GetFilter() const { return m_filter; } // Get the wild card used for the filter wxString GetWild() const { return m_filter.AfterLast(wxT('|')); } // Set how the files are displayed - see enum wxFileBrowserStyles_Type void SetBrowserStyle(long style); long GetBrowserStyle() const { return m_browser_style; } bool HasBrowserStyle(int style_mask) const { return (m_browser_style & style_mask) != 0; } // Show or hide hidden files void ShowHidden(bool show_hidden); bool GetShowHidden() const { return m_show_hidden; } // When showing the files in a listctrl also show the folders in the treectrl // also don't let them unsplit it void ShowFolders(bool show_folders); bool GetShowFolders() const { return HasBrowserStyle(wxFILEBROWSER_SHOW_FOLDERS); } // When splitting, split vertically or horizontally void SplitVertical(bool split_vertically); bool GetSplitVertical() const { return HasBrowserStyle(wxFILEBROWSER_SPLIT_VERTICAL); } // ----------------------------------------------------------------------- // implementation // utility function, returns the dir part of the filepath w/ trailing wxFILE_SEP_PATH bool GetPathFromFilePath(const wxString &filepath, wxString &path) const; // Delete all selected items in the wxFileCtrl bool DeleteSelectedListItems(bool ask_ok = true); // Store a list of selected items that you'll copy/cut when you paste them bool CopyCutSelectedListItems(bool copy_them); // Paste the stored CopyCutSelectedListItems - based on CopyCutSelectedListItems list bool PasteCopyCutSelectedListItems(); // Get a list of all the selected items in the list control wxArrayInt GetSelectedListItems() const; // Get the wxFileData items that are selected in the list control wxArrayFileData GetSelectedListFileData() const; // Get the currently focused list item or NULL if none selected wxFileData *GetFocusedListItem() const; // Create a wxFileData from a wxFileName wxFileData CreateFileData(const wxFileName& fileName) const; // Get the last or currently focused path + filename wxString GetLastFocusedFilePath(); // Show a simple dialog that contains the properties of the file/dir void ShowPropertiesDialog(const wxFileData &fileData) const; // returns a string with the name of a program to run the file wxString GetOpenWithFileCmd(wxFileData* fd) const; // Get a pointer to the path history combo, can change its contents wxComboBox *GetPathCombo() const { return m_pathCombo; } // Get a pointer to the filter combo // don't delete selections less than the # of filters passed in // ie. check for items with GetClientData() !NULL wxComboBox *GetFilterCombo() const { return m_filterCombo; } // Can this file be read/opened? bool CanRead(const wxString& filePath) const; // Can this file be written to, deleted, moved, cut... bool CanWrite(const wxString& filePath) const; // Update the menu/toolbar items void UpdateMenu(wxMenu *menu); void UpdateToolBar(wxToolBar *toolBar); // Update the state of the toolbar and menu items void UpdateItems(); #if wxUSE_CONFIG // Load the recent paths/filters, max = 20 void LoadConfig(wxConfigBase& config, bool paths=true, bool filters=true, const wxString &configPath = wxT("/wxFileBrowser")); // Save the recent paths, filters, if n_xxx < 0 then don't save it void SaveConfig(wxConfigBase& config, int n_paths=10, int n_filters=10, const wxString &configPath = wxT("/wxFileBrowser")); #endif // wxUSE_CONFIG protected : void OnSize( wxSizeEvent& event ); void DoSize(); virtual wxSize DoGetBestSize() const; // toolbar tools events void OnViewButtons(wxCommandEvent &event); void OnPathCombo(wxCommandEvent &event); void OnPathComboEnter(wxCommandEvent &event); void OnFilterCombo(wxCommandEvent &event); void OnFilterComboEnter(wxCommandEvent &event); // wxDirCtrl events - a wxTreeCtrl void OnTreeItemSelection(wxTreeEvent &event); void OnTreeItemActivation(wxTreeEvent &event); void OnTreeRightClick(wxTreeEvent& event); // wxFileCtrl events - a wxListCtrl void OnListColClick(wxListEvent &event); void OnListItemActivated(wxListEvent &event); void OnListItemSelected(wxListEvent &event); void OnListRightClick(wxListEvent &event); void OnTreeMenu(wxCommandEvent &event); void OnListMenu(wxCommandEvent &event); void OnIdle( wxIdleEvent &event ); //for delayed set path from combo void OnSetPath( wxCommandEvent &event ); void OnSetFilter( wxCommandEvent &event ); // (re)inserts the item at pos, deleting it if it existed after pos // keeps recent items at top bool InsertComboItem(wxComboBox *combo, const wxString &item, int pos = 0) const; // Send an event, returns false if event.Veto() called bool DoSendEvent(wxFileBrowserEvent &event) const; int FBStyleToLCStyle(int fb_style) const; // wxFileBrowserStyles_Type to wxLC_XXX int FBStyleToMenuID(int fb_style) const; // wxFileBrowserStyles_Type menu id int MenuIDToFBStyle(int menuID) const; // menu id to wxFileBrowserStyles_Type // Windows wxToolBar *m_viewToolBar; wxToolBar *m_pathToolBar; wxBitmapButton *m_viewButton; wxComboBox *m_filterCombo; wxComboBox *m_pathCombo; wxSplitterWindow *m_splitterWin; wxGenericDirCtrl *m_dirCtrl; wxFileCtrl *m_fileCtrl; wxMenu *m_listMenu; // popup menu in listctrl wxMenu *m_treeMenu; // popup menu in treectrl wxMenu *m_viewMenu; // popup menu in for changing view // data wxString m_filter; // current filter wxString m_path; // current path wxString m_lastFocusedFilePath; // path + filename of last focused item wxArrayString m_pathHistory; // recently used paths int m_path_history_index; // current index in recently used paths wxArrayFileData m_copycutFiles; // list of names when copying or cutting bool m_last_copy; // last CopyCutSelectedListItems was a copy, else cut int m_init_filters; // # of filters initially passed in bool m_ignore_tree_event; // temporarily ignore m_dirCtrl events long m_browser_style; int m_filterComboSelection; // last selection of the filter/path combo int m_pathComboSelection; bool m_show_hidden; // show hidden files private : void Init(); DECLARE_EVENT_TABLE() DECLARE_DYNAMIC_CLASS(wxFileBrowser) }; #endif // __WX_FILEBROWSER_H__ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/genergdi.h0000644000076500007650000003141311350032206020702 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: genergdi.h // Purpose: Generic gdi pen and colour // Author: John Labenski // Modified by: // Created: 12/1/2000 // Copyright: (c) John Labenski // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_GENERGDI_H_ #define _WX_GENERGDI_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "genergdi.h" #endif #include "wx/colour.h" #include "wx/pen.h" #include "wx/brush.h" #include "wx/wxthings/thingdef.h" class WXDLLIMPEXP_THINGS wxGenericColour; class WXDLLIMPEXP_THINGS wxGenericPen; class WXDLLIMPEXP_THINGS wxGenericBrush; // Uncreated and invalid versions of the generic colour, pen, and brush WXDLLIMPEXP_DATA_THINGS(extern const wxGenericColour) wxNullGenericColour; WXDLLIMPEXP_DATA_THINGS(extern const wxGenericPen) wxNullGenericPen; WXDLLIMPEXP_DATA_THINGS(extern const wxGenericBrush) wxNullGenericBrush; // Arrays of the generic colours, pens, and brushes #include "wx/dynarray.h" #ifndef WX_DECLARE_OBJARRAY_WITH_DECL // for wx2.4 backwards compatibility #define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, expmode) WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLIMPEXP_THINGS) #endif WX_DECLARE_OBJARRAY_WITH_DECL(wxGenericColour, wxArrayGenericColour, class WXDLLIMPEXP_THINGS); WX_DECLARE_OBJARRAY_WITH_DECL(wxGenericPen, wxArrayGenericPen, class WXDLLIMPEXP_THINGS); WX_DECLARE_OBJARRAY_WITH_DECL(wxGenericBrush, wxArrayGenericBrush, class WXDLLIMPEXP_THINGS); //---------------------------------------------------------------------------- // wxGenericColour - a RGBA colour that's converts from and to a wxColour. // You can have thousands of them without using up resources. (on MSW) //---------------------------------------------------------------------------- class WXDLLIMPEXP_THINGS wxGenericColour : public wxObject { public: wxGenericColour() : wxObject() {} wxGenericColour( const wxGenericColour& c ) { Create(c); } wxGenericColour( const wxColour& c ) { Create(c); } wxGenericColour( unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=255 ) : wxObject() { Create(red, green, blue, alpha); } wxGenericColour( unsigned long colABGR ) : wxObject() { CreateABGR(colABGR); } // Implicit conversion from the colour name wxGenericColour( const wxString &colourName ) : wxObject() { Create(colourName); } wxGenericColour( const char *colourName ) : wxObject() { Create(wxString::FromAscii(colourName)); } #if wxUSE_UNICODE wxGenericColour( const wxChar *colourName ) : wxObject() { Create(wxString(colourName)); } #endif virtual ~wxGenericColour() {} // Destroy the refed data void Destroy() { UnRef(); } // Is this colour valid, has refed data bool Ok() const { return m_refData != NULL; } // ----------------------------------------------------------------------- // (re)Create this colour, unrefing this colour first. // Use these to detach this colour from it's refed copies. void Create( const wxGenericColour& c ); void Create( const wxColour& c); void Create( unsigned char red = 0, unsigned char green = 0, unsigned char blue = 0, unsigned char alpha=255 ); void CreateABGR( unsigned long colABGR ); void CreateARGB( unsigned long colARGB ); void Create( const wxString& colourName ); // ----------------------------------------------------------------------- // Set the colour values of the refed data. // Use these to adjust the values of all the refed copies. void Set( const wxGenericColour &c ); void Set( const wxColour& c ); void Set( unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=255 ); void SetABGR( unsigned long colABGR ); void SetARGB( unsigned long colARGB ); void Set( const wxString& colourName ); void SetRed ( unsigned char r ); void SetGreen( unsigned char g ); void SetBlue ( unsigned char b ); void SetAlpha( unsigned char a ); // ----------------------------------------------------------------------- // Get the colour values inline wxColour GetColour() const { return wxColour(GetRed(), GetGreen(), GetBlue()); } unsigned char GetRed() const; unsigned char GetGreen() const; unsigned char GetBlue() const; unsigned char GetAlpha() const; // wxWidgets wxColour compatibility functions unsigned char Red() const { return GetRed(); } unsigned char Green() const { return GetGreen(); } unsigned char Blue() const { return GetBlue(); } unsigned char Alpha() const { return GetAlpha(); } // ----------------------------------------------------------------------- // Equivalency tests bool IsSameAs( const wxGenericColour& c ) const; bool IsSameAs( const wxColour& c ) const; // Get a "hot to cold" colour where i ranges from 0 to 255 wxGenericColour GetHotColdColour(double i) const; // Read colour to and from string //wxString WriteString(const wxString& format = wxT("%d,%d,%d,%d")) const; //bool ReadString(const wxString& str, const wxString& format = wxT("%d,%d,%d,%d")); // operators bool operator == (const wxGenericColour& c) const { return m_refData == c.m_refData; } bool operator != (const wxGenericColour& c) const { return m_refData != c.m_refData; } wxGenericColour& operator = (const wxGenericColour& c) { if ( (*this) != c ) Ref(c); return *this; } wxGenericColour& operator = ( const wxColour& c ) { Create(c); return *this; } private: // ref counting code virtual wxObjectRefData *CreateRefData() const; virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; DECLARE_DYNAMIC_CLASS(wxGenericColour) }; //---------------------------------------------------------------------------- // wxGenericPen - a pen structure that converts to and from wxPen // You can have thousands of them without using up resources. (on MSW) //---------------------------------------------------------------------------- class WXDLLIMPEXP_THINGS wxGenericPen : public wxObject { public: wxGenericPen() : wxObject() {} wxGenericPen( const wxGenericPen &pen ) : wxObject() { Create(pen); } wxGenericPen( const wxPen &pen ) : wxObject() { Create(pen); } wxGenericPen( const wxGenericColour &colour, int width = 1, int style = wxSOLID, int cap = wxCAP_ROUND, int join = wxJOIN_ROUND ) : wxObject() { Create(colour, width, style, cap, join); } wxGenericPen( const wxColour &colour, int width = 1, int style = wxSOLID, int cap = wxCAP_ROUND, int join = wxJOIN_ROUND ) : wxObject() { Create(colour, width, style, cap, join); } virtual ~wxGenericPen() {} // Destroy the refed data void Destroy() { UnRef(); } // Is this colour valid, has refed data bool Ok() const { return m_refData != NULL; } // ----------------------------------------------------------------------- // (re)Create this pen, unrefing this pen first. // Use these to detach this pen from it's refed copies. void Create( const wxGenericPen &pen ); void Create( const wxPen &pen ); void Create( const wxGenericColour &colour, int width = 1, int style = wxSOLID, int cap = wxCAP_ROUND, int join = wxJOIN_ROUND ); void Create( const wxColour &colour, int width = 1, int style = wxSOLID, int cap = wxCAP_ROUND, int join = wxJOIN_ROUND ); // ----------------------------------------------------------------------- // Set the values of the refed data. // Use these to adjust the values of all the refed copies. void Set( const wxGenericPen& pen ); void Set( const wxPen& pen ); void SetColour( const wxGenericColour &colour ); void SetColour( const wxColour &colour ); void SetColour( int red, int green, int blue, int alpha=255 ); void SetCap( int capStyle ); void SetJoin( int joinStyle ); void SetStyle( int style ); void SetWidth( int width ); void SetDashes( int number_of_dashes, const wxDash *dash ); // ----------------------------------------------------------------------- // Get the pen values wxPen GetPen() const; wxGenericColour GetGenericColour() const; wxColour GetColour() const; int GetWidth() const; int GetStyle() const; int GetCap() const; int GetJoin() const; int GetDashes(wxDash **ptr) const; int GetDashCount() const; wxDash* GetDash() const; // ----------------------------------------------------------------------- // Equivalency tests bool IsSameAs(const wxGenericPen& pen) const; bool IsSameAs(const wxPen& pen) const; // Read pen to and from string //wxString WriteString() const; //bool ReadString(const wxString& str); // operators bool operator == (const wxGenericPen& pen) const { return m_refData == pen.m_refData; } bool operator != (const wxGenericPen& pen) const { return m_refData != pen.m_refData; } wxGenericPen& operator = (const wxGenericPen& pen) { if ( (*this) != pen ) Ref(pen); return *this; } wxGenericPen& operator = ( const wxPen& pen ) { Create(pen); return *this; } private: // ref counting code virtual wxObjectRefData *CreateRefData() const; virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; DECLARE_DYNAMIC_CLASS(wxGenericPen) }; //---------------------------------------------------------------------------- // wxGenericBrush - a brush structure that converts to and from wxBrush // You can have thousands of them without using up resources. (on MSW) //---------------------------------------------------------------------------- class WXDLLIMPEXP_THINGS wxGenericBrush : public wxObject { public: wxGenericBrush() : wxObject() {} wxGenericBrush( const wxGenericBrush &brush ) : wxObject() { Create(brush); } wxGenericBrush( const wxBrush &brush ) : wxObject() { Create(brush); } wxGenericBrush( const wxGenericColour &colour, int style = wxSOLID) : wxObject() { Create(colour, style); } wxGenericBrush( const wxColour &colour, int style = wxSOLID) : wxObject() { Create(colour, style); } wxGenericBrush( const wxBitmap& stipple ) : wxObject() { Create(stipple); } virtual ~wxGenericBrush() {} // Destroy the refed data void Destroy() { UnRef(); } // Is this colour valid, has refed data bool Ok() const { return m_refData != NULL; } // ----------------------------------------------------------------------- // (re)Create this brush, unrefing this pen first. // Use these to detach this pen from it's refed copies. void Create( const wxGenericBrush &brush ); void Create( const wxBrush &brush ); void Create( const wxGenericColour &colour, int style = wxSOLID ); void Create( const wxColour &colour, int style = wxSOLID ); void Create( const wxBitmap &stipple ); // ----------------------------------------------------------------------- // Set the values of the refed data. // Use these to adjust the values of all the refed copies. void Set( const wxGenericBrush& brush ); void Set( const wxBrush& brush ); void SetColour( const wxGenericColour &colour ); void SetColour( const wxColour &colour ); void SetColour( int red, int green, int blue, int alpha=255 ); void SetStyle( int style ); void SetStipple( const wxBitmap& stipple ); // ----------------------------------------------------------------------- // Get the brush values wxBrush GetBrush() const; wxGenericColour GetGenericColour() const; wxColour GetColour() const; int GetStyle() const; wxBitmap* GetStipple() const; bool IsHatch() const { return (GetStyle()>=wxFIRST_HATCH) && (GetStyle()<=wxLAST_HATCH); } // ----------------------------------------------------------------------- // Equivalency tests bool IsSameAs(const wxGenericBrush& brush) const; bool IsSameAs(const wxBrush& brush) const; // operators bool operator == (const wxGenericBrush& brush) const { return m_refData == brush.m_refData; } bool operator != (const wxGenericBrush& brush) const { return m_refData != brush.m_refData; } wxGenericBrush& operator = (const wxGenericBrush& brush) { if ( (*this) != brush ) Ref(brush); return *this; } wxGenericBrush& operator = ( const wxBrush& brush ) { Create(brush); return *this; } private: // ref counting code virtual wxObjectRefData *CreateRefData() const; virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; DECLARE_DYNAMIC_CLASS(wxGenericBrush) }; #endif // _WX_GENERGDI_H_ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/geometry.h0000644000076500007650000005645111350032206020762 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: geometry.h // Purpose: Additional geometry functions for wxWidgets (see wx/geometry.h) // Author: John Labenski // Created: 07/01/02 // Copyright: John Labenski, 2002 // License: wxWidgets v2 /////////////////////////////////////////////////////////////////////////////// #ifndef __WXIMAGER_GEOMETRY_H__ #define __WXIMAGER_GEOMETRY_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "geometry.h" #endif #include "wx/wxthings/thingdef.h" #include "wx/geometry.h" #define wxGEOMETRY_INF 1E100 //----------------------------------------------------------------------------- // wxRay2DDouble uses point slope line format // // y = mx+b, m=(x-x0)/(y-y0) //----------------------------------------------------------------------------- class WXDLLEXPORT wxRay2DDouble : public wxPoint2DDouble { public : inline wxRay2DDouble(wxDouble x=0, wxDouble y=0, wxDouble slope=0) { m_x = x; m_y = y; m_slope = slope; } inline wxRay2DDouble(const wxPoint2DDouble &pt, wxDouble slope) { m_x = pt.m_x; m_y = pt.m_y; m_slope = slope; } inline wxRay2DDouble(wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2) { m_x = x1; m_y = y1; m_slope = GetSlope(x1, y1, x2, y2); } inline wxRay2DDouble(const wxPoint2DDouble &pt1, const wxPoint2DDouble &pt2) { m_x = pt1.m_x; m_y = pt1.m_y; m_slope = GetSlope(pt1, pt2); } inline wxRay2DDouble(const wxRay2DDouble &line) { m_x = line.m_x; m_y = line.m_y; m_slope = line.m_slope; } inline wxDouble GetX() const { return m_x; } inline wxDouble GetY() const { return m_y; } inline wxPoint2DDouble GetPoint() const { return (wxPoint2DDouble)(*this); } inline wxDouble GetSlope() const { return m_slope; } inline void SetX(wxDouble x) { m_x = x; } inline void SetY(wxDouble y) { m_y = y; } inline void SetPoint(const wxPoint2DDouble &pt ) { m_x = pt.m_x; m_y = pt.m_y; } inline void SetSlope(wxDouble slope) { m_slope = slope; } inline wxDouble GetYFromX(wxDouble x) const {return m_slope*(x-m_x) + m_y;} inline wxDouble GetXFromY(wxDouble y) const {return (y-m_y)/m_slope + m_x;} // Get a point along the line at pos x or y inline wxPoint2DDouble GetPointOnRayFromX(wxDouble x) const { return wxPoint2DDouble(x, GetYFromX(x)); } inline wxPoint2DDouble GetPointOnRayFromY(wxDouble y) const { if (m_slope == 0) return (*this); return wxPoint2DDouble(GetXFromY(y), y); } // Translate the point m_pt along the line to pos x or y inline void TranslatePointByX(wxDouble x) { m_y = GetYFromX(x); m_x = x; } inline void TranslatePointByY(wxDouble y) { m_x = GetXFromY(y); m_y = y; } inline wxRay2DDouble GetTranslatedLineByX(wxDouble x) const { return wxRay2DDouble(x, GetYFromX(x), m_slope); } inline wxRay2DDouble GetTranslatedLineByY(wxDouble y) const { return wxRay2DDouble(GetXFromY(y), y, m_slope); } inline wxDouble GetDistanceToPoint(const wxPoint2DDouble &pt, wxPoint2DDouble *closestPt=NULL) const { wxPoint2DDouble l1(m_x, m_y); wxPoint2DDouble l2(GetPointOnRayFromX(m_x+pt.m_x)); wxPoint2DDouble v = l2 - l1; wxPoint2DDouble w = pt - l1; wxDouble c1 = w.GetDotProduct(v); wxDouble c2 = v.GetDotProduct(v); wxDouble b = c1 / c2; wxPoint2DDouble pb = l1 + b*v; if (closestPt) *closestPt = pb; return pb.GetDistance( pt ); /* wxPoint2DDouble ll2 = l2; double l = ll2.GetDistanceSquare(l1); double u = ((p.m_x-l1.m_x)*(l2.m_x-l1.m_x)+(p.m_y-l1.m_y)*(l2.m_y-l1.m_y))/l; wxPoint2DDouble i = l1 + u*(l2-l1); //printf("distance %.9lf %.9lf %d\n\n", i.GetDistance(p), pb.GetDistance(p), int(pb==i)); */ // this x for y on this line // y(on this line) = m_slope*(x-m_pt.m_x) + m_pt.m_y // = (-1/m_slope)(x-pt.m_x) + pt.m_y // so // x(on this line) = (y-m_pt.m_y)/m_slope + m_pt.m_x // = (y-pt.m_y)/(-1/m_slope) + m_pt.m_x //(y-m_pt.m_y)/m_slope + m_pt.m_x = (y-pt.m_y)(-1/m_slope) + m_pt.m_x //(y-m_pt.m_y)/m_slope - m_slope*(y-pt.m_y) = + m_pt.m_x - m_pt.m_x //y*(1/m_slope - m_slope) = + m_pt.m_x - m_pt.m_x +m_slope*pt.m_y + m_slope*m_pt.m_y //y = (m_pt.m_x - m_pt.m_x +m_slope*pt.m_y + m_slope*m_pt.m_y)/(1/m_slope - m_slope) /* wxDouble x = (m_x + m_slope*m_slope*m_x - m_slope*(m_y - m_y))/(m_slope*m_slope+1.0); wxPoint2DDouble pl(x, m_slope*(x-m_x) + m_y); if (closestPt) *closestPt = pl; return pl.GetDistance(pt); */ } inline wxDouble GetDistanceToRay( const wxRay2DDouble &ray ) const { // FIXME - unchecked, just quickly translated from some other code if (m_slope != ray.m_slope) return 0; if (m_slope == 0) return fabs(m_y - ray.m_y); wxPoint2DDouble p1 = GetPointOnRayFromX(0); wxPoint2DDouble p2 = ray.GetPointOnRayFromX(0); // y = (-1/s1)*x+p1.m_y = s2*x + p2.m_y wxDouble dx = (p1.m_y - p2.m_y)/(m_slope + (1.0/m_slope)); wxDouble dy = (m_slope*dx+p2.m_y) - p1.m_y; return sqrt(dx*dx + dy*dy); } inline static wxDouble GetSlope(wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2) { return (y2 - y1)/(x2 - x1); } inline static wxDouble GetSlope(const wxPoint2DDouble &pt1, const wxPoint2DDouble &pt2) { return (pt2.m_y-pt1.m_y)/(pt2.m_x-pt1.m_x); } // find the point where the two rays meet, return false if parallel bool Intersect(const wxRay2DDouble& other, wxPoint2DDouble& pt) const { // (y1-y0)/(x1-x0)=m for both lines, equate y1's first if (m_slope == other.m_slope) return false; pt.m_x = (m_slope*m_x - other.m_slope*other.m_x + other.m_y - m_y)/(m_slope - other.m_slope); pt.m_y = GetYFromX(pt.m_x); return true; } // Operators inline wxRay2DDouble operator=(const wxRay2DDouble& r) { m_x = r.m_x; m_y = r.m_y; m_slope = r.m_slope; return *this; } inline bool operator==(const wxRay2DDouble& r) const { return (m_x == r.m_x)&&(m_y == r.m_y)&&(m_slope == r.m_slope); } inline bool operator!=(const wxRay2DDouble& r) const { return !(*this == r); } inline wxRay2DDouble operator+(const wxPoint2DDouble& rel_pos) const { return wxRay2DDouble(m_x+rel_pos.m_x, m_y+rel_pos.m_y, m_slope); } inline wxRay2DDouble operator-(const wxPoint2DDouble& rel_pos) const { return wxRay2DDouble(m_x-rel_pos.m_x, m_y-rel_pos.m_y, m_slope); } inline wxRay2DDouble operator*(const wxPoint2DDouble& rel_pos) const { return wxRay2DDouble(m_x*rel_pos.m_x, m_y*rel_pos.m_y, m_slope); } inline wxRay2DDouble operator/(const wxPoint2DDouble& rel_pos) const { return wxRay2DDouble(m_x/rel_pos.m_x, m_y/rel_pos.m_y, m_slope); } inline wxRay2DDouble& operator+=(const wxPoint2DDouble& rel_pos) { m_x += rel_pos.m_x; m_y += rel_pos.m_y; return *this; } inline wxRay2DDouble& operator-=(const wxPoint2DDouble& rel_pos) { m_x -= rel_pos.m_x; m_y -= rel_pos.m_y; return *this; } inline wxRay2DDouble& operator*=(const wxPoint2DDouble& rel_pos) { m_x *= rel_pos.m_x; m_y *= rel_pos.m_y; return *this; } inline wxRay2DDouble& operator/=(const wxPoint2DDouble& rel_pos) { m_x /= rel_pos.m_x; m_y /= rel_pos.m_y; return *this; } inline wxRay2DDouble operator+(const wxDouble& rel_slope) const { return wxRay2DDouble(m_x, m_y, m_slope+rel_slope); } inline wxRay2DDouble operator-(const wxDouble& rel_slope) const { return wxRay2DDouble(m_x, m_y, m_slope-rel_slope); } inline wxRay2DDouble operator*(const wxDouble& rel_slope) const { return wxRay2DDouble(m_x, m_y, m_slope*rel_slope); } inline wxRay2DDouble operator/(const wxDouble& rel_slope) const { return wxRay2DDouble(m_x, m_y, m_slope/rel_slope); } inline wxRay2DDouble& operator+=(const wxDouble& rel_slope) { m_slope += rel_slope; return *this; } inline wxRay2DDouble& operator-=(const wxDouble& rel_slope) { m_slope -= rel_slope; return *this; } inline wxRay2DDouble& operator*=(const wxDouble& rel_slope) { m_slope *= rel_slope; return *this; } inline wxRay2DDouble& operator/=(const wxDouble& rel_slope) { m_slope /= rel_slope; return *this; } wxDouble m_slope; }; //----------------------------------------------------------------------------- // wxLine2DInt uses point slope line format // // y = mx+b, m=(x-x0)/(y-y0) //----------------------------------------------------------------------------- /* class WXDLLEXPORT wxLine2DInt : wxRect2DInt { public : inline wxLine2DInt(wxInt32 x1=0, wxInt32 y1=0, wxInt32 x2=0, wxInt32 y2=0) { m_x = x1; m_y = y1; m_width = x2 - x1; m_height = y2 - y1; } inline wxLine2DInt(const wxPoint2DInt &pt1, const wxPoint2DInt &pt2) { m_x = pt1.m_x; m_y = pt1.m_y; m_width = pt2.m_x - pt1.m_x; m_height = pt2.m_y - pt1.m_y; } inline wxLine2DInt(const wxLine2DInt &line) { m_x = line.m_x; m_y = line.m_y; m_width = line.m_width; m_height = line.m_height; } inline wxInt32 GetX1() const { return m_x; } inline wxInt32 GetY1() const { return m_y; } inline wxInt32 GetX2() const { return m_x + m_width; } inline wxInt32 GetY2() const { return m_y + m_height; } inline wxPoint2DInt Get1Point() const { return GetTopLeft(); } inline wxPoint2DInt Get2Point() const { return GetBottomRight(); } inline wxDouble GetSlope() const { return wxDouble(m_height)/wxDouble(m_width); } inline void SetX1(wxInt32 x) { m_x = x; } inline void SetY1(wxInt32 y) { m_y = y; } inline void SetX2(wxInt32 x) { m_width = m_x - x; } inline void SetY2(wxInt32 y) { m_height = m_y - y; } inline void SetPoint1(const wxPoint2DInt &pt ) { SetTopLeft(pt); } inline void SetPoint2(const wxPoint2DInt &pt ) { SetBottomRight(pt); } inline wxDouble GetYFromX(wxDouble x) const {return (wxDouble(m_height)/m_width)*(x-m_x) + m_y;} inline wxDouble GetXFromY(wxDouble y) const {return (y-m_y)*(wxDouble(m_height)/m_width) + m_x;} // Get a point along the line at pos x or y inline wxPoint2DInt GetPointOnLineFromX(wxInt32 x) const { return wxPoint2DInt(x, GetYFromX(x)); } inline wxPoint2DInt GetPointOnLineFromY(wxInt32 y) const { return wxPoint2DInt(GetXFromY(y), y); } // Translate the point m_pt along the line to pos x or y inline void TranslatePointByX(wxDouble x) { m_pt.m_y = GetYFromX(x); m_pt.m_x = x; } inline void TranslatePointByY(wxDouble y) { m_pt.m_x = GetXFromY(y); m_pt.m_y = y; } inline wxLine2DInt GetTranslatedLineByX(wxDouble x) { return wxLine2DInt(x, GetYFromX(x), m_slope); } inline wxLine2DInt GetTranslatedLineByY(wxDouble y) { return wxLine2DInt(GetXFromY(y), y, m_slope); } inline wxDouble GetDistanceToPoint(const wxPoint2DDouble &pt, wxPoint2DDouble *closestPt=NULL) const { wxPoint2DDouble l1(m_pt); wxPoint2DDouble l2(GetPointOnLineFromX(m_pt.m_x+pt.m_x)); wxPoint2DDouble v = l2 - l1; wxPoint2DDouble w = pt - l1; double c1 = w.GetDotProduct(v); double c2 = v.GetDotProduct(v); double b = c1 / c2; wxPoint2DDouble pb = l1 + b*v; if (closestPt) *closestPt = pb; return pb.GetDistance( pt ); } inline static wxDouble GetSlope(wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2) { return (y2 - y1)/(x2 - x1); } inline static wxDouble GetSlope(const wxPoint2DDouble &pt1, const wxPoint2DDouble &pt2) { return (pt2.m_y-pt1.m_y)/(pt2.m_x-pt1.m_x); } // Default copy operator is ok wxPoint2DDouble m_pt; wxDouble m_slope; }; */ //----------------------------------------------------------------------------- // wxCircleDouble m_r*m_r = (x-m_origin.m_x)^2 + (y-m_origin.m_y)^2 //----------------------------------------------------------------------------- class WXDLLIMPEXP_THINGS wxCircleDouble : public wxPoint2DDouble { public : inline wxCircleDouble(const wxCircleDouble &circle) { m_x = circle.m_x; m_y = circle.m_y; m_r = circle.m_r; } inline wxCircleDouble(wxDouble x=0, wxDouble y=0, wxDouble r=0) { m_x = x; m_y = y; m_r = r; } inline wxCircleDouble(const wxPoint2DDouble &origin, wxDouble r) { m_x = origin.m_x; m_y = origin.m_y; m_r = r; } inline wxCircleDouble(const wxPoint2DDouble &p1, const wxPoint2DDouble &p2, const wxPoint2DDouble &p3); inline bool IsEmpty() const { return m_r <= 0; } inline wxDouble GetX() const { return m_x; } inline wxDouble GetY() const { return m_y; } inline wxPoint2DDouble GetOrigin() const { return wxPoint2DDouble(m_x, m_y); } inline wxDouble GetRadius() const { return m_r; } // Get a bounding rect inline wxRect2DDouble GetRect() const { return wxRect2DDouble(m_x-m_r, m_y-m_r, 2.0*m_r, 2.0*m_r); } inline void SetX(wxDouble x) { m_x = x; } inline void SetY(wxDouble y) { m_y = y; } inline void SetOrigin(const wxPoint2DDouble &origin) { m_x = origin.m_x; m_y = origin.m_y; } inline void SetRadius(wxDouble r) { m_r = r; } inline bool GetPointInCircle(wxDouble x, wxDouble y) const { if (IsEmpty()) return false; return ((x-m_x)*(x-m_x) + (y-m_y)*(y-m_y) <= m_r*m_r); } inline bool GetPointInCircle(const wxPoint2DDouble &pt) const { return GetPointInCircle(pt.m_x, pt.m_y); } inline bool Intersects(const wxCircleDouble &circle) const { return GetDistance(circle) <= m_r + circle.m_r; } int IntersectLine( const wxRay2DDouble &line, wxPoint2DDouble *pt1=NULL, wxPoint2DDouble *pt2=NULL ) const; // Operators inline wxCircleDouble operator=(const wxCircleDouble& c) { m_x = c.m_x; m_y = c.m_y; m_r = c.m_r; return *this; } inline bool operator==(const wxCircleDouble& c) const { return (m_x == c.m_x)&&(m_y == c.m_y)&&(m_r == c.m_r); } inline bool operator!=(const wxCircleDouble& c) const { return !(*this == c); } inline wxCircleDouble operator+(const wxPoint2DDouble& rel_origin) const { return wxCircleDouble(m_x+rel_origin.m_x, m_y+rel_origin.m_y, m_r); } inline wxCircleDouble operator-(const wxPoint2DDouble& rel_origin) const { return wxCircleDouble(m_x-rel_origin.m_x, m_y-rel_origin.m_y, m_r); } inline wxCircleDouble operator*(const wxPoint2DDouble& rel_origin) const { return wxCircleDouble(m_x*rel_origin.m_x, m_y*rel_origin.m_y, m_r); } inline wxCircleDouble operator/(const wxPoint2DDouble& rel_origin) const { return wxCircleDouble(m_x/rel_origin.m_x, m_y/rel_origin.m_y, m_r); } inline wxCircleDouble& operator+=(const wxPoint2DDouble& rel_origin) { m_x += rel_origin.m_x; m_y += rel_origin.m_y; return *this; } inline wxCircleDouble& operator-=(const wxPoint2DDouble& rel_origin) { m_x -= rel_origin.m_x; m_y -= rel_origin.m_y; return *this; } inline wxCircleDouble& operator*=(const wxPoint2DDouble& rel_origin) { m_x *= rel_origin.m_x; m_y *= rel_origin.m_y; return *this; } inline wxCircleDouble& operator/=(const wxPoint2DDouble& rel_origin) { m_x /= rel_origin.m_x; m_y /= rel_origin.m_y; return *this; } inline wxCircleDouble operator+(const wxDouble& rel_radius) const { return wxCircleDouble(m_x, m_y, m_r+rel_radius); } inline wxCircleDouble operator-(const wxDouble& rel_radius) const { return wxCircleDouble(m_x, m_y, m_r-rel_radius); } inline wxCircleDouble operator*(const wxDouble& rel_radius) const { return wxCircleDouble(m_x, m_y, m_r*rel_radius); } inline wxCircleDouble operator/(const wxDouble& rel_radius) const { return wxCircleDouble(m_x, m_y, m_r/rel_radius); } inline wxCircleDouble& operator+=(const wxDouble& rel_radius) { m_r += rel_radius; return *this; } inline wxCircleDouble& operator-=(const wxDouble& rel_radius) { m_r -= rel_radius; return *this; } inline wxCircleDouble& operator*=(const wxDouble& rel_radius) { m_r *= rel_radius; return *this; } inline wxCircleDouble& operator/=(const wxDouble& rel_radius) { m_r /= rel_radius; return *this; } wxDouble m_r; }; //----------------------------------------------------------------------------- // wxCircleInt m_r*m_r = (x-m_origin.m_x)^2 + (y-m_origin.m_y)^2 //----------------------------------------------------------------------------- class WXDLLEXPORT wxCircleInt : public wxPoint2DInt { public : inline wxCircleInt(wxInt32 x=0, wxInt32 y=0, wxInt32 r=0) { m_x = x; m_y = y; m_r = r; } inline wxCircleInt(const wxPoint2DInt &origin, wxInt32 r) { m_x = origin.m_x; m_y = origin.m_y; m_r = r; } inline wxCircleInt(const wxCircleInt &circle) { m_x = circle.m_x; m_y = circle.m_y; m_r = circle.m_r; } inline bool IsEmpty() const { return m_r <= 0; } inline wxInt32 GetX() const { return m_x; } inline wxInt32 GetY() const { return m_y; } inline wxPoint2DInt GetOrigin() const { return wxPoint2DInt(m_x, m_y); } inline wxInt32 GetRadius() const { return m_r; } // Get a bounding rect inline wxRect2DInt GetRect() const { return wxRect2DInt(m_x-m_r, m_y-m_r, 2*m_r, 2*m_r); } inline void SetX(wxInt32 x) { m_x = x; } inline void SetY(wxInt32 y) { m_y = y; } inline void SetOrigin(const wxPoint2DInt &origin) { m_x = origin.m_x; m_y = origin.m_y; } inline void SetRadius(wxInt32 r) { m_r = r; } inline bool GetPointInCircle(wxInt32 x, wxInt32 y) const { if (IsEmpty()) return false; return ((x-m_x)*(x-m_x) + (y-m_y)*(y-m_y) <= m_r*m_r); } inline bool GetPointInCircle(const wxPoint2DInt &pt) const { return GetPointInCircle(pt.m_x, pt.m_y); } inline bool Intersects(const wxCircleInt &circle) const { return GetDistance(circle) <= m_r + circle.m_r; } // int IntersectLine( const wxRay2DDouble &line, // wxPoint2DInt *pt1=NULL, // wxPoint2DInt *pt2=NULL ) const; // Operators inline wxCircleInt operator=(const wxCircleInt& c) { m_x = c.m_x; m_y = c.m_y; m_r = c.m_r; return *this; } inline bool operator==(const wxCircleInt& c) const { return (m_x == c.m_x)&&(m_y == c.m_y)&&(m_r == c.m_r); } inline bool operator!=(const wxCircleInt& c) const { return !(*this == c); } inline wxCircleInt operator+(const wxPoint2DInt& rel_origin) const { return wxCircleInt(m_x+rel_origin.m_x, m_y+rel_origin.m_y, m_r); } inline wxCircleInt operator-(const wxPoint2DInt& rel_origin) const { return wxCircleInt(m_x-rel_origin.m_x, m_y-rel_origin.m_y, m_r); } inline wxCircleInt operator*(const wxPoint2DInt& rel_origin) const { return wxCircleInt(m_x*rel_origin.m_x, m_y*rel_origin.m_y, m_r); } inline wxCircleInt operator/(const wxPoint2DInt& rel_origin) const { return wxCircleInt(m_x/rel_origin.m_x, m_y/rel_origin.m_y, m_r); } inline wxCircleInt& operator+=(const wxPoint2DInt& rel_origin) { m_x += rel_origin.m_x; m_y += rel_origin.m_y; return *this; } inline wxCircleInt& operator-=(const wxPoint2DInt& rel_origin) { m_x -= rel_origin.m_x; m_y -= rel_origin.m_y; return *this; } inline wxCircleInt& operator*=(const wxPoint2DInt& rel_origin) { m_x *= rel_origin.m_x; m_y *= rel_origin.m_y; return *this; } inline wxCircleInt& operator/=(const wxPoint2DInt& rel_origin) { m_x /= rel_origin.m_x; m_y /= rel_origin.m_y; return *this; } inline wxCircleInt operator+(const wxInt32& rel_radius) const { return wxCircleInt(m_x, m_y, m_r+rel_radius); } inline wxCircleInt operator-(const wxInt32& rel_radius) const { return wxCircleInt(m_x, m_y, m_r-rel_radius); } inline wxCircleInt operator*(const wxInt32& rel_radius) const { return wxCircleInt(m_x, m_y, m_r*rel_radius); } inline wxCircleInt operator/(const wxInt32& rel_radius) const { return wxCircleInt(m_x, m_y, m_r/rel_radius); } inline wxCircleInt& operator+=(const wxInt32& rel_radius) { m_r += rel_radius; return *this; } inline wxCircleInt& operator-=(const wxInt32& rel_radius) { m_r -= rel_radius; return *this; } inline wxCircleInt& operator*=(const wxInt32& rel_radius) { m_r *= rel_radius; return *this; } inline wxCircleInt& operator/=(const wxInt32& rel_radius) { m_r /= rel_radius; return *this; } wxInt32 m_r; }; //----------------------------------------------------------------------------- // wxEllipseInt m_r*m_r = (x-m_origin.m_x)^2 + (y-m_origin.m_y)^2 //----------------------------------------------------------------------------- class WXDLLEXPORT wxEllipseInt { public : inline wxEllipseInt(wxInt32 x=0, wxInt32 y=0, wxInt32 r_x=0, wxInt32 r_y=0) { m_origin.m_x=x; m_origin.m_y=y; m_radius.m_x=r_x; m_radius.m_y=r_y; } inline wxEllipseInt(const wxPoint2DInt &origin, const wxPoint2DInt radius) { m_origin = origin; m_radius = radius; } inline wxEllipseInt(const wxEllipseInt &ellipse) { m_origin = ellipse.m_origin; m_radius = ellipse.m_radius; } inline bool IsEmpty() const { return m_radius.m_x<=0 || m_radius.m_y<=0; } inline wxInt32 GetX() const { return m_origin.m_x; } inline wxInt32 GetY() const { return m_origin.m_y; } inline wxPoint2DInt GetOrigin() const { return m_origin; } inline wxInt32 GetXRadius() const { return m_radius.m_x; } inline wxInt32 GetYRadius() const { return m_radius.m_y; } inline wxPoint2DInt GetRadius() const { return m_radius; } // Get a bounding rect inline wxRect2DInt GetRect() const { return wxRect2DInt(m_origin.m_x-m_radius.m_x, m_origin.m_y-m_radius.m_y, 2*m_radius.m_x, 2*m_radius.m_y); } inline void SetX(wxInt32 x) { m_origin.m_x = x; } inline void SetY(wxInt32 y) { m_origin.m_y = y; } inline void SetOrigin(const wxPoint2DInt &origin) { m_origin = origin; } inline void SetXRadius(wxInt32 r_x) { m_radius.m_x = r_x; } inline void SetYRadius(wxInt32 r_y) { m_radius.m_y = r_y; } inline void SetRadius(const wxPoint2DInt &radius) { m_radius = radius; } inline bool GetPointInEllipse(wxInt32 x, wxInt32 y) const { if (IsEmpty()) return false; return (((x-m_origin.m_x)*(x-m_origin.m_x))/m_radius.m_x + ((y-m_origin.m_y)*(y-m_origin.m_y))/m_radius.m_y <= 1); } inline bool GetPointInEllipse(const wxPoint2DInt &pt) const { return GetPointInEllipse(pt.m_x, pt.m_y); } // int IntersectLine( const wxRay2DDouble &line, // wxPoint2DInt *pt1=NULL, // wxPoint2DInt *pt2=NULL ) const; inline bool operator==(const wxEllipseInt& c) const { return (m_origin == c.m_origin)&&(m_radius == c.m_radius); } inline bool operator!=(const wxEllipseInt& c) const { return !(*this == c); } inline wxEllipseInt operator+(const wxPoint2DInt& rel_origin) const { return wxEllipseInt(m_origin+rel_origin, m_radius); } inline wxEllipseInt& operator+=(const wxPoint2DInt& rel_origin) { m_origin += rel_origin; return *this; } inline wxEllipseInt operator-(const wxPoint2DInt& rel_origin) const { return wxEllipseInt(m_origin-rel_origin, m_radius); } inline wxEllipseInt& operator-=(const wxPoint2DInt& rel_origin) { m_origin -= rel_origin; return *this; } wxPoint2DInt m_radius; wxPoint2DInt m_origin; }; #endif // __WXIMAGER_GEOMETRY_H__ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/medsort.h0000644000076500007650000006105511350032206020600 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: medsort.h // Purpose: Macros of generic public domain median sorting algorithms // Author: John Labenski & mostly others // Created: 07/01/02 // Copyright: see macro headers, rewritten by John Labenski, 2002 // License: Public Domain ///////////////////////////////////////////////////////////////////////////// #ifndef __WX_MEDSORT_H__ #define __WX_MEDSORT_H__ /* Notes : code taken from http://ndevilla.free.fr/median/ see the headers for each function taken from the files see bottom for benchmark data Each of these functions are implemented as macros that can be used to either DECLARE and DEFINE functions for the different element types required or they can be used inline for example: in a header file declare the function with DECLARE_WIRTHS_MEDIAN( wirths_median_int, int ) and you'll get this code int wirths_median_int( int *arr, int n, int &median ); in the c(pp) file define the function DEFINE_WIRTHS_MEDIAN( wirths_median_int, int ) and get int withs_median_int( int *arr, int n, int &median ) { the function itself } otherwise use the macro inline in some other function IMPLEMENT_WIRTHS_MEDIAN(int, arr, n, &median) */ /*--------------------------------------------------------------------------- * This Quickselect routine is based on the algorithm described in * "Numerical recipes in C", Second Edition, * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 * This code by Nicolas Devillard - 1998. Public domain. ---------------------------------------------------------------------------- This does NOT fully sort the input array, but it does modify it QUICK_SELECT(elem_type, arr, n, median) elem_type is a valid data type, int, long, unsigned char, float... arr is an array delcared as elem_type *array and passed as array n is the size of the array, ie. total element count median contains the median value on exit ---------------------------------------------------------------------------*/ #define DECLARE_QUICK_SELECT( name, elem_type ) \ elem_type name( elem_type *arr, int n, elem_type &median ); #define DEFINE_QUICK_SELECT( name, elem_type ) \ elem_type name( elem_type *arr, int n, elem_type &median ) \ IMPLEMENT_QUICK_SELECT( elem_type, arr, n, median ) #define IMPLEMENT_QUICK_SELECT(elem_type, arr, n, median) \ { \ int low=0, high=n-1, half=(low+high)/2, middle, ll, hh; \ \ for (;;) { \ if (high <= low) /* One element only */ \ break; /*return arr[half] ; */ \ \ if (high == low + 1) { /* Two elements only */ \ if (arr[low] > arr[high]) \ { register elem_type t=arr[low];arr[low]=arr[high];arr[high]=t; } \ break; /* return arr[half] ; */ \ } \ \ /* Find median of low, middle and high items; swap into low */ \ middle = (low + high) / 2; \ if (arr[middle] > arr[high]) { register elem_type t=arr[middle];arr[middle]=arr[high];arr[high]=t; } \ if (arr[low] > arr[high]) { register elem_type t=arr[low]; arr[low] =arr[high];arr[high]=t; } \ if (arr[middle] > arr[low] ) { register elem_type t=arr[middle];arr[middle]=arr[low]; arr[low] =t; } \ \ /* Swap low item (now in position middle) into position (low+1) */ \ { register elem_type t=arr[middle];arr[middle]=arr[low+1];arr[low+1]=t; } \ \ /* Nibble from ends towards middle, swapping items when stuck */ \ ll = low + 1; \ hh = high; \ for (;;) { \ do ll++; while (arr[low] > arr[ll] ); \ do hh--; while (arr[hh] > arr[low]); \ \ if (hh < ll) break; \ \ { register elem_type t=arr[ll];arr[ll]=arr[hh];arr[hh]=t;} \ } \ \ /* Swap middle item (in position low) back into correct position */ \ { register elem_type t=arr[low];arr[low]=arr[hh];arr[hh]=t; } \ \ /* Re-set active partition */ \ if (hh <= half) low = ll; \ if (hh >= half) high = hh - 1; \ } \ median = arr[half]; \ } /*--------------------------------------------------------------------------- Function : kth_smallest() In : array of elements, # of elements in the array, rank k Out : one element Job : find the kth smallest element in the array Notice : use the median() macro defined below to get the median. Reference: Author: Wirth, Niklaus Title: Algorithms + data structures = programs Publisher: Englewood Cliffs: Prentice-Hall, 1976 Physical description: 366 p. Series: Prentice-Hall Series in Automatic Computation --------------------------------------------------------------------------- This does NOT fully sort the input array, but it does modify it WIRTHS_KTH_SMALLEST(elem_type, arr, n, k, ksmallest) elem_type is a valid data type, int, long, unsigned char, float... arr is an array delcared as elem_type *array and passed as array n is the size of the array, ie. total element count k is the kth smallest value of the array that you want to find ksmallest contains the kth smallest value of arr on exit WIRTHS_MEDIAN(elem_type, arr, n, median) finds median value Calls WIRTHS_KTH_SMALLEST with (k = n/2) fills median ---------------------------------------------------------------------------*/ #define DECLARE_WIRTHS_MEDIAN( name, elem_type ) \ elem_type name( elem_type *arr, int n, elem_type &median ); #define DEFINE_WIRTHS_MEDIAN( name, elem_type ) \ elem_type name( elem_type *arr, int n, elem_type &median ) \ WIRTHS_MEDIAN( elem_type, arr, n, median ) #define IMPLEMENT_WIRTHS_MEDIAN(elem_type, arr, n, median) \ IMPLEMENT_WIRTHS_KTH_SMALLEST(elem_type, arr, n, (((n)&1)?((n)/2):(((n)/2)-1)), median) #define DECLARE_WIRTHS_KTH_SMALLEST( name, elem_type ) \ elem_type name( elem_type *arr, int n, elem_type &median ); #define DEFINE_WIRTHS_KTH_SMALLEST( name, elem_type ) \ elem_type name( elem_type *arr, int n, elem_type &median ) \ IMPLEMENT_WIRTHS_MEDIAN( elem_type, arr, n, median ) #define IMPLEMENT_WIRTHS_KTH_SMALLEST(elem_type, arr, n, k, ksmallest) \ { \ register int i, j, l=0, m=n-1; \ register elem_type x; \ \ while (lmax) max=arr[i]; \ } \ \ while (1) { \ guess = (min+max)/2; \ less = 0; greater = 0; equal = 0; \ maxltguess = min; \ mingtguess = max; \ for (i=0; imaxltguess) maxltguess = arr[i]; \ } else if (arr[i]>guess) { \ greater++; \ if (arr[i]greater) max = maxltguess; \ else min = mingtguess; \ } \ if (less >= (n+1)/2) median = maxltguess; \ else if (less+equal >= (n+1)/2) median = guess; \ else median = mingtguess; \ } /*---------------------------------------------------------------------------- Function : pixel_qsort() In : pixel array, size of the array Out : void Job : sort out the array of pixels Notice : optimized implementation, unreadable. --------------------------------------------------------------------------- This fully sorts the input array by modifying it DECLARE_PIXEL_QSORT(name, elem_type) ----------------------------------------------------------------------------*/ #define PIXEL_QSORT_STACK_SIZE 50 #define PIXEL_QSORT_THRESHOLD 7 #define DECLARE_PIXEL_QSORT( name, elem_type ) \ void name( elem_type *arr, int n ); #define DEFINE_PIXEL_QSORT( name, elem_type ) \ void name( elem_type *arr, int n ) \ IMPLEMENT_PIXEL_QSORT( name, elem_type ) #define IMPLEMENT_PIXEL_QSORT( elem_type, arr, n ) \ { \ int i, ir=n, j, k, l=1, j_stack=0; \ int *i_stack ; \ elem_type a ; \ \ i_stack = (int*)malloc(PIXEL_QSORT_STACK_SIZE * sizeof(elem_type)); \ for (;;) { \ if (ir-l < PIXEL_QSORT_THRESHOLD) { \ for (j=l+1 ; j<=ir ; j++) { \ a = arr[j-1]; \ for (i=j-1 ; i>=1 ; i--) { \ if (arr[i-1] <= a) break; \ arr[i] = arr[i-1]; \ } \ arr[i] = a; \ } \ if (j_stack == 0) break; \ ir = i_stack[j_stack-- -1]; \ l = i_stack[j_stack-- -1]; \ } else { \ k = (l+ir) >> 1; \ { elem_type t=arr[k-1];arr[k-1]=arr[l];arr[l]=t; } \ if (arr[l] > arr[ir-1]) { \ { elem_type t=arr[l];arr[l]=arr[ir-1];arr[ir-1]=t; } \ } \ if (arr[l-1] > arr[ir-1]) { \ { elem_type t=arr[l-1];arr[l-1]=arr[ir-1];arr[ir-1]=t; } \ } \ if (arr[l] > arr[l-1]) { \ { elem_type t=arr[l];arr[l]=arr[l-1];arr[l-1]=t; } \ } \ i = l+1; j = ir; a = arr[l-1]; \ for (;;) { \ do i++; while (arr[i-1] < a); \ do j--; while (arr[j-1] > a); \ if (j < i) break; \ { elem_type t=arr[i-1];arr[i-1]=arr[j-1];arr[j-1]=t; } \ } \ arr[l-1] = arr[j-1]; \ arr[j-1] = a; \ j_stack += 2; \ wxASSERT(!(j_stack>PIXEL_QSORT_STACK_SIZE)); \ /* if (j_stack > PIXEL_QSORT_STACK_SIZE) { */ \ /* printf("stack too small in pixel_qsort: aborting"); */ \ /* exit(-2001); } */ \ if (ir-i+1 >= j-l) { \ i_stack[j_stack-1] = ir; \ i_stack[j_stack-2] = i; \ ir = j-1; \ } else { \ i_stack[j_stack-1] = j-1; \ i_stack[j_stack-2] = l; \ l = i; \ } \ } \ } \ free(i_stack); \ } /*------------------------------------------------------------------------- Function : pixel_qsort2() In : two pixel arrays, size of the arrays Out : void Job : sort out both arrays based on the first array Notice : optimized implementation, unreadable. --------------------------------------------------------------------------- This fully sorts the input arrays by modifying them Uses the first array as the comparison array DECLARE_PIXEL_QSORT2(name, elem_type) ----------------------------------------------------------------------------*/ #define PIXEL_QSORT2_STACK_SIZE 50 #define PIXEL_QSORT2_THRESHOLD 7 #define DECLARE_PIXEL_QSORT2( name, elem_type ) \ void name( elem_type *arr, elem_type *arr2, int n ); #define DEFINE_PIXEL_QSORT2( name, elem_type ) \ void name( elem_type *arr, elem_type *arr2, int n ) \ IMPLEMENT_PIXEL_QSORT2( name, elem_type ) #define IMPLEMENT_PIXEL_QSORT2( elem_type, arr, arr2, n ) \ { \ int i, ir=n, j, k, l=1, j_stack=0; \ int *i_stack ; \ elem_type a, a2 ; \ \ i_stack = (int*)malloc(PIXEL_QSORT2_STACK_SIZE * sizeof(elem_type)); \ for (;;) { \ if (ir-l < PIXEL_QSORT2_THRESHOLD) { \ for (j=l+1 ; j<=ir ; j++) { \ a = arr[j-1]; a2 = arr2[j-1]; \ for (i=j-1 ; i>=1 ; i--) { \ if (arr[i-1] <= a) break; \ arr[i] = arr[i-1]; \ arr2[i] = arr2[i-1]; \ } \ arr[i] = a; arr2[i] = a2; \ } \ if (j_stack == 0) break; \ ir = i_stack[j_stack-- -1]; \ l = i_stack[j_stack-- -1]; \ } else { \ k = (l+ir) >> 1; \ { elem_type t=arr[k-1];arr[k-1]=arr[l];arr[l]=t; t=arr2[k-1];arr2[k-1]=arr2[l];arr2[l]=t; } \ if (arr[l] > arr[ir-1]) { \ { elem_type t=arr[l];arr[l]=arr[ir-1];arr[ir-1]=t; t=arr2[l];arr2[l]=arr2[ir-1];arr2[ir-1]=t;} \ } \ if (arr[l-1] > arr[ir-1]) { \ { elem_type t=arr[l-1];arr[l-1]=arr[ir-1];arr[ir-1]=t; t=arr2[l-1];arr2[l-1]=arr2[ir-1];arr2[ir-1]=t;} \ } \ if (arr[l] > arr[l-1]) { \ { elem_type t=arr[l];arr[l]=arr[l-1];arr[l-1]=t; t=arr2[l];arr2[l]=arr2[l-1];arr2[l-1]=t; } \ } \ i = l+1; j = ir; a = arr[l-1]; a2 = arr2[l-1]; \ for (;;) { \ do i++; while (arr[i-1] < a); \ do j--; while (arr[j-1] > a); \ if (j < i) break; \ { elem_type t=arr[i-1];arr[i-1]=arr[j-1];arr[j-1]=t; t=arr2[i-1];arr2[i-1]=arr2[j-1];arr2[j-1]=t;} \ } \ arr[l-1] = arr[j-1]; arr2[l-1] = arr2[j-1]; \ arr[j-1] = a; arr2[j-1] = a2; \ j_stack += 2; \ wxASSERT(!(j_stack>PIXEL_QSORT_STACK_SIZE)); \ /* if (j_stack > PIXEL_QSORT_STACK_SIZE) { */ \ /* printf("stack too small in pixel_qsort: aborting"); */ \ /* exit(-2001); } */ \ if (ir-i+1 >= j-l) { \ i_stack[j_stack-1] = ir; \ i_stack[j_stack-2] = i; \ ir = j-1; \ } else { \ i_stack[j_stack-1] = j-1; \ i_stack[j_stack-2] = l; \ l = i; \ } \ } \ } \ free(i_stack); \ } /* Abbreviated benchmark data from http://ndevilla.free.fr/median/median/node13.html (QuickSelect, Wirth, Aho/Hopcroft/Ullman, Torben, pixel quicksort) Pentium II 400 MHz running Linux 2.0 with glibc-2.0.7. The basic method using the libc qsort() function has not been represented here, because it is so slow compared to the others that it would make the plot unreadable. Furthermore, it depends on the local implementation of your C library. Ratios have been obtained for sets with increasing number of values, from 1e4 to 1e6. The speed ratios have been computed to the fastest method on average (QuickSelect), then averaged over all measure points. QuickSelect : 1.00 WIRTH median : 1.33 AHU median : 3.71 Torben : 8.95 fast pixel sort : 6.50 Elm Qselect Wirth AHU Torben pqsort 10000 0.000 0.000 0.010 0.010 0.010 100000 0.010 0.020 0.050 0.140 0.100 200000 0.040 0.040 0.180 0.310 0.220 300000 0.070 0.060 0.190 0.470 0.340 400000 0.080 0.140 0.150 0.630 0.450 500000 0.110 0.080 0.510 0.800 0.580 600000 0.090 0.140 0.320 0.940 0.730 700000 0.120 0.100 0.450 1.100 0.810 800000 0.120 0.160 0.590 1.270 0.940 900000 0.180 0.250 0.760 1.430 1.070 1000000 0.210 0.290 0.600 1.580 1.240 */ #endif //__WX_MEDSORT_H__ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/menubtn.h0000644000076500007650000001547211350032206020575 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: wxMenuButton // Purpose: A button with a dropdown wxMenu // Author: John Labenski // Modified by: // Created: 11/05/2002 // Copyright: (c) John Labenski // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// /* wxMenuButton is a button that drops down an assigned wxMenu Create the button with either a text or bitmap label. Create a new wxMenu and call AssignMenu and thats it. When you press the dropdown button the menu appears. When you press the label button the next wxITEM_RADIO (ie wxMenuItem::GetKind) in the menu is selected round robin. If there are no radio items then it really just acts like a menubar, though this is probably not too useful. The events sent in this case are EVT_MENUs either generated by the menu when you click on it or created when you click on the label to select the next radio item. */ #ifndef _WX_MENUBTN_H_ #define _WX_MENUBTN_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "menubtn.h" #endif #include "wx/wxthings/thingdef.h" #include "wx/wxthings/toggle.h" class WXDLLEXPORT wxMenu; class WXDLLEXPORT wxBitmap; class WXDLLIMPEXP_THINGS wxCustomButton; //----------------------------------------------------------------------------- // wxMenuButton styles //----------------------------------------------------------------------------- #define wxMENUBUTTON_DROP_WIDTH 10 #define wxMENUBUTTON_DROP_HEIGHT 22 enum wxMenuButton_Styles { wxMENUBUT_FLAT = wxCUSTBUT_FLAT }; //----------------------------------------------------------------------------- // wxMenuButton //----------------------------------------------------------------------------- class WXDLLIMPEXP_THINGS wxMenuButton : public wxControl { public: wxMenuButton() : wxControl() { Init(); } // Use this constructor if you need one compatible with a wxButton // setup the button later with AssignMenu wxMenuButton( wxWindow* parent, wxWindowID id, const wxString &label, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxMenuButton")) : wxControl() { Init(); Create(parent,id,label,wxNullBitmap,pos,size,style,val,name); } // Use this constructor if you need one compatible with a wxBitmapButton // setup the button later with AssignMenu wxMenuButton( wxWindow* parent, wxWindowID id, const wxBitmap &bitmap, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxMenuButton")) : wxControl() { Init(); Create(parent,id,wxEmptyString,bitmap,pos,size,style,val,name); } // wxComboBox constructor, completely setup later wxMenuButton( wxWindow *parent, wxWindowID id, const wxString& value = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, int n = 0, const wxString choices[] = (const wxString *) NULL, long style = 0, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxMenuButton")) : wxControl() { n = n; choices = choices; // get rid of unused warning Init(); Create(parent, id, value, wxNullBitmap, pos, size, style, val, name); } // Native constructor wxMenuButton( wxWindow* parent, wxWindowID id, const wxString &label, const wxBitmap &bitmap, wxMenu *menu, bool static_menu = false, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxMenuButton")) : wxControl() { Init(); AssignMenu(menu, static_menu); Create(parent,id,label,bitmap,pos,size,style,val,name); } virtual ~wxMenuButton(); bool Create( wxWindow* parent, wxWindowID id, const wxString &label, const wxBitmap &bitmap, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxNO_BORDER, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxMenuButton")); // Gets the id of the first selected radio item or wxNOT_FOUND (-1) if none int GetSelection() const; // This menu will be displayed when the dropdown button is pressed. // if static_menu is false it will be deleted when the buttton is destroyed. void AssignMenu(wxMenu *menu, bool static_menu = false); wxMenu *GetMenu() const { return m_menu; } // get a pointer to the label button, for turning it into a toggle perhaps wxCustomButton *GetLabelButton() const { return m_labelButton; } wxCustomButton *GetDropDownButton() const { return m_dropdownButton; } void SetToolTip(const wxString &tip); void SetToolTip(wxToolTip *tip); protected: void OnButton(wxCommandEvent &event); virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); virtual wxSize DoGetBestSize(); // FIXME! - in MSW the radio items don't check themselves #ifdef __WXMSW__ void OnMenu( wxCommandEvent &event ); #endif wxCustomButton *m_labelButton; wxCustomButton *m_dropdownButton; wxMenu *m_menu; bool m_menu_static; long m_style; private: void Init(); DECLARE_DYNAMIC_CLASS(wxMenuButton) DECLARE_EVENT_TABLE() }; //----------------------------------------------------------------------------- // wxMenuButtonEvents // // EVT_MENUBUTTON_OPEN(id, fn) - menu is about to be opened, (dis)(en)able items // or call Veto() to stop menu from popping up // this is a wxNotifyEvent //----------------------------------------------------------------------------- BEGIN_DECLARE_EVENT_TYPES() DECLARE_LOCAL_EVENT_TYPE( wxEVT_MENUBUTTON_OPEN, 0 ) END_DECLARE_EVENT_TYPES() #define EVT_MENUBUTTON_OPEN(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_MENUBUTTON_OPEN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxNotifyEventFunction) & fn, (wxObject *) NULL ), #endif // _WX_MENUBTN_H_ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/optvalue.h0000644000076500007650000002061411350032206020756 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: optvalue.h // Purpose: An string option & value pair class // Author: John Labenski // Created: 07/01/02 // Copyright: John Labenski, 2002 // License: wxWidgets v2 ///////////////////////////////////////////////////////////////////////////// #ifndef __WXOPTIONVALUE_H__ #define __WXOPTIONVALUE_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "optvalue.h" #endif #include "wx/wxthings/thingdef.h" class WXDLLIMPEXP_THINGS wxOptionValue; #include "wx/dynarray.h" WX_DECLARE_OBJARRAY_WITH_DECL(wxOptionValue, wxArrayOptionValue, class WXDLLIMPEXP_THINGS); //---------------------------------------------------------------------------- // Global wxString utilities //---------------------------------------------------------------------------- //extern wxArrayString wxStringToWords( const wxString &string ); //---------------------------------------------------------------------------- // wxOptionValue - a ref counted wxString key, wxString value container //---------------------------------------------------------------------------- class WXDLLIMPEXP_THINGS wxOptionValue : public wxObject { public: wxOptionValue(bool create = true) : wxObject() { if (create) Create(); } wxOptionValue( const wxOptionValue &optValue ) : wxObject() { Create(optValue); } wxOptionValue( const wxString &str ) : wxObject() { Create(str); } // (Re)Create as an empty container bool Create(); // Ref the other wxOptionValue bool Create( const wxOptionValue &optValue ); // Create from a string with this structure // [type] # optional // key = value bool Create( const wxString &string ); // Make a true copy of the source wxOptionValue (not refed) bool Copy( const wxOptionValue &source ); // Is there any ref data bool Ok() const; // Unref the data void Destroy(); //------------------------------------------------------------------------- // Get/Set the "type", which can mean whatever you want wxString GetType() const; void SetType( const wxString &type ); //------------------------------------------------------------------------- // does this have a wxOptionValueArray filled with children size_t GetChildrenCount() const; wxArrayOptionValue *GetChildren() const; bool AddChild( const wxOptionValue& child ); void DeleteChildren(); //------------------------------------------------------------------------- // Get the number of different option name/value combinations size_t GetOptionCount() const; // Access the arrays themselves wxArrayString GetOptionNames() const; wxArrayString GetOptionValues() const; // Get a specific option name or value wxString GetOptionName( size_t n ) const; wxString GetOptionValue( size_t n ) const; // returns the index of the option >= 0 or -1 (wxNOT_FOUND) if not found int HasOption(const wxString &name) const; // Search through the option names for this part returning the first match int FindOption(const wxString &part_of_option_name) const; // delete this option, returns sucess bool DeleteOption(const wxString &name); bool DeleteOption( size_t n ); // Option functions (arbitrary name/value mapping) void SetOption(const wxString& name, const wxString& value, bool force=true ); void SetOption(const wxString& name, int value, bool force=true ) { SetOption(name, wxString::Format(wxT("%d"), value), force); } void SetOption(const wxString& name, double value, bool force=true ) { SetOption(name, wxString::Format(wxT("%lf"), value), force); } // printf style for numeric values SetOption("Name", true, "%d %f", 2, 2.5) void SetOption(const wxString& name, bool update, const wxChar* format, ...); void SetOption(const wxString& name, int v1, int v2, int v3, bool force=true ) { SetOption(name, wxString::Format(wxT("%d %d %d"), v1, v2, v3), force); } void SetOption(const wxString& name, double v1, double v2, double v3, bool force=true ) { SetOption(name, wxString::Format(wxT("%lf %lf %lf"), v1, v2, v3), force); } void SetOption(const wxString& name, int *v, int count, bool force=true ) { if(v) { wxString s; for (int i=0; i m_max; } // Swap the min and max values inline void SwapMinMax() { register int temp=m_min; m_min=m_max; m_max=temp; } // returns -1 for i < min, 0 for in range, +1 for i > m_max inline int Position(int i) const { return i < m_min ? -1 : (i > m_max ? 1 : 0); } // Is this point or the range within this range inline bool Contains( int i ) const { return (i >= m_min) && (i <= m_max); } inline bool Contains( const wxRangeInt &r ) const { return (r.m_min >= m_min) && (r.m_max <= m_max); } // returns if the range intersects the given range inline bool Intersects(const wxRangeInt& r) const { return Intersect(r).IsEmpty(); } // returns the intersection of the range with the other inline wxRangeInt Intersect(const wxRangeInt& r) const { return wxRangeInt(wxMax(m_min, r.m_min), wxMin(m_max, r.m_max)); } // returns the union of the range with the other inline wxRangeInt Union(const wxRangeInt& r) const { return wxRangeInt(wxMin(m_min, r.m_min), wxMax(m_max, r.m_max)); } // Is this point inside or touches +/- 1 of the range inline bool Touches( int i ) const { return !IsEmpty() && wxRangeInt(m_min-1, m_max+1).Contains(i); } // Is the range adjoining this range inline bool Touches( const wxRangeInt &r ) const { if (IsEmpty() || r.IsEmpty()) return false; wxRangeInt rExp(m_min-1, m_max+1); return rExp.Contains(r.m_min) || rExp.Contains(r.m_max); } // combine this single point with the range by expanding the m_min/m_max to contain it // if only_if_touching then only combine if i is just outside the range by +/-1 // returns true if the range has been changed at all, false if not bool Combine(int i, bool only_if_touching = false); bool Combine(const wxRangeInt &r, bool only_if_touching = false); // delete range r from this, return true is anything was done // if r spans this then this and right become wxEmptyRangeInt // else if r is inside of this then this is the left side and right is the right // else if r.m_min > m_min then this is the left side // else if r.m_min < m_min this is the right side bool Delete( const wxRangeInt &r, wxRangeInt *right=NULL ); // operators // no copy ctor or assignment operator - the defaults are ok // comparison inline bool operator==(const wxRangeInt& r) const { return (m_min == r.m_min)&&(m_max == r.m_max); } inline bool operator!=(const wxRangeInt& r) const { return !(*this == r); } // Adding ranges unions them to create the largest range inline wxRangeInt operator+(const wxRangeInt& r) const { return Union(r); } inline wxRangeInt& operator+=(const wxRangeInt& r) { if(r.m_minm_max) m_max=r.m_max; return *this; } // Subtracting ranges intersects them to get the smallest range inline wxRangeInt operator-(const wxRangeInt& r) const { return Intersect(r); } inline wxRangeInt& operator-=(const wxRangeInt& r) { if(r.m_min>m_min) m_min=r.m_min; if(r.m_max m_max; } // Swap the min and max values inline void SwapMinMax() { register wxDouble temp = m_min; m_min = m_max; m_max = temp; } // returns -1 for i < min, 0 for in range, +1 for i > m_max inline int Position(wxDouble i) const { return i < m_min ? -1 : i > m_max ? 1 : 0; } // Is this point or the range within this range inline bool Contains( wxDouble i ) const { return (i>=m_min)&&(i<=m_max); } inline bool Contains( const wxRangeDouble &r ) const { return (r.m_min>=m_min)&&(r.m_max<=m_max); } // returns if the range intersects the given range inline bool Intersects(const wxRangeDouble& r) const { return Intersect(r).IsEmpty(); } // returns the intersection of the range with the other inline wxRangeDouble Intersect(const wxRangeDouble& r) const { return wxRangeDouble(wxMax(m_min, r.m_min), wxMin(m_max, r.m_max)); } // returns the union of the range with the other inline wxRangeDouble Union(const wxRangeDouble& r) const { return wxRangeDouble(wxMin(m_min, r.m_min), wxMax(m_max, r.m_max)); } // no touches for double since what would be a good eps value? // combine this single point with the range by expanding the m_min/m_max to contain it // if only_if_touching then only combine if there is overlap // returns true if the range has been changed at all, false if not bool Combine(wxDouble i); bool Combine( const wxRangeDouble &r, bool only_if_touching = false ); // delete range r from this, return true is anything was done // if r spans this then this and right become wxEmptyRangeInt // else if r is inside of this then this is the left side and right is the right // else if r.m_min > m_min then this is the left side // else if r.m_min < m_min this is the right side bool Delete( const wxRangeDouble &r, wxRangeDouble *right=NULL ); // operators // no copy ctor or assignment operator - the defaults are ok // comparison inline bool operator==(const wxRangeDouble& r) const { return (m_min == r.m_min)&&(m_max == r.m_max); } inline bool operator!=(const wxRangeDouble& r) const { return !(*this == r); } // Adding ranges unions them to create the largest range inline wxRangeDouble operator+(const wxRangeDouble& r) const { return Union(r); } inline wxRangeDouble& operator+=(const wxRangeDouble& r) { if(r.m_minm_max) m_max=r.m_max; return *this; } // Subtracting ranges intersects them to get the smallest range inline wxRangeDouble operator-(const wxRangeDouble& r) const { return Intersect(r); } inline wxRangeDouble& operator-=(const wxRangeDouble& r) { if(r.m_min>m_min) m_min=r.m_min; if(r.m_max to return to it Shift + Arrow = *2 increment value Ctrl + Arrow = *10 increment value Alt + Arrow = *100 increment value combinations of Shift, Ctrl, Alt increment by the product of the factors PgUp & PgDn = *10 increment * the product of the Shift, Ctrl, Alt factors sets the control's value to the it's last valid state SetDigits controls the format of the text, # decimal places exponential uses the %.Xle format otherwise %.Xlf, where places = X for arbitray formats subclass control and override SyncSpinToText() for proper behavior when a user types in a value */ #ifndef __wxSPINCTRLDBL_H__ #define __wxSPINCTRLDBL_H__ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "spinctld.h" #endif #include "wx/spinbutt.h" #include "wx/spinctrl.h" // for EVT_SPINCTRL #include "wx/wxthings/thingdef.h" class WXDLLEXPORT wxTextCtrl; class WXDLLIMPEXP_THINGS wxSpinCtrlDblTextCtrl; enum { wxSPINCTRLDBL_AUTODIGITS = -1 // try to autocalc the # of digits }; class WXDLLIMPEXP_THINGS wxSpinCtrlDbl: public wxControl { public: wxSpinCtrlDbl() : wxControl() { Init(); } // Native constructor - note &parent, this is to avoid ambiguity wxSpinCtrlDbl( wxWindow &parent, wxWindowID id, const wxString &value = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(95,-1), long style = 0, double min = 0.0, double max = 100.0, double initial = 0.0, double increment = 1.0, int digits = wxSPINCTRLDBL_AUTODIGITS, const wxString& name = _T("wxSpinCtrlDbl") ) { Init(); Create(&parent, id, value, pos, size, style, min, max, initial, increment, digits, name); } // wxSpinCtrl compatibility, call SetIncrement(increment,digits) after wxSpinCtrlDbl( wxWindow *parent, wxWindowID id = wxID_ANY, const wxString &value = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(95,-1), long style = 0, int min = 0, int max = 100, int initial = 0, const wxString& name = _T("wxSpinCtrlDbl") ) { Init(); Create(parent, id, value, pos, size, style, (double)min, (double)max, (double)initial, 1.0, -1, name); } bool Create( wxWindow *parent, wxWindowID id = wxID_ANY, const wxString &value = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(100,-1), long style = 0, double min = 0.0, double max = 100.0, double initial = 0.0, double increment = 1.0, int digits = wxSPINCTRLDBL_AUTODIGITS, const wxString& name = _T("wxSpinCtrlDbl") ); virtual ~wxSpinCtrlDbl(); // ----------------------------------------------------------------------- // Public (normal usage) functions enum formatType { lf_fmt, // %lf le_fmt, // %le lg_fmt // %lg }; virtual void SetValue( double value ); void SetValue( double value, double min, double max, double increment, int digits = wxSPINCTRLDBL_AUTODIGITS, formatType fmt = lg_fmt ) { SetRange(min, max); SetIncrement(increment); SetDigits(digits, fmt); SetValue(value); } // Set the value as text, if force then set text as is virtual void SetValue( const wxString& text, bool force ); // Set the allowed range, if max_val < min_val then no range and all vals allowed. void SetRange( double min_val, double max_val ); // Set the increment to use when the spin button or arrow keys pressed. void SetIncrement( double increment ); void SetIncrement( double increment, int digits, formatType fmt = lg_fmt ) { SetIncrement(increment); SetDigits(digits, fmt); } // Set the number of digits to show, use wxSPINCTRLDBL_AUTODIGITS // or specify exact number to show i.e. %.[digits]lf // The format type is used to create an appropriate format string. void SetDigits( int digits = wxSPINCTRLDBL_AUTODIGITS, formatType fmt = lg_fmt ); // Set the format string to use, ie. format="%.2lf" for .01 void SetFormat( const wxString& format ); // Set the control the the default value. virtual void SetDefaultValue() { SetValue( m_default_value ); } // Set the value of the default value, default is the inital value. void SetDefaultValue( double default_value ); // Force the value to always be divisible by the increment, initially off. // This uses the default_value as the basis, you'll get strange results // for very large differences between the current value and default value // when the increment is very small. void SetSnapToTicks(bool forceTicks); double GetValue() const { return m_value; } double GetMin() const { return m_min; } double GetMax() const { return m_max; } virtual bool HasRange() const { return m_max >= m_min; } virtual bool InRange(double value) const { return !HasRange() || ((value >= m_min) && (value <= m_max)); } double GetIncrement() const { return m_increment; } int GetDigits() const { return m_digits; } wxString GetFormat() const { return m_textFormat; } double GetDefaultValue() const { return m_default_value; } bool GetSnapToTicks() const { return m_snap_ticks; } bool IsDefaultValue() const { return (m_value == m_default_value); } virtual bool SetFont( const wxFont &font ); wxFont GetFont() const; virtual bool SetBackgroundColour(const wxColour& colour); wxColour GetBackgroundColour() const; virtual bool SetForegroundColour(const wxColour& colour); wxColour GetForegroundColour() const; // for setting... stuff wxTextCtrl *GetTextCtrl() { return (wxTextCtrl*)m_textCtrl; } protected: void OnSpinUp( wxSpinEvent &event ); void OnSpinDown( wxSpinEvent &event ); void OnTextEnter( wxCommandEvent &event ); void OnText( wxCommandEvent &event ); // the textctrl is subclassed to get at pgup/dn and then sent here void OnChar( wxKeyEvent &event ); virtual void SyncSpinToText(bool send_event = true, bool force_valid = true); void DoSendEvent(); // send an event based on current state virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); virtual wxSize DoGetBestSize() const; void OnFocus( wxFocusEvent& event ); // pass focus to textctrl, for wxTAB_TRAVERSAL void OnKillFocus( wxFocusEvent &event ); wxSpinButton *m_spinButton; wxSpinCtrlDblTextCtrl *m_textCtrl; double m_min; // min allowed value double m_max; // max allowed value double m_value; // current value double m_default_value; // initial value, or SetDefaultValue(value) double m_increment; // how much to to add per spin int m_digits; // number of digits displayed after decimal point bool m_snap_ticks; // value is divisible by increment wxString m_textFormat; // used as wxString.Printf(m_textFormat.c_str(), m_value); private: friend class wxSpinCtrlDblTextCtrl; void Init(); DECLARE_DYNAMIC_CLASS(wxSpinCtrlDbl) DECLARE_EVENT_TABLE() }; #endif // __wxSPINCTRLDBL_H__ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/thingdef.h0000644000076500007650000000212611350032206020705 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: thingdef.h // Purpose: Definitions for wxThings // Author: John Labenski // Modified by: // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// #ifndef __WX_THINGDEF_H__ #define __WX_THINGDEF_H__ #include "wx/defs.h" // ---------------------------------------------------------------------------- // DLLIMPEXP macros // ---------------------------------------------------------------------------- // These are our DLL macros (see the contrib libs like wxPlot) /* #ifdef WXMAKINGDLL_THINGS #define WXDLLIMPEXP_THINGS WXEXPORT #define WXDLLIMPEXP_DATA_THINGS(type) WXEXPORT type #elif defined(WXUSINGDLL) #define WXDLLIMPEXP_THINGS WXIMPORT #define WXDLLIMPEXP_DATA_THINGS(type) WXIMPORT type #else // not making nor using DLL */ #define WXDLLIMPEXP_THINGS #define WXDLLIMPEXP_DATA_THINGS(type) type /* #endif */ #endif // __WX_THINGDEF_H__ gambit-0.2010.09.01/src/labenski/include/wx/wxthings/toggle.h0000644000076500007650000002245511350032206020405 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: wxCustomButton.h based on wxCustomToggleCtrl.cpp // Purpose: a toggle button // Author: Bruce Phillips modified by John Labenski // Modified by: // Created: 11/05/2002 // RCS-ID: // Copyright: (c) Bruce Phillips, John Labenski // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// /* wxCustomButton is a bitmap and/or text button that can toggle or not. It can be used as a drop-in replacement for a wxButton, wxToggleButton, wxBitmapButton, and the non-existant "wxBitmapToggleButton." The event's wxCommandEvent::GetExtraLong contains one of the following wxEVT_LEFT_UP, wxEVT_RIGHT_UP, wxEVT_LEFT_DCLICK, wxEVT_RIGHT_DCLICK these can be used to distinguish between the types of events sent There are four styles the button can take. wxCUSTBUT_BUTTON == wxButton Left and Right clicks and double clicks all send wxEVT_COMMAND_BUTTON_CLICKED => EVT_BUTTON(id,fn) wxCUSTBUT_TOGGLE == wxToggleButton Left clicks sends wxEVT_COMMAND_TOGGLEBUTTON_CLICKED => EVT_TOGGLEBUTTON(id, fn) Left double clicks and Right clicks send wxEVT_COMMAND_BUTTON_CLICKED => EVT_BUTTON(id,fn) wxCUSTBUT_BUT_DCLICK_TOG Left and Right clicks and Right double clicks send wxEVT_COMMAND_BUTTON_CLICKED => EVT_BUTTON(id,fn) Left double clicks sends wxEVT_COMMAND_TOGGLEBUTTON_CLICKED => EVT_TOGGLEBUTTON(id, fn) wxCUSTBUT_TOG_DCLICK_BUT Left clicks sends wxEVT_COMMAND_TOGGLEBUTTON_CLICKED => EVT_TOGGLEBUTTON(id, fn) Left and Right double clicks and Right clicks send wxEVT_COMMAND_BUTTON_CLICKED => EVT_BUTTON(id,fn) The event's wxCommandEvent::GetInt (IsChecked) is true (1) if the button is depressed, this is only useful for the wxToggleButton styles For both types of button when double-clicked it sends this event wxEVT_COMMAND_BUTTON_CLICKED => EVT_BUTTON(id, fn) and the button state does not change. Only a single EVT_BUTTON event should be sent on double-click and event.GetExtraLong == wxEVT_XXX_DCLICK, if not then there's a bug. If no bitmaps are set the text is centered, if only a bitmap it set then it's centered, if a bitmap and text are set then the text is one of the positions wxCUSTBUT_LEFT/RIGHT/TOP/BOTTOM The disabled bitmap it automatically created by dithering with the background, the others just copy the bitmap in the constructor. The control assumes they are all the same size. You have to #include "wx/tglbtn.h" for EVT_TOGGLEBUTTON */ #ifndef _WX_CUSTOMBUTTON_H_ #define _WX_CUSTOMBUTTON_H_ #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "toggle.h" #endif #include "wx/wxthings/thingdef.h" class WXDLLEXPORT wxTimer; class WXDLLEXPORT wxTimerEvent; //----------------------------------------------------------------------------- // wxCustomButton styles //----------------------------------------------------------------------------- enum wxCustomButton_Style { // Position of the label, use only one wxCUSTBUT_LEFT = 0x0001, wxCUSTBUT_RIGHT = 0x0002, wxCUSTBUT_TOP = 0x0004, wxCUSTBUT_BOTTOM = 0x0008, // Button style, use only one wxCUSTBUT_NOTOGGLE = 0x0100, wxCUSTBUT_BUTTON = 0x0200, wxCUSTBUT_TOGGLE = 0x0400, wxCUSTBUT_BUT_DCLICK_TOG = 0x0800, wxCUSTBUT_TOG_DCLICK_BUT = 0x1000, // drawing styles wxCUSTBUT_FLAT = 0x2000 // flat, mouseover raises if not depressed }; //----------------------------------------------------------------------------- // wxCustomButton //----------------------------------------------------------------------------- class WXDLLIMPEXP_THINGS wxCustomButton : public wxControl { public: wxCustomButton() : wxControl() { Init(); } // wxToggleButton or wxButton compatible constructor (also wxTextCtrl) wxCustomButton(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCUSTBUT_TOGGLE, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxCustomButton")) : wxControl() { Init(); Create(parent,id,label,wxNullBitmap,pos,size,style,val,name); } // wxBitmapButton compatible constructor wxCustomButton(wxWindow *parent, wxWindowID id, const wxBitmap& bitmap, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCUSTBUT_TOGGLE, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxCustomButton")) : wxControl() { Init(); Create(parent,id,wxEmptyString,bitmap,pos,size,style,val,name); } // Native constructor wxCustomButton(wxWindow *parent, wxWindowID id, const wxString& label, const wxBitmap& bitmap, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCUSTBUT_TOGGLE|wxCUSTBUT_BOTTOM, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxCustomButton")) : wxControl() { Init(); Create(parent,id,label,bitmap,pos,size,style,val,name); } virtual ~wxCustomButton(); bool Create(wxWindow* parent, wxWindowID id, const wxString& label, const wxBitmap &bitmap, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& val = wxDefaultValidator, const wxString& name = wxT("wxCustomButton")); bool GetValue() const { return m_down%2 != 0; } void SetValue( bool depressed ); // Use combinations of wxCustomButton_Style(s) long GetButtonStyle() const { return m_button_style; } bool SetButtonStyle( long style ); // Set the text label, wxEmptyString for none void SetLabel( const wxString &label ); // set the bitmaps, ONLY this Label bitmap is used for calculating control size // all bitmaps will be centered accordingly in any case // call SetSet(GetBestSize()) if you change their size and want the control to resize appropriately void SetBitmapLabel(const wxBitmap& bitmap); void SetBitmapSelected(const wxBitmap& sel) { m_bmpSelected = sel; CalcLayout(true); }; void SetBitmapFocus(const wxBitmap& focus) { m_bmpFocus = focus; CalcLayout(true); }; void SetBitmapDisabled(const wxBitmap& disabled) { m_bmpDisabled = disabled; CalcLayout(true); }; // wxBitmapButton compatibility void SetLabel(const wxBitmap& bitmap) { SetBitmapLabel(bitmap); } // retrieve the bitmaps const wxBitmap& GetBitmapLabel() const { return m_bmpLabel; } const wxBitmap& GetBitmapSelected() const { return m_bmpSelected; } const wxBitmap& GetBitmapFocus() const { return m_bmpFocus; } const wxBitmap& GetBitmapDisabled() const { return m_bmpDisabled; } // Creates a "disabled" bitmap by dithering it with the background colour wxBitmap CreateBitmapDisabled(const wxBitmap &bitmap) const; // set/get the margins (in pixels) around the label and bitmap // if fit = true then resize the button to fit void SetMargins(const wxSize &margin, bool fit = false); // set/get the margins around the text label // the inter bitmap/label margin is the max of either margin, not the sum void SetLabelMargin(const wxSize &margin, bool fit = false); wxSize GetLabelMargin() const { return m_labelMargin; } // set/get the margins around the bitmap // the inter bitmap/label margin is the max of either margin, not the sum void SetBitmapMargin(const wxSize &margin, bool fit = false); wxSize GetBitmapMargin() const { return m_bitmapMargin; } // can be used to activate the focused behavior (see MenuButton) void SetFocused(bool focused) { m_focused = focused; Refresh(false); } bool GetFocused() const { return m_focused; } protected: void OnPaint(wxPaintEvent &event); void Redraw(); virtual void Paint( wxDC &dc ); virtual wxSize DoGetBestSize() const; virtual void SendEvent(); void OnMouseEvents(wxMouseEvent &event); void OnTimer(wxTimerEvent &event); void OnSize( wxSizeEvent &event ); virtual void CalcLayout(bool refresh); int m_down; // toggle state if m_down%2 then depressed bool m_focused; // mouse in window long m_button_style; // the bitmaps for various states wxBitmap m_bmpLabel, m_bmpSelected, m_bmpFocus, m_bmpDisabled; // the margins around the label/bitmap wxSize m_labelMargin, m_bitmapMargin; wxPoint m_bitmapPos, m_labelPos; wxTimer *m_timer; wxEventType m_eventType; // store the mouse event type private: void Init(); DECLARE_DYNAMIC_CLASS(wxCustomButton) DECLARE_EVENT_TABLE() }; #endif // _WX_CUSTOMBUTTON_H_ gambit-0.2010.09.01/src/labenski/README.txt0000644000076500007650000000124411350032206014506 00000000000000This directory contains various source code for handy widgets distributed by John Labenski, jrl1[at]lehigh[dot]edu, under the wxWidgets license. These are distributed by the author in several separate but interdepedent packages, versioned by release date. This directory builds them into a single shared library from a unified hierarchy. The idea is to try to change the sources as minimally as possible, to make dropping in a new release from the author simple. The doc/ subdirectory includes the original README files from each of the subpackages. The following packages and versions are currently included in this directory: wxThings 031605 wxSheet 052405 gambit-0.2010.09.01/src/labenski/src/0000777000076500007650000000000011441457113013673 500000000000000gambit-0.2010.09.01/src/labenski/src/block.cpp0000644000076500007650000007514711350032206015412 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: block.cpp // Purpose: Rectangular selection storage classes for ints and doubles // Author: John Labenski // Created: 07/01/02 // Copyright: (c) John Labenski 2004 // Licence: wxWidgets ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "block.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP //#include "wx/object.h" #endif // WX_PRECOMP #include "wx/wxthings/block.h" // use this to check to see if there is any overlap after minimizing //#define CHECK_BLOCK_OVERLAP 1 #define PRINT_BLOCK(msg, b) { wxPrintf(wxT("Block '%s' %lg %lg %lg %lg\n"), msg, (double)(b).m_x1, (double)(b).m_y1, (double)(b).m_x2, (double)(b).m_y2); } wxBlockInt const wxEmptyBlockInt(0, 0, -1, -1); wxBlockDouble const wxEmptyBlockDouble(0, 0, -1, -1); #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArrayBlockInt); WX_DEFINE_OBJARRAY(wxArrayBlockDouble); WX_DEFINE_OBJARRAY(wxArrayBlockIntSelection); WX_DEFINE_OBJARRAY(wxArrayBlockDoubleSelection); // ---------------------------------------------------------------------------- // Sorting functions for wxBlockInt // ---------------------------------------------------------------------------- static int wxCMPFUNC_CONV wxblockint_sort_topleft_bottomright( wxBlockInt **a, wxBlockInt **b) { register int y = ((*a)->m_y1 - (*b)->m_y1); if (y < 0) return -1; if (y == 0) return ((*a)->m_x1 - (*b)->m_x1); return 1; } static int wxCMPFUNC_CONV wxblockint_sort_topright_bottomleft( wxBlockInt **a, wxBlockInt **b) { register int y = ((*a)->m_y1 - (*b)->m_y1); if (y < 0) return -1; if (y == 0) return ((*a)->m_x2 - (*b)->m_x2); return 1; } static int wxCMPFUNC_CONV wxblockint_sort_bottomleft_topright( wxBlockInt **a, wxBlockInt **b) { register int y = ((*a)->m_y2 - (*b)->m_y2); if (y > 0) return -1; if (y == 0) return ((*a)->m_x1 - (*b)->m_x1); return 1; } static int wxCMPFUNC_CONV wxblockint_sort_bottomright_topleft( wxBlockInt **a, wxBlockInt **b) { register int y = ((*a)->m_y2 - (*b)->m_y2); if (y > 0) return -1; if (y == 0) return ((*a)->m_x2 - (*b)->m_x2); return 1; } static int wxCMPFUNC_CONV wxblockint_sort_largest_to_smallest( wxBlockInt **a, wxBlockInt **b) { return (*a)->IsLarger(**b); } static int wxCMPFUNC_CONV wxblockint_sort_smallest_to_largest( wxBlockInt **a, wxBlockInt **b) { return -(*a)->IsLarger(**b); } void wxArrayBlockIntSort(wxArrayBlockInt &blocks, wxBlockSort_Type type) { switch (type) { case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT : blocks.Sort(wxblockint_sort_topleft_bottomright); break; case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT : blocks.Sort(wxblockint_sort_topright_bottomleft); break; case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT : blocks.Sort(wxblockint_sort_bottomleft_topright); break; case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT : blocks.Sort(wxblockint_sort_bottomright_topleft); break; case wxBLOCKSORT_SMALLEST_TO_LARGEST : blocks.Sort(wxblockint_sort_smallest_to_largest); break; case wxBLOCKSORT_LARGEST_TO_SMALLEST : blocks.Sort(wxblockint_sort_largest_to_smallest); break; default : wxFAIL_MSG(wxT("unknown block sort type")); } } // ---------------------------------------------------------------------------- // Sorting functions for wxBlockDouble // ---------------------------------------------------------------------------- static int wxCMPFUNC_CONV wxblockdouble_sort_topleft_bottomright( wxBlockDouble **a, wxBlockDouble **b) { register wxDouble y = ((*a)->m_y1 - (*b)->m_y1); if (y < 0) return -1; if (y == 0) return int((*a)->m_x1 - (*b)->m_x1); return 1; } static int wxCMPFUNC_CONV wxblockdouble_sort_topright_bottomleft( wxBlockDouble **a, wxBlockDouble **b) { register wxDouble y = ((*a)->m_y1 - (*b)->m_y1); if (y < 0) return -1; if (y == 0) return int((*a)->m_x2 - (*b)->m_x2); return 1; } static int wxCMPFUNC_CONV wxblockdouble_sort_bottomleft_topright( wxBlockDouble **a, wxBlockDouble **b) { register wxDouble y = ((*a)->m_y2 - (*b)->m_y2); if (y > 0) return -1; if (y == 0) return int((*a)->m_x1 - (*b)->m_x1); return 1; } static int wxCMPFUNC_CONV wxblockdouble_sort_bottomright_topleft( wxBlockDouble **a, wxBlockDouble **b) { register wxDouble y = ((*a)->m_y2 - (*b)->m_y2); if (y > 0) return -1; if (y == 0) return int((*a)->m_x2 - (*b)->m_x2); return 1; } static int wxCMPFUNC_CONV wxblockdouble_sort_largest_to_smallest( wxBlockDouble **a, wxBlockDouble **b) { return (*a)->IsLarger(**b); } static int wxCMPFUNC_CONV wxblockdouble_sort_smallest_to_largest( wxBlockDouble **a, wxBlockDouble **b) { return -(*a)->IsLarger(**b); } void wxArrayBlockDoubleSort(wxArrayBlockDouble &blocks, wxBlockSort_Type type) { switch (type) { case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT : blocks.Sort(wxblockdouble_sort_topleft_bottomright); break; case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT : blocks.Sort(wxblockdouble_sort_topright_bottomleft); break; case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT : blocks.Sort(wxblockdouble_sort_bottomleft_topright); break; case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT : blocks.Sort(wxblockdouble_sort_bottomright_topleft); break; case wxBLOCKSORT_SMALLEST_TO_LARGEST : blocks.Sort(wxblockdouble_sort_smallest_to_largest); break; case wxBLOCKSORT_LARGEST_TO_SMALLEST : blocks.Sort(wxblockdouble_sort_largest_to_smallest); break; default : wxFAIL_MSG(wxT("unknown block sort type")); } } //============================================================================= // wxBlockInt //============================================================================= #define TEST_BLOCKS #ifdef TEST_BLOCKS void TestBlocks() { printf("Start Testing blocks -----------------------------------------\n"); wxBlockInt b1(1,1,4,4); wxBlockInt b2(5,4,10,11); PRINT_BLOCK("b1", b1) PRINT_BLOCK("b2", b2) wxBlockInt iB; iB.Intersect(b1, b2, &iB); PRINT_BLOCK("Intersect b1 b2", iB) wxBlockInt uB; uB.Union(b1, b2, &uB); PRINT_BLOCK("Union b1 b2", uB) printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); b1 = wxBlockInt(2,3,7,9); b2 = wxBlockInt(8,3,8,3); printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); b1 = wxBlockInt(2,3,7,9); b2 = wxBlockInt(1,3,1,3); printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); iB.Intersect(b1, b2, &iB); PRINT_BLOCK("Intersect b1 b2", iB) b1 = wxBlockInt(2,3,7,9); b2 = wxBlockInt(2,2,2,2); printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); b1 = wxBlockInt(2,3,7,9); b2 = wxBlockInt(7,10,7,10); printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); printf("End Testing blocks -----------------------------------------\n"); fflush(stdout); } #endif //TEST_BLOCKS bool wxBlockInt::Touches(const wxBlockInt &b) const // see Intersects { //if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) && // ((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2)))) // return true; return Intersects(wxBlockInt(b.m_x1-1, b.m_y1-1, b.m_x2+1, b.m_y2+1)); /* wxInt32 left = wxMax( m_x1, b.m_x1 ); wxInt32 right = wxMin( m_x2, b.m_x2 ); if (labs(left - right) <= 1) { wxInt32 top = wxMax( m_y1, b.m_y1 ); wxInt32 bottom = wxMin( m_y2, b.m_y2 ); if (labs(top - bottom) <= 1) return true; } return false; */ } bool wxBlockInt::Combine(const wxBlockInt &b) { if (!Touches(b)) return false; if (Contains(b)) return true; if (b.Contains(*this)) { *this = b; return true; } wxBlockInt unionBlock; Union( *this, b, &unionBlock ); if (unionBlock.IsEmpty()) return false; // at least one of the two blocks has to be at each corner of the union if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) && ((unionBlock.GetRightTop() == GetRightTop()) || (unionBlock.GetRightTop() == b.GetRightTop())) && ((unionBlock.GetLeftBottom() == GetLeftBottom()) || (unionBlock.GetLeftBottom() == b.GetLeftBottom())) && ((unionBlock.GetRightBottom() == GetRightBottom()) || (unionBlock.GetRightBottom() == b.GetRightBottom())) ) { *this = unionBlock; return true; } return false; } bool wxBlockInt::Combine( const wxBlockInt &block, wxBlockInt &top, wxBlockInt &bottom, wxBlockInt &left, wxBlockInt &right) const { top = bottom = left = right = wxEmptyBlockInt; wxBlockInt iBlock; Intersect(*this, block, &iBlock); if (iBlock.IsEmpty()) return false; // nothing to combine if (iBlock == *this) return true; // can combine all of this, no leftover bool combined = false; if ( block.m_y1 < m_y1 ) { top = wxBlockInt( block.m_x1, block.m_y1, block.m_x2, m_y1-1 ); combined = true; } if ( block.m_y2 > m_y2 ) { bottom = wxBlockInt( block.m_x1, m_y2+1, block.m_x2, block.m_y2 ); combined = true; } if ( block.m_x1 < m_x1 ) { left = wxBlockInt( block.m_x1, iBlock.m_y1, m_x1-1, iBlock.m_y2 ); combined = true; } if ( block.m_x2 > m_x2 ) { right = wxBlockInt( m_x2+1, iBlock.m_y1, block.m_x2, iBlock.m_y2 ); combined = true; } return combined; } bool wxBlockInt::Delete( const wxBlockInt &block, wxBlockInt &top, wxBlockInt &bottom, wxBlockInt &left, wxBlockInt &right) const { top = bottom = left = right = wxEmptyBlockInt; wxBlockInt iBlock; Intersect(*this, block, &iBlock); if (iBlock.IsEmpty()) return false; // nothing to delete if (iBlock == *this) return true; // can delete all of this, no leftover bool deleted = false; if ( m_y1 < iBlock.m_y1 ) { top = wxBlockInt( m_x1, m_y1, m_x2, iBlock.m_y1-1 ); deleted = true; } if ( GetBottom() > iBlock.GetBottom() ) { bottom = wxBlockInt( m_x1, iBlock.m_y2+1, m_x2, m_y2 ); deleted = true; } if ( m_x1 < iBlock.m_x1 ) { left = wxBlockInt( m_x1, iBlock.m_y1, iBlock.m_x1-1, iBlock.m_y2 ); deleted = true; } if ( GetRight() > iBlock.GetRight() ) { right = wxBlockInt( iBlock.m_x2+1, iBlock.m_y1, m_x2, iBlock.m_y2 ); deleted = true; } return deleted; } //============================================================================= // wxBlockDouble //============================================================================= bool wxBlockDouble::Touches(const wxBlockDouble &b) const // see Intersects { if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) && ((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2)))) return true; return false; } bool wxBlockDouble::Combine(const wxBlockDouble &b) { if (!Touches(b)) return false; if (Contains(b)) return true; if (b.Contains(*this)) { *this = b; return true; } wxBlockDouble unionBlock; Union( *this, b, &unionBlock ); if (unionBlock.IsEmpty()) return false; // at least one of the two blocks has to be at each corner of the union if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) && ((unionBlock.GetRightTop() == GetRightTop()) || (unionBlock.GetRightTop() == b.GetRightTop())) && ((unionBlock.GetLeftBottom() == GetLeftBottom()) || (unionBlock.GetLeftBottom() == b.GetLeftBottom())) && ((unionBlock.GetRightBottom() == GetRightBottom()) || (unionBlock.GetRightBottom() == b.GetRightBottom())) ) { *this = unionBlock; return true; } return false; } bool wxBlockDouble::Combine( const wxBlockDouble &block, wxBlockDouble &top, wxBlockDouble &bottom, wxBlockDouble &left, wxBlockDouble &right) const { top = bottom = left = right = wxEmptyBlockDouble; wxBlockDouble iBlock; Intersect(*this, block, &iBlock); if (iBlock.IsEmpty()) return false; // nothing to combine if (iBlock == *this) return true; // can combine all of this, no leftover bool combined = false; if ( block.m_y1 < m_y1 ) { top = wxBlockDouble( block.m_x1, block.m_y1, block.m_x2, m_y1 ); combined = true; } if ( block.m_y2 > m_y2 ) { bottom = wxBlockDouble( block.m_x1, m_y2, block.m_x2, block.m_y2 ); combined = true; } if ( block.m_x1 < m_x1 ) { left = wxBlockDouble( block.m_x1, iBlock.m_y1, m_x1, iBlock.m_y2 ); combined = true; } if ( block.m_x2 > m_x2 ) { right = wxBlockDouble( m_x2, iBlock.m_y1, block.m_x2, iBlock.m_y2 ); combined = true; } return combined; } bool wxBlockDouble::Delete( const wxBlockDouble &block, wxBlockDouble &top, wxBlockDouble &bottom, wxBlockDouble &left, wxBlockDouble &right) const { top = bottom = left = right = wxEmptyBlockDouble; wxBlockDouble iBlock; Intersect(*this, block, &iBlock); if (iBlock.IsEmpty()) return false; // nothing to delete if (iBlock == *this) return true; // can delete all of this, no leftover bool deleted = false; if ( m_y1 < iBlock.m_y1 ) { top = wxBlockDouble( m_x1, m_y1, m_x2, iBlock.m_y1 ); deleted = true; } if ( m_y2 > iBlock.m_y2 ) { bottom = wxBlockDouble( m_x1, iBlock.m_y2, m_x2, m_y2 ); deleted = true; } if ( m_x1 < iBlock.m_x1 ) { left = wxBlockDouble( m_x1, iBlock.m_y1, iBlock.m_x1, iBlock.m_y2 ); deleted = true; } if ( m_x2 > iBlock.m_x2 ) { right = wxBlockDouble( iBlock.m_x2, iBlock.m_y1, m_x2, iBlock.m_y2 ); deleted = true; } return deleted; } //============================================================================= // wxBlockIntSelection //============================================================================= wxBlockInt wxBlockIntSelection::GetBlock( int index ) const { wxCHECK_MSG((index>=0) && (index= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2)) { wxRangeInt range(m_blocks[n].m_y1, m_blocks[n].m_y2); ranges.Add(range); } } return ranges; } wxArrayRangeInt wxBlockIntSelection::GetBlockRow(int row) const { wxArrayRangeInt ranges; register int n, count = m_blocks.GetCount(); for (n=0; n= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2)) ranges.Add(wxRangeInt(m_blocks[n].m_x1, m_blocks[n].m_x2)); } return ranges; } #endif // USE_wxRANGE wxBlockInt wxBlockIntSelection::GetBoundingBlock() const { register int n, count = m_blocks.GetCount(); if (count == 0) return wxEmptyBlockInt; wxBlockInt bound = m_blocks[0]; for (n=1; n 0) ? n - 1 : -1; if (!top.IsEmpty()) m_blocks.Add(top); if (!bottom.IsEmpty()) m_blocks.Add(bottom); if (!left.IsEmpty()) m_blocks.Add(left); if (!right.IsEmpty()) m_blocks.Add(right); } } if (combineNow) Minimize(); return done; } bool wxBlockIntSelection::SelectBlock( const wxBlockInt &block, bool combineNow, wxArrayBlockInt *addedBlocks ) { wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") ); //TestBlocks(); wxArrayBlockInt extraBlocks; wxArrayBlockInt *extra = &extraBlocks; if (addedBlocks != NULL) { addedBlocks->Clear(); extra = addedBlocks; } extra->Add(block); int n, count = m_blocks.GetCount(); wxBlockInt top, bottom, left, right; for (n=0; nGetCount()); k++) { if (m_blocks[n].Combine(extra->Item(k), top, bottom, left, right)) { extra->RemoveAt(k); if (!top.IsEmpty()) extra->Add(top); if (!bottom.IsEmpty()) extra->Add(bottom); if (!left.IsEmpty()) extra->Add(left); if (!right.IsEmpty()) extra->Add(right); //DoMinimize( *extra ); n = -1; break; } } } if (extra->GetCount() > 0u) { WX_APPEND_ARRAY(m_blocks, *extra); if (combineNow) Minimize(); return true; } return false; } bool wxBlockIntSelection::Minimize() { bool ret = DoMinimize(m_blocks); Sort(m_sort); return ret; } bool wxBlockIntSelection::DoMinimize(wxArrayBlockInt &blocks) { int n; for (n=0; n<1000; n++) // should probably just take a few { if (!DoDoMinimize(blocks)) break; } #ifdef CHECK_BLOCK_OVERLAP for (size_t a=0; a=0) && (index= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2)) { wxRangeDouble range(m_blocks[n].m_y1, m_blocks[n].m_y2); ranges.Add(range); } } return ranges; } wxArrayRangeDouble wxBlockDoubleSelection::GetBlockRow(wxDouble row) const { wxArrayRangeDouble ranges; register int n, count = m_blocks.GetCount(); for (n=0; n= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2)) ranges.Add(wxRangeDouble(m_blocks[n].m_x1, m_blocks[n].m_x2)); } return ranges; } #endif // USE_wxRANGE wxBlockDouble wxBlockDoubleSelection::GetBoundingBlock() const { register int n, count = m_blocks.GetCount(); if (count == 0) return wxEmptyBlockDouble; wxBlockDouble bound = m_blocks[0]; for (n=1; n= m_blocks[n].m_x1) && (y >= m_blocks[n].m_y1) && (x <= m_blocks[n].m_x2) && (y <= m_blocks[n].m_y2) ) return true; } return wxNOT_FOUND; } int wxBlockDoubleSelection::Index( const wxBlockDouble &b ) const { register int n, count = m_blocks.GetCount(); for (n=0; n 0) ? n - 1 : -1; if (!top.IsEmpty()) m_blocks.Add(top); if (!bottom.IsEmpty()) m_blocks.Add(bottom); if (!left.IsEmpty()) m_blocks.Add(left); if (!right.IsEmpty()) m_blocks.Add(right); } } if (combineNow) Minimize(); return done; } bool wxBlockDoubleSelection::SelectBlock( const wxBlockDouble &block, bool combineNow) { // It's valid to select a block with a width and height 0 since that means that point //wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") ); wxArrayBlockDouble extra; extra.Add(block); wxBlockDouble top, bottom, left, right; for (int n=0; n 0) { done = m_blocks[n].Combine(extra[k], top, bottom, left, right); if (done) { extra.RemoveAt(k); k--; } } else { done = extra[k].Combine(m_blocks[n], top, bottom, left, right); if (done) { m_blocks.RemoveAt(n); n = -1; } } } if (done) { if (!top.IsEmpty()) extra.Add(top); if (!bottom.IsEmpty()) extra.Add(bottom); if (!left.IsEmpty()) extra.Add(left); if (!right.IsEmpty()) extra.Add(right); //DoMinimize( extra ); if (n == -1) break; } } } if (extra.GetCount() > 0u) { WX_APPEND_ARRAY(m_blocks, extra); if (combineNow) Minimize(); return true; } return false; } bool wxBlockDoubleSelection::Minimize() { bool ret = DoMinimize(m_blocks); Sort(m_sort); return ret; } bool wxBlockDoubleSelection::DoMinimize(wxArrayBlockDouble &blocks) { int n; for (n=0; n<1000; n++) // should probably just take < 10 at most { if (!DoDoMinimize(blocks)) break; } #ifdef CHECK_BLOCK_OVERLAP for (size_t a=0; a= int(m_blocks.GetCount()))) return false; // first time here if (m_block_index < 0) { m_block_index = 0; pt = m_pt = m_blocks[m_block_index].GetLeftTop(); return true; } // at end of block swap to new one if (m_pt == m_blocks[m_block_index].GetRightBottom()) { ++m_block_index; if (int(m_blocks.GetCount()) > m_block_index) { pt = m_pt = m_blocks[m_block_index].GetLeftTop(); return true; } else // past end nothing more to check return false; } // at end of col, down to next row if (m_pt.m_x == m_blocks[m_block_index].GetRight()) { m_pt.m_x = m_blocks[m_block_index].m_x1; m_pt.m_y++; pt = m_pt; return true; } // increment the col m_pt.m_x++; pt = m_pt; return true; } bool wxBlockIntSelectionIterator::IsInSelection(const wxPoint2DInt &pt) const { register int n, count = m_blocks.GetCount(); for (n=0; n The file FFT.ZIP contains C source code for performing Discrete Fast Fourier Transforms (DFFTs) and inverse DFFTs. Please see fouier.txt which was the readme.txt that Don Cross provided. This source code is public domain. Use at your own risk. For more information, point your web browser at: (dead link) http://www.intersrv.com/~dcross/fft.html Helper routines for Fast Fourier Transform implementation. Contains common code for fft_float() and fft_double(). See also: ..\include\fourier.h Revision history: 1998 September 19 [Don Cross] Improved the efficiency of IsPowerOfTwo(). Updated coding standards. 2003 [John Labenski] Merged fourierd.c (double), fourierf.c (float), and fftmisc.c into fourier.c for simplicity. ============================================================================*/ #include #include #include #include "wx/plotctrl/fourier.h" #define BITS_PER_WORD (sizeof(unsigned) * 8) #define DDC_PI (3.14159265358979323846) /*--- start of file fftmisc.c---*/ // #define IsPowerOfTwo(x) (((x)<2) || ((x)&((x)-1)) ? false : true) // returns 1 if the numver is a power of two else 0 int IsPowerOfTwo ( unsigned x ) { if ( x < 2 ) return 0; if ( x & (x-1) ) // Thanks to 'byang' for this cute trick! return 0; return 1; } // returns the number of bits needed unsigned NumberOfBitsNeeded ( unsigned PowerOfTwo ) { unsigned i; for ( i=0; ; i++ ) { if ( PowerOfTwo & (1 << i) ) return i; } return 0; } unsigned ReverseBits ( unsigned index, unsigned NumBits ) { unsigned i, rev; for ( i=rev=0; i < NumBits; i++ ) { rev = (rev << 1) | (index & 1); index >>= 1; } return rev; } double Index_to_frequency ( unsigned NumSamples, unsigned Index ) { if ( Index >= NumSamples ) return 0.0; else if ( Index <= NumSamples/2 ) return (double)Index / (double)NumSamples; return -(double)(NumSamples-Index) / (double)NumSamples; } /*--- end of file fftmisc.c---*/ /*============================================================================ fourierd.c - Don Cross http://www.intersrv.com/~dcross/fft.html Contains definitions for doing Fourier transforms and inverse Fourier transforms. This module performs operations on arrays of 'double'. Revision history: 1998 September 19 [Don Cross] Updated coding standards. Improved efficiency of trig calculations. ============================================================================*/ #define CHECKPOINTERDOUBLE(p) if (CheckPointerDouble(p,#p) == 0) return 0; static int CheckPointerDouble ( void *p, char *name ) { if ( p == NULL ) { fprintf ( stderr, "Error in fft_double(): %s == NULL\n", name ); return 0; } return 1; } int fft_double ( unsigned NumSamples, int InverseTransform, double *RealIn, double *ImagIn, double *RealOut, double *ImagOut ) { unsigned NumBits; /* Number of bits needed to store indices */ unsigned i, j, k, n; unsigned BlockSize, BlockEnd; double angle_numerator = -2.0 * DDC_PI; // this is - to match matlab double tr, ti; /* temp real, temp imaginary */ if ( !IsPowerOfTwo(NumSamples) || (NumSamples < 2) ) { fprintf ( stderr, "Error in fft(): NumSamples=%u is not power of two\n", NumSamples ); return 0; } if ( InverseTransform ) angle_numerator = -angle_numerator; CHECKPOINTERDOUBLE ( RealIn ); CHECKPOINTERDOUBLE ( RealOut ); CHECKPOINTERDOUBLE ( ImagOut ); NumBits = NumberOfBitsNeeded ( NumSamples ); /* ** Do simultaneous data copy and bit-reversal ordering into outputs... */ for ( i=0; i < NumSamples; i++ ) { j = ReverseBits ( i, NumBits ); RealOut[j] = RealIn[i]; ImagOut[j] = (ImagIn == NULL) ? 0.0 : ImagIn[i]; } /* ** Do the FFT itself... */ BlockEnd = 1; for ( BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1 ) { double delta_angle = angle_numerator / (double)BlockSize; double sm2 = sin ( -2 * delta_angle ); double sm1 = sin ( -delta_angle ); double cm2 = cos ( -2 * delta_angle ); double cm1 = cos ( -delta_angle ); double w = 2 * cm1; /* double ar[3], ai[3]; replaced array with fixed vals below - labenski */ double ar0, ar1, ar2, ai0, ai1, ai2; for ( i=0; i < NumSamples; i += BlockSize ) { ar2 = cm2; ar1 = cm1; ai2 = sm2; ai1 = sm1; for ( j=i, n=0; n < BlockEnd; j++, n++ ) { ar0 = w*ar1 - ar2; ar2 = ar1; ar1 = ar0; ai0 = w*ai1 - ai2; ai2 = ai1; ai1 = ai0; k = j + BlockEnd; tr = ar0*RealOut[k] - ai0*ImagOut[k]; ti = ar0*ImagOut[k] + ai0*RealOut[k]; RealOut[k] = RealOut[j] - tr; ImagOut[k] = ImagOut[j] - ti; RealOut[j] += tr; ImagOut[j] += ti; } } BlockEnd = BlockSize; } /* ** Need to normalize if inverse transform... */ if ( InverseTransform ) { double denom = (double)NumSamples; for ( i=0; i < NumSamples; i++ ) { RealOut[i] /= denom; ImagOut[i] /= denom; } } return 1; } /*--- end of file fourierd.c ---*/ /*============================================================================ fourierf.c - Don Cross http://www.intersrv.com/~dcross/fft.html Contains definitions for doing Fourier transforms and inverse Fourier transforms. This module performs operations on arrays of 'float'. Revision history: 1998 September 19 [Don Cross] Updated coding standards. Improved efficiency of trig calculations. ============================================================================*/ #define CHECKPOINTERFLOAT(p) if (CheckPointerFloat(p,#p) == 0) return 0; static int CheckPointerFloat ( void *p, char *name ) { if ( p == NULL ) { fprintf ( stderr, "Error in fft_float(): %s == NULL\n", name ); return 0; } return 1; } int fft_float ( unsigned NumSamples, int InverseTransform, float *RealIn, float *ImagIn, float *RealOut, float *ImagOut ) { unsigned NumBits; /* Number of bits needed to store indices */ unsigned i, j, k, n; unsigned BlockSize, BlockEnd; double angle_numerator = -2.0 * DDC_PI; // this is - to match matlab double tr, ti; /* temp real, temp imaginary */ if ( !IsPowerOfTwo(NumSamples) || (NumSamples < 2) ) { fprintf ( stderr, "Error in fft(): NumSamples=%u is not power of two\n", NumSamples ); return 0; } if ( InverseTransform ) angle_numerator = -angle_numerator; CHECKPOINTERFLOAT ( RealIn ); CHECKPOINTERFLOAT ( RealOut ); CHECKPOINTERFLOAT ( ImagOut ); NumBits = NumberOfBitsNeeded ( NumSamples ); /* ** Do simultaneous data copy and bit-reversal ordering into outputs... */ for ( i=0; i < NumSamples; i++ ) { j = ReverseBits ( i, NumBits ); RealOut[j] = RealIn[i]; ImagOut[j] = (ImagIn == NULL) ? (float)0.0 : ImagIn[i]; } /* ** Do the FFT itself... */ BlockEnd = 1; for ( BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1 ) { double delta_angle = angle_numerator / (double)BlockSize; double sm2 = sin ( -2 * delta_angle ); double sm1 = sin ( -delta_angle ); double cm2 = cos ( -2 * delta_angle ); double cm1 = cos ( -delta_angle ); double w = 2 * cm1; /* double ar[3], ai[3]; replaced array with fixed vals below - labenski */ double ar0, ar1, ar2, ai0, ai1, ai2; /* double temp; */ for ( i=0; i < NumSamples; i += BlockSize ) { ar2 = cm2; ar1 = cm1; ai2 = sm2; ai1 = sm1; for ( j=i, n=0; n < BlockEnd; j++, n++ ) { ar0 = w*ar1 - ar2; ar2 = ar1; ar1 = ar0; ai0 = w*ai1 - ai2; ai2 = ai1; ai1 = ai0; k = j + BlockEnd; tr = ar0*RealOut[k] - ai0*ImagOut[k]; ti = ar0*ImagOut[k] + ai0*RealOut[k]; RealOut[k] = (float)(RealOut[j] - tr); ImagOut[k] = (float)(ImagOut[j] - ti); RealOut[j] += (float)tr; ImagOut[j] += (float)ti; } } BlockEnd = BlockSize; } /* ** Need to normalize if inverse transform... */ if ( InverseTransform ) { float denom = (float)NumSamples; for ( i=0; i < NumSamples; i++ ) { RealOut[i] /= denom; ImagOut[i] /= denom; } } return 1; } /*--- end of file fourierf.c ---*/ gambit-0.2010.09.01/src/labenski/src/fparser.cpp0000644000076500007650000027451411350032206015761 00000000000000//=============================== // Function parser v2.71 by Warp //=============================== // Modified for use with wxWidgets by John Labenski 1/20/04 // removed all non ASCII chars from this file for unicode compatibility. // I apologize for mangling peoples names, but some unicode editors could not // properly load this file previously. #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "fparser.h" #pragma implementation "fparser.hh" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/defs.h" #include "wx/string.h" #endif #if defined(__VISUALC__) && wxUSE_DEBUG_NEW_ALWAYS && defined(new) #undef new // turn off wxWidgets debug code #endif // Turn off warnings generated from MSVC's buggy std:: lib header files. #if defined(__VISUALC__) #include #pragma warning(disable: 4018) // signed/unsigned mismatch #pragma warning(disable: 4100) // unreferenced formal parameter #pragma warning(disable: 4146) // unary minus operator applied to unsigned type, // result still unsigned #pragma warning(disable: 4244) // 'conversion' conversion from 'type1' to 'type2', // possible loss of data #pragma warning(disable: 4245) // conversion from 'type1' to 'type2', signed/unsigned // mismatch #pragma warning(disable: 4511) // 'class' : copy constructor could not be generated #pragma warning(disable: 4512) // 'class' : assignment operator could not be generated #pragma warning(disable: 4663) // C++ language change: to explicitly specialize class // template 'vector' #pragma warning(disable: 4710) // 'function' : function not inlined #pragma warning(disable: 4786) // identifier was truncated to 'number' characters #endif // Comment out the following line if your compiler supports the (non-standard) // asinh, acosh and atanh functions and you want them to be supported. If // you are not sure, just leave it (those function will then not be supported). //#define NO_ASINH #if defined(__VISUALC__) || defined(__BORLANDC__) // || defined(__WATCOMC__) // use our own asin/cos/tanh functions from since compilier doesn't have them // "A Numerical Library in C for Scientists and Engineers", H.T. Lau, 1995 #include #include double logoneplusx(double x) { if (x == 0.0) return 0.0; else if ((x < -0.2928) || (x > 0.4142)) return log(1.0 + x); else { double z = x/(x + 2.0); double y = z*z; return z*(2.0+y*(0.666666666663366+y*(0.400000001206045+y* (0.285714091590488+y*(0.22223823332791+y* (0.1811136267967+y*0.16948212488)))))); } } double asinh(double x) { if (fabs(x) > 1.0E10) return ((x > 0.0) ? 0.69314718055995+log(fabs(x)) : -0.69314718055995+log(fabs(x))); else { double y = x*x; return ((x == 0.0) ? 0.0 : ((x > 0.0) ? logoneplusx(fabs(x)+y/(1.0+sqrt(1.0+y))) : -logoneplusx(fabs(x)+y/(1.0+sqrt(1.0+y))))); } } double acosh(double x) { return ((x <= 1.0) ? 0.0 : ((x > 1.0E10) ? 0.69314718055995+log(x) : log(x+sqrt((x-1.0)*(x+1.0))))); } double atanh(double x) { double ax = fabs(x); if (ax >= 1.0) return ((x > 0.0) ? DBL_MAX : -DBL_MAX); else { return ((x == 0) ? 0.0 : ((x > 0.0) ? 0.5*logoneplusx(2.0*ax/(1.0-ax)) : -0.5*logoneplusx(2.0*ax/(1.0-ax)))); } } #endif // Uncomment the following line to disable the eval() function if it could // be too dangerous in the target application: //#define DISABLE_EVAL // Comment this line out if you are not going to use the optimizer and want // a slightly smaller library. The Optimize() method can still be called, // but it will not do anything. // If you are unsure, just leave it. It won't slow down the other parts of // the library. #ifndef NO_SUPPORT_OPTIMIZER #define SUPPORT_OPTIMIZER #endif #include "wx/plotctrl/fparser.h" #include "fparser.hh" // ---------------------------------------------------------------------------- // wxFunctionParser - a thin wrapper around FunctionParser // ---------------------------------------------------------------------------- wxFunctionParser::wxFunctionParser() : m_ok(false) { m_functionParser = new FunctionParser; } wxFunctionParser::wxFunctionParser(const wxFunctionParser& fP) { m_functionParser = new FunctionParser(*fP.GetFunctionParser()); m_function = fP.GetFunctionString(); m_variables = fP.GetVariableString(); m_ok = fP.Ok(); } wxFunctionParser::~wxFunctionParser() { delete m_functionParser; } int wxFunctionParser::Parse(const wxString& function, const wxString& vars, bool useDegrees) { m_function = function; m_variables = vars; std::string Function = (const char*)wxConvUTF8.cWX2MB(function.c_str()); std::string Vars = (const char*)wxConvUTF8.cWX2MB(vars.c_str()); int ret = m_functionParser->Parse(Function, Vars, useDegrees); m_ok = (ret == -1) && ErrorMsg().IsEmpty(); return ret; } wxString wxFunctionParser::ErrorMsg() const { const char *msg = m_functionParser->ErrorMsg(); if (!msg) return wxEmptyString; return wxConvUTF8.cMB2WX(msg); } wxFunctionParser::ParseErrorType wxFunctionParser::GetParseErrorType() const { return (wxFunctionParser::ParseErrorType)m_functionParser->GetParseErrorType(); } double wxFunctionParser::Eval(const double* Vars) { return m_functionParser->Eval(Vars); } int wxFunctionParser::EvalError() const { return m_functionParser->EvalError(); } bool wxFunctionParser::AddConstant(const wxString& name, double value) { std::string Name = (const char*)wxConvUTF8.cWX2MB(name.c_str()); return m_functionParser->AddConstant(Name, value); } bool wxFunctionParser::AddFunction(const wxString& name, FunctionPtr fP, unsigned paramsAmount) { std::string Name = (const char*)wxConvUTF8.cWX2MB(name.c_str()); return m_functionParser->AddFunction(Name, fP, paramsAmount); } bool wxFunctionParser::AddFunction(const wxString& name, wxFunctionParser& fP) { std::string Name = (const char*)wxConvUTF8.cWX2MB(name.c_str()); return m_functionParser->AddFunction(Name, *fP.GetFunctionParser()); } void wxFunctionParser::Optimize() { m_functionParser->Optimize(); } int wxFunctionParser::GetNumberVariables() const { return m_functionParser->GetNumberVariables(); } bool wxFunctionParser::GetUseDegrees() const { return m_functionParser->GetUseDegrees(); } wxString wxFunctionParser::GetVariableName(size_t n) const { int numVars = GetNumberVariables(); if (int(n) >= numVars) return wxEmptyString; wxString vars(GetVariableString()); size_t i, count = 0, len = vars.Length(); for (i = 0; i < len; i++) { if (n == count) return vars.Mid(i).BeforeFirst(wxT(',')); if (vars[i] == wxT(',')) count++; } return wxEmptyString; } wxFunctionParser& wxFunctionParser::operator=(const wxFunctionParser& cpy) { *m_functionParser = *cpy.GetFunctionParser(); m_function = cpy.GetFunctionString(); m_variables = cpy.GetVariableString(); m_ok = cpy.Ok(); return *this; } //============================================================================ #include #include #include #include #include #include #if defined(__VISUALC__) && (__VISUALC__ <= 1100) // for VC6 - non standard namespace std {} #endif using namespace std; #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif namespace { // The functions must be in alphabetical order: enum OPCODE { cAbs, cAcos, #ifndef NO_ASINH cAcosh, #endif cAsin, #ifndef NO_ASINH cAsinh, #endif cAtan, cAtan2, #ifndef NO_ASINH cAtanh, #endif cCeil, cCos, cCosh, cCot, cCsc, #ifndef DISABLE_EVAL cEval, #endif cExp, cFloor, cIf, cInt, cLog, cLog10, cMax, cMin, cSec, cSin, cSinh, cSqrt, cTan, cTanh, // These do not need any ordering: cImmed, cJump, cNeg, cAdd, cSub, cMul, cDiv, cMod, cPow, cEqual, cLess, cGreater, cAnd, cOr, cDeg, cRad, cFCall, cPCall, #ifdef SUPPORT_OPTIMIZER cVar, cDup, cInv, #endif VarBegin }; struct FuncDefinition { const char* name; unsigned nameLength; unsigned opcode; unsigned params; // This is basically strcmp(), but taking 'nameLength' as string // length (not ending '\0'): bool operator<(const FuncDefinition& rhs) const { for(unsigned i = 0; i < nameLength; ++i) { if(i == rhs.nameLength) return false; const char c1 = name[i], c2 = rhs.name[i]; if(c1 < c2) return true; if(c2 < c1) return false; } return nameLength < rhs.nameLength; } }; // This list must be in alphabetical order: const FuncDefinition Functions[]= { { "abs", 3, cAbs, 1 }, { "acos", 4, cAcos, 1 }, #ifndef NO_ASINH { "acosh", 5, cAcosh, 1 }, #endif { "asin", 4, cAsin, 1 }, #ifndef NO_ASINH { "asinh", 5, cAsinh, 1 }, #endif { "atan", 4, cAtan, 1 }, { "atan2", 5, cAtan2, 2 }, #ifndef NO_ASINH { "atanh", 5, cAtanh, 1 }, #endif { "ceil", 4, cCeil, 1 }, { "cos", 3, cCos, 1 }, { "cosh", 4, cCosh, 1 }, { "cot", 3, cCot, 1 }, { "csc", 3, cCsc, 1 }, #ifndef DISABLE_EVAL { "eval", 4, cEval, 0 }, #endif { "exp", 3, cExp, 1 }, { "floor", 5, cFloor, 1 }, { "if", 2, cIf, 0 }, { "int", 3, cInt, 1 }, { "log", 3, cLog, 1 }, { "log10", 5, cLog10, 1 }, { "max", 3, cMax, 2 }, { "min", 3, cMin, 2 }, { "sec", 3, cSec, 1 }, { "sin", 3, cSin, 1 }, { "sinh", 4, cSinh, 1 }, { "sqrt", 4, cSqrt, 1 }, { "tan", 3, cTan, 1 }, { "tanh", 4, cTanh, 1 } }; const unsigned FUNC_AMOUNT = sizeof(Functions)/sizeof(Functions[0]); // BCB4 does not implement the standard lower_bound function. // This is used instead: const FuncDefinition* fp_lower_bound(const FuncDefinition* first, const FuncDefinition* last, const FuncDefinition& value) { while(first < last) { const FuncDefinition* middle = first+(last-first)/2; if(*middle < value) first = middle+1; else last = middle; } return last; } // Returns a pointer to the FuncDefinition instance which 'name' is // the same as the one given by 'F'. If no such function name exists, // returns 0. inline const FuncDefinition* FindFunction(const char* F) { FuncDefinition func = { F, 0, 0, 0 }; while(isalnum(F[func.nameLength])) ++func.nameLength; if(func.nameLength) { const FuncDefinition* found = fp_lower_bound(Functions, Functions+FUNC_AMOUNT, func); if(found == Functions+FUNC_AMOUNT || func < *found) return 0; return found; } return 0; } } //--------------------------------------------------------------------------- // Copy-on-write method //--------------------------------------------------------------------------- inline void FunctionParser::copyOnWrite() { if(data->referenceCounter > 1) { Data* oldData = data; data = new Data(*oldData); --(oldData->referenceCounter); data->referenceCounter = 1; } } //--------------------------------------------------------------------------- // Constructors and destructors //--------------------------------------------------------------------------- //=========================================================================== FunctionParser::FunctionParser(): parseErrorType(FP_NO_ERROR), evalErrorType(0), data(new Data) { data->referenceCounter = 1; } FunctionParser::~FunctionParser() { if(--(data->referenceCounter) == 0) { delete data; } } FunctionParser::FunctionParser(const FunctionParser& cpy): parseErrorType(cpy.parseErrorType), evalErrorType(cpy.evalErrorType), data(cpy.data) { ++(data->referenceCounter); } FunctionParser& FunctionParser::operator=(const FunctionParser& cpy) { if(data != cpy.data) { if(--(data->referenceCounter) == 0) delete data; parseErrorType = cpy.parseErrorType; evalErrorType = cpy.evalErrorType; data = cpy.data; ++(data->referenceCounter); } return *this; } FunctionParser::Data::Data(): useDegreeConversion(false), ByteCode(0), ByteCodeSize(0), Immed(0), ImmedSize(0), Stack(0), StackSize(0) {} FunctionParser::Data::~Data() { if(ByteCode) { delete[] ByteCode; ByteCode=0; } if(Immed) { delete[] Immed; Immed=0; } if(Stack) { delete[] Stack; Stack=0; } } // Makes a deep-copy of Data: FunctionParser::Data::Data(const Data& cpy): varAmount(cpy.varAmount), useDegreeConversion(cpy.useDegreeConversion), Variables(cpy.Variables), Constants(cpy.Constants), FuncPtrNames(cpy.FuncPtrNames), FuncPtrs(cpy.FuncPtrs), FuncParserNames(cpy.FuncParserNames), FuncParsers(cpy.FuncParsers), ByteCode(0), ByteCodeSize(cpy.ByteCodeSize), Immed(0), ImmedSize(cpy.ImmedSize), Stack(0), StackSize(cpy.StackSize) { if(ByteCodeSize) ByteCode = new unsigned[ByteCodeSize]; if(ImmedSize) Immed = new double[ImmedSize]; if(StackSize) Stack = new double[StackSize]; // MSVC doesn't allow i used twice in for loops for(unsigned i=0; i& dest) { unsigned varNumber = VarBegin; unsigned ind1 = 0, ind2; while(ind1 < Vars.size()) { if(!isalpha(Vars[ind1]) && Vars[ind1]!='_') return false; for(ind2=ind1+1; ind2FuncParserNames) != data->FuncParserNames.end() || FindVariable(n, data->FuncPtrNames) != data->FuncPtrNames.end()) return false; copyOnWrite(); data->Constants[name] = value; return true; } return false; } // Function pointers bool FunctionParser::AddFunction(const std::string& name, FunctionPtr func, unsigned paramsAmount) { if(paramsAmount == 0) return false; // Currently must be at least one if(isValidName(name)) { const char* n = name.c_str(); if(FindVariable(n, data->FuncParserNames) != data->FuncParserNames.end() || FindConstant(n) != data->Constants.end()) return false; copyOnWrite(); data->FuncPtrNames[name] = data->FuncPtrs.size(); data->FuncPtrs.push_back(Data::FuncPtrData(func, paramsAmount)); return true; } return false; } bool FunctionParser::checkRecursiveLinking(const FunctionParser* fp) const { if(fp == this) return true; for(unsigned i=0; idata->FuncParsers.size(); ++i) if(checkRecursiveLinking(fp->data->FuncParsers[i])) return true; return false; } bool FunctionParser::AddFunction(const std::string& name, FunctionParser& parser) { if(parser.data->varAmount == 0) // Currently must be at least one return false; if(isValidName(name)) { const char* n = name.c_str(); if(FindVariable(n, data->FuncPtrNames) != data->FuncPtrNames.end() || FindConstant(n) != data->Constants.end()) return false; if(checkRecursiveLinking(&parser)) return false; copyOnWrite(); data->FuncParserNames[name] = data->FuncParsers.size(); data->FuncParsers.push_back(&parser); return true; } return false; } // Main parsing function // --------------------- int FunctionParser::Parse(const std::string& Function, const std::string& Vars, bool useDegrees) { copyOnWrite(); data->Variables.clear(); if(!ParseVars(Vars, data->Variables)) { parseErrorType = INVALID_VARS; return Function.size(); } data->varAmount = data->Variables.size(); // this is for Eval() const char* Func = Function.c_str(); parseErrorType = FP_NO_ERROR; int Result = CheckSyntax(Func); if(Result>=0) return Result; data->useDegreeConversion = useDegrees; if(!Compile(Func)) return Function.size(); data->Variables.clear(); parseErrorType = FP_NO_ERROR; return -1; } namespace { // Is given char an operator? inline bool IsOperator(int c) { return strchr("+-*/%^=<>&|",c)!=NULL; } // skip whitespace inline void sws(const char* F, int& Ind) { while(F[Ind] && isspace(F[Ind])) ++Ind; } } // Returns an iterator to the variable with the same name as 'F', or to // Variables.end() if no such variable exists: inline FunctionParser::Data::VarMap_t::const_iterator FunctionParser::FindVariable(const char* F, const Data::VarMap_t& vars) const { if(vars.size()) { unsigned ind = 0; while(isalnum(F[ind]) || F[ind] == '_') ++ind; if(ind) { string name(F, ind); return vars.find(name); } } return vars.end(); } inline FunctionParser::Data::ConstMap_t::const_iterator FunctionParser::FindConstant(const char* F) const { if(data->Constants.size()) { unsigned ind = 0; while(isalnum(F[ind]) || F[ind] == '_') ++ind; if(ind) { string name(F, ind); return data->Constants.find(name); } } return data->Constants.end(); } //--------------------------------------------------------------------------- // Check function string syntax // ---------------------------- int FunctionParser::CheckSyntax(const char* Function) { const Data::VarMap_t& Variables = data->Variables; const Data::ConstMap_t& Constants = data->Constants; const Data::VarMap_t& FuncPtrNames = data->FuncPtrNames; const Data::VarMap_t& FuncParserNames = data->FuncParserNames; vector functionParenthDepth; int Ind=0, ParenthCnt=0, c; char* Ptr; while(true) { sws(Function, Ind); c=Function[Ind]; // Check for valid operand (must appear) // Check for leading - if(c=='-') { sws(Function, ++Ind); c=Function[Ind]; } if(c==0) { parseErrorType=PREMATURE_EOS; return Ind; } // Check for math function bool foundFunc = false; const FuncDefinition* fptr = FindFunction(&Function[Ind]); if(fptr) { Ind += fptr->nameLength; foundFunc = true; } else { // Check for user-defined function Data::VarMap_t::const_iterator fIter = FindVariable(&Function[Ind], FuncPtrNames); if(fIter != FuncPtrNames.end()) { Ind += fIter->first.size(); foundFunc = true; } else { Data::VarMap_t::const_iterator pIter = FindVariable(&Function[Ind], FuncParserNames); if(pIter != FuncParserNames.end()) { Ind += pIter->first.size(); foundFunc = true; } } } if(foundFunc) { sws(Function, Ind); c = Function[Ind]; if(c!='(') { parseErrorType=EXPECT_PARENTH_FUNC; return Ind; } functionParenthDepth.push_back(ParenthCnt+1); } // Check for opening parenthesis if(c=='(') { ++ParenthCnt; sws(Function, ++Ind); if(Function[Ind]==')') { parseErrorType=EMPTY_PARENTH; return Ind;} continue; } // Check for number if(isdigit(c) || (c=='.' && isdigit(Function[Ind+1]))) { strtod(&Function[Ind], &Ptr); Ind += int(Ptr-&Function[Ind]); sws(Function, Ind); c = Function[Ind]; } else { // Check for variable Data::VarMap_t::const_iterator vIter = FindVariable(&Function[Ind], Variables); if(vIter != Variables.end()) Ind += vIter->first.size(); else { // Check for constant Data::ConstMap_t::const_iterator cIter = FindConstant(&Function[Ind]); if(cIter != Constants.end()) Ind += cIter->first.size(); else { parseErrorType=SYNTAX_ERROR; return Ind; } } sws(Function, Ind); c = Function[Ind]; } // Check for closing parenthesis while(c==')') { if(functionParenthDepth.size() && functionParenthDepth.back() == ParenthCnt) functionParenthDepth.pop_back(); if((--ParenthCnt)<0) { parseErrorType=MISM_PARENTH; return Ind; } sws(Function, ++Ind); c=Function[Ind]; } // If we get here, we have a legal operand and now a legal operator or // end of string must follow // Check for EOS if(c==0) break; // The only way to end the checking loop without error // Check for operator if(!IsOperator(c) && (c != ',' || functionParenthDepth.empty() || functionParenthDepth.back() != ParenthCnt)) { parseErrorType=EXPECT_OPERATOR; return Ind; } // If we get here, we have an operand and an operator; the next loop will // check for another operand (must appear) ++Ind; } // while // Check that all opened parentheses are also closed if(ParenthCnt>0) { parseErrorType=MISSING_PARENTH; return Ind; } // The string is ok parseErrorType=FP_NO_ERROR; return -1; } // Compile function string to bytecode // ----------------------------------- bool FunctionParser::Compile(const char* Function) { if(data->ByteCode) { delete[] data->ByteCode; data->ByteCode=0; } if(data->Immed) { delete[] data->Immed; data->Immed=0; } if(data->Stack) { delete[] data->Stack; data->Stack=0; } vector byteCode; byteCode.reserve(1024); tempByteCode = &byteCode; vector immed; immed.reserve(1024); tempImmed = &immed; data->StackSize = StackPtr = 0; CompileExpression(Function, 0); if(parseErrorType != FP_NO_ERROR) return false; data->ByteCodeSize = byteCode.size(); data->ImmedSize = immed.size(); if(data->ByteCodeSize) { data->ByteCode = new unsigned[data->ByteCodeSize]; memcpy(data->ByteCode, &byteCode[0], sizeof(unsigned)*data->ByteCodeSize); } if(data->ImmedSize) { data->Immed = new double[data->ImmedSize]; memcpy(data->Immed, &immed[0], sizeof(double)*data->ImmedSize); } if(data->StackSize) data->Stack = new double[data->StackSize]; return true; } inline void FunctionParser::AddCompiledByte(unsigned c) { tempByteCode->push_back(c); } inline void FunctionParser::AddImmediate(double i) { tempImmed->push_back(i); } inline void FunctionParser::AddFunctionOpcode(unsigned opcode) { if(data->useDegreeConversion) switch(opcode) { case cCos: case cCosh: case cCot: case cCsc: case cSec: case cSin: case cSinh: case cTan: case cTanh: AddCompiledByte(cRad); } AddCompiledByte(opcode); if(data->useDegreeConversion) switch(opcode) { case cAcos: #ifndef NO_ASINH case cAcosh: case cAsinh: case cAtanh: #endif case cAsin: case cAtan: case cAtan2: AddCompiledByte(cDeg); } } inline void FunctionParser::incStackPtr() { if(++StackPtr > data->StackSize) ++(data->StackSize); } // Compile if() int FunctionParser::CompileIf(const char* F, int ind) { int ind2 = CompileExpression(F, ind, true); // condition sws(F, ind2); if(F[ind2] != ',') { parseErrorType=ILL_PARAMS_AMOUNT; return ind2; } AddCompiledByte(cIf); unsigned curByteCodeSize = tempByteCode->size(); AddCompiledByte(0); // Jump index; to be set later AddCompiledByte(0); // Immed jump index; to be set later --StackPtr; ind2 = CompileExpression(F, ind2+1, true); // then sws(F, ind2); if(F[ind2] != ',') { parseErrorType=ILL_PARAMS_AMOUNT; return ind2; } AddCompiledByte(cJump); unsigned curByteCodeSize2 = tempByteCode->size(); unsigned curImmedSize2 = tempImmed->size(); AddCompiledByte(0); // Jump index; to be set later AddCompiledByte(0); // Immed jump index; to be set later --StackPtr; ind2 = CompileExpression(F, ind2+1, true); // else sws(F, ind2); if(F[ind2] != ')') { parseErrorType=ILL_PARAMS_AMOUNT; return ind2; } // Set jump indices (*tempByteCode)[curByteCodeSize] = curByteCodeSize2+1; (*tempByteCode)[curByteCodeSize+1] = curImmedSize2; (*tempByteCode)[curByteCodeSize2] = tempByteCode->size()-1; (*tempByteCode)[curByteCodeSize2+1] = tempImmed->size(); return ind2+1; } int FunctionParser::CompileFunctionParams(const char* F, int ind, unsigned requiredParams) { unsigned curStackPtr = StackPtr; int ind2 = CompileExpression(F, ind); if(StackPtr != curStackPtr+requiredParams) { parseErrorType=ILL_PARAMS_AMOUNT; return ind; } StackPtr -= requiredParams - 1; sws(F, ind2); return ind2+1; // F[ind2] is ')' } // Compiles element int FunctionParser::CompileElement(const char* F, int ind) { sws(F, ind); char c = F[ind]; if(c == '(') { ind = CompileExpression(F, ind+1); sws(F, ind); return ind+1; // F[ind] is ')' } if(isdigit(c) || c=='.' /*|| c=='-'*/) // Number { const char* startPtr = &F[ind]; char* endPtr; double val = strtod(startPtr, &endPtr); AddImmediate(val); AddCompiledByte(cImmed); incStackPtr(); return ind+(endPtr-startPtr); } if(isalpha(c) || c == '_') // Function, variable or constant { const FuncDefinition* func = FindFunction(F+ind); if(func) // is function { int ind2 = ind + func->nameLength; sws(F, ind2); // F[ind2] is '(' if(strcmp(func->name, "if") == 0) // "if" is a special case { return CompileIf(F, ind2+1); } #ifndef DISABLE_EVAL unsigned requiredParams = strcmp(func->name, "eval") == 0 ? data->Variables.size() : func->params; #else unsigned requiredParams = func->params; #endif ind2 = CompileFunctionParams(F, ind2+1, requiredParams); AddFunctionOpcode(func->opcode); return ind2; // F[ind2-1] is ')' } Data::VarMap_t::const_iterator vIter = FindVariable(F+ind, data->Variables); if(vIter != data->Variables.end()) // is variable { AddCompiledByte(vIter->second); incStackPtr(); return ind + vIter->first.size(); } Data::ConstMap_t::const_iterator cIter = FindConstant(F+ind); if(cIter != data->Constants.end()) // is constant { AddImmediate(cIter->second); AddCompiledByte(cImmed); incStackPtr(); return ind + cIter->first.size(); } Data::VarMap_t::const_iterator fIter = FindVariable(F+ind, data->FuncPtrNames); if(fIter != data->FuncPtrNames.end()) // is user-defined func pointer { unsigned index = fIter->second; int ind2 = ind + fIter->first.length(); sws(F, ind2); // F[ind2] is '(' ind2 = CompileFunctionParams(F, ind2+1, data->FuncPtrs[index].params); AddCompiledByte(cFCall); AddCompiledByte(index); return ind2; } Data::VarMap_t::const_iterator pIter = FindVariable(F+ind, data->FuncParserNames); if(pIter != data->FuncParserNames.end()) // is user-defined func parser { unsigned index = pIter->second; int ind2 = ind + pIter->first.length(); sws(F, ind2); // F[ind2] is '(' ind2 = CompileFunctionParams (F, ind2+1, data->FuncParsers[index]->data->varAmount); AddCompiledByte(cPCall); AddCompiledByte(index); return ind2; } } parseErrorType = UNEXPECTED_ERROR; return ind; } // Compiles '^' int FunctionParser::CompilePow(const char* F, int ind) { int ind2 = CompileElement(F, ind); sws(F, ind2); while(F[ind2] == '^') { ind2 = CompileUnaryMinus(F, ind2+1); sws(F, ind2); AddCompiledByte(cPow); --StackPtr; } return ind2; } // Compiles unary '-' int FunctionParser::CompileUnaryMinus(const char* F, int ind) { sws(F, ind); if(F[ind] == '-') { int ind2 = ind+1; sws(F, ind2); ind2 = CompilePow(F, ind2); sws(F, ind2); // if we are negating a constant, negate the constant itself: if(tempByteCode->back() == cImmed) tempImmed->back() = -tempImmed->back(); // if we are negating a negation, we can remove both: else if(tempByteCode->back() == cNeg) tempByteCode->pop_back(); else AddCompiledByte(cNeg); return ind2; } int ind2 = CompilePow(F, ind); sws(F, ind2); return ind2; } // Compiles '*', '/' and '%' int FunctionParser::CompileMult(const char* F, int ind) { int ind2 = CompileUnaryMinus(F, ind); sws(F, ind2); char op; while((op = F[ind2]) == '*' || op == '/' || op == '%') { ind2 = CompileUnaryMinus(F, ind2+1); sws(F, ind2); switch(op) { case '*': AddCompiledByte(cMul); break; case '/': AddCompiledByte(cDiv); break; case '%': AddCompiledByte(cMod); break; } --StackPtr; } return ind2; } // Compiles '+' and '-' int FunctionParser::CompileAddition(const char* F, int ind) { int ind2 = CompileMult(F, ind); sws(F, ind2); char op; while((op = F[ind2]) == '+' || op == '-') { ind2 = CompileMult(F, ind2+1); sws(F, ind2); AddCompiledByte(op=='+' ? cAdd : cSub); --StackPtr; } return ind2; } // Compiles '=', '<' and '>' int FunctionParser::CompileComparison(const char* F, int ind) { int ind2 = CompileAddition(F, ind); sws(F, ind2); char op; while((op = F[ind2]) == '=' || op == '<' || op == '>') { ind2 = CompileAddition(F, ind2+1); sws(F, ind2); switch(op) { case '=': AddCompiledByte(cEqual); break; case '<': AddCompiledByte(cLess); break; case '>': AddCompiledByte(cGreater); break; } --StackPtr; } return ind2; } // Compiles '&' int FunctionParser::CompileAnd(const char* F, int ind) { int ind2 = CompileComparison(F, ind); sws(F, ind2); while(F[ind2] == '&') { ind2 = CompileComparison(F, ind2+1); sws(F, ind2); AddCompiledByte(cAnd); --StackPtr; } return ind2; } // Compiles '|' int FunctionParser::CompileOr(const char* F, int ind) { int ind2 = CompileAnd(F, ind); sws(F, ind2); while(F[ind2] == '|') { ind2 = CompileAnd(F, ind2+1); sws(F, ind2); AddCompiledByte(cOr); --StackPtr; } return ind2; } // Compiles ',' int FunctionParser::CompileExpression(const char* F, int ind, bool stopAtComma) { int ind2 = CompileOr(F, ind); sws(F, ind2); if(stopAtComma) return ind2; while(F[ind2] == ',') { ind2 = CompileOr(F, ind2+1); sws(F, ind2); } return ind2; } // Return parse error message // -------------------------- const char* FunctionParser::ErrorMsg() const { if(parseErrorType != FP_NO_ERROR) return ParseErrorMessage[parseErrorType]; return 0; } //--------------------------------------------------------------------------- // Function evaluation //--------------------------------------------------------------------------- //=========================================================================== namespace { inline int doubleToInt(double d) { return d<0 ? -int((-d)+.5) : int(d+.5); } inline double Min(double d1, double d2) { return d1d2 ? d1 : d2; } inline double DegreesToRadians(double degrees) { return degrees*(M_PI/180.0); } inline double RadiansToDegrees(double radians) { return radians*(180.0/M_PI); } } double FunctionParser::Eval(const double* Vars) { const unsigned* const ByteCode = data->ByteCode; const double* const Immed = data->Immed; double* const Stack = data->Stack; const unsigned ByteCodeSize = data->ByteCodeSize; unsigned IP, DP=0; int SP=-1; for(IP=0; IP 1) { evalErrorType=4; return 0; } Stack[SP] = acos(Stack[SP]); break; #ifndef NO_ASINH case cAcosh: Stack[SP] = acosh(Stack[SP]); break; #endif case cAsin: if(Stack[SP] < -1 || Stack[SP] > 1) { evalErrorType=4; return 0; } Stack[SP] = asin(Stack[SP]); break; #ifndef NO_ASINH case cAsinh: Stack[SP] = asinh(Stack[SP]); break; #endif case cAtan: Stack[SP] = atan(Stack[SP]); break; case cAtan2: Stack[SP-1] = atan2(Stack[SP-1], Stack[SP]); --SP; break; #ifndef NO_ASINH case cAtanh: Stack[SP] = atanh(Stack[SP]); break; #endif case cCeil: Stack[SP] = ceil(Stack[SP]); break; case cCos: Stack[SP] = cos(Stack[SP]); break; case cCosh: Stack[SP] = cosh(Stack[SP]); break; case cCot: { double t = tan(Stack[SP]); if(t == 0) { evalErrorType=1; return 0; } Stack[SP] = 1/t; break; } case cCsc: { double s = sin(Stack[SP]); if(s == 0) { evalErrorType=1; return 0; } Stack[SP] = 1/s; break; } #ifndef DISABLE_EVAL case cEval: { data->Stack = new double[data->StackSize]; double retVal = Eval(&Stack[SP-data->varAmount+1]); delete[] data->Stack; data->Stack = Stack; SP -= data->varAmount-1; Stack[SP] = retVal; break; } #endif case cExp: Stack[SP] = exp(Stack[SP]); break; case cFloor: Stack[SP] = floor(Stack[SP]); break; case cIf: { unsigned jumpAddr = ByteCode[++IP]; unsigned immedAddr = ByteCode[++IP]; if(doubleToInt(Stack[SP]) == 0) { IP = jumpAddr; DP = immedAddr; } --SP; break; } case cInt: Stack[SP] = floor(Stack[SP]+.5); break; case cLog: if(Stack[SP] <= 0) { evalErrorType=3; return 0; } Stack[SP] = log(Stack[SP]); break; case cLog10: if(Stack[SP] <= 0) { evalErrorType=3; return 0; } Stack[SP] = log10(Stack[SP]); break; case cMax: Stack[SP-1] = Max(Stack[SP-1], Stack[SP]); --SP; break; case cMin: Stack[SP-1] = Min(Stack[SP-1], Stack[SP]); --SP; break; case cSec: { double c = cos(Stack[SP]); if(c == 0) { evalErrorType=1; return 0; } Stack[SP] = 1/c; break; } case cSin: Stack[SP] = sin(Stack[SP]); break; case cSinh: Stack[SP] = sinh(Stack[SP]); break; case cSqrt: if(Stack[SP] < 0) { evalErrorType=2; return 0; } Stack[SP] = sqrt(Stack[SP]); break; case cTan: Stack[SP] = tan(Stack[SP]); break; case cTanh: Stack[SP] = tanh(Stack[SP]); break; // Misc: case cImmed: Stack[++SP] = Immed[DP++]; break; case cJump: DP = ByteCode[IP+2]; IP = ByteCode[IP+1]; break; // Operators: case cNeg: Stack[SP] = -Stack[SP]; break; case cAdd: Stack[SP-1] += Stack[SP]; --SP; break; case cSub: Stack[SP-1] -= Stack[SP]; --SP; break; case cMul: Stack[SP-1] *= Stack[SP]; --SP; break; case cDiv: if(Stack[SP] == 0) { evalErrorType=1; return 0; } Stack[SP-1] /= Stack[SP]; --SP; break; case cMod: if(Stack[SP] == 0) { evalErrorType=1; return 0; } Stack[SP-1] = fmod(Stack[SP-1], Stack[SP]); --SP; break; case cPow: Stack[SP-1] = pow(Stack[SP-1], Stack[SP]); --SP; break; case cEqual: Stack[SP-1] = (Stack[SP-1] == Stack[SP]); --SP; break; case cLess: Stack[SP-1] = (Stack[SP-1] < Stack[SP]); --SP; break; case cGreater: Stack[SP-1] = (Stack[SP-1] > Stack[SP]); --SP; break; case cAnd: Stack[SP-1] = (doubleToInt(Stack[SP-1]) && doubleToInt(Stack[SP])); --SP; break; case cOr: Stack[SP-1] = (doubleToInt(Stack[SP-1]) || doubleToInt(Stack[SP])); --SP; break; // Degrees-radians conversion: case cDeg: Stack[SP] = RadiansToDegrees(Stack[SP]); break; case cRad: Stack[SP] = DegreesToRadians(Stack[SP]); break; // User-defined function calls: case cFCall: { unsigned index = ByteCode[++IP]; unsigned params = data->FuncPtrs[index].params; double retVal = data->FuncPtrs[index].ptr(&Stack[SP-params+1]); SP -= params-1; Stack[SP] = retVal; break; } case cPCall: { unsigned index = ByteCode[++IP]; unsigned params = data->FuncParsers[index]->data->varAmount; double retVal = data->FuncParsers[index]->Eval(&Stack[SP-params+1]); SP -= params-1; Stack[SP] = retVal; break; } #ifdef SUPPORT_OPTIMIZER case cVar: break; // Paranoia. These should never exist case cDup: Stack[SP+1] = Stack[SP]; ++SP; break; case cInv: if(Stack[SP] == 0.0) { evalErrorType=1; return 0; } Stack[SP] = 1.0/Stack[SP]; break; #endif // Variables: default: Stack[++SP] = Vars[ByteCode[IP]-VarBegin]; } } evalErrorType=0; return Stack[SP]; } #ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT namespace { inline void printHex(std::ostream& dest, unsigned n) { dest.width(8); dest.fill('0'); hex(dest); //uppercase(dest); dest << n; } } void FunctionParser::PrintByteCode(std::ostream& dest) const { const unsigned* const ByteCode = data->ByteCode; const double* const Immed = data->Immed; for(unsigned IP=0, DP=0; IPByteCodeSize; ++IP) { printHex(dest, IP); dest << ": "; unsigned opcode = ByteCode[IP]; switch(opcode) { case cIf: dest << "jz\t"; printHex(dest, ByteCode[IP+1]+1); dest << endl; IP += 2; break; case cJump: dest << "jump\t"; printHex(dest, ByteCode[IP+1]+1); dest << endl; IP += 2; break; case cImmed: dest.precision(10); dest << "push\t" << Immed[DP++] << endl; break; case cFCall: { unsigned index = ByteCode[++IP]; Data::VarMap_t::const_iterator iter = data->FuncPtrNames.begin(); while(iter->second != index) ++iter; dest << "call\t" << iter->first << endl; break; } case cPCall: { unsigned index = ByteCode[++IP]; Data::VarMap_t::const_iterator iter = data->FuncParserNames.begin(); while(iter->second != index) ++iter; dest << "call\t" << iter->first << endl; break; } default: if(opcode < VarBegin) { string n; switch(opcode) { case cNeg: n = "neg"; break; case cAdd: n = "add"; break; case cSub: n = "sub"; break; case cMul: n = "mul"; break; case cDiv: n = "div"; break; case cMod: n = "mod"; break; case cPow: n = "pow"; break; case cEqual: n = "eq"; break; case cLess: n = "lt"; break; case cGreater: n = "gt"; break; case cAnd: n = "and"; break; case cOr: n = "or"; break; case cDeg: n = "deg"; break; case cRad: n = "rad"; break; #ifndef DISABLE_EVAL case cEval: n = "call\t0"; break; #endif #ifdef SUPPORT_OPTIMIZER case cVar: n = "(var)"; break; case cDup: n = "dup"; break; case cInv: n = "inv"; break; #endif default: n = Functions[opcode-cAbs].name; } dest << n << endl; } else { dest << "push\tVar" << opcode-VarBegin << endl; } } } } #endif //======================================================================== // Optimization code was contributed by Bisqwit (http://iki.fi/bisqwit/) //======================================================================== #ifdef SUPPORT_OPTIMIZER #include #include #define CONSTANT_E 2.71828182845904509080 // exp(1) #define CONSTANT_PI M_PI // atan2(0,-1) #define CONSTANT_L10 2.30258509299404590109 // log(10) #define CONSTANT_L10I 0.43429448190325176116 // 1/log(10) #define CONSTANT_L10E CONSTANT_L10I // log10(e) #define CONSTANT_L10EI CONSTANT_L10 // 1/log10(e) #define CONSTANT_DR (180.0 / M_PI) // 180/pi #define CONSTANT_RD (M_PI / 180.0) // pi/180 namespace { class compres { // states: 0=false, 1=true, 2=unknown public: compres(bool b) : state(b) {} compres(char v) : state(v) {} // is it? operator bool() const { return state != 0; } // is it not? bool operator! () const { return state != 1; } bool operator==(bool b) const { return (state != 0) != !b; } bool operator!=(bool b) const { return (state != 0) != b; } private: char state; }; const compres maybe = (char)2; struct CodeTree; class SubTree { CodeTree *tree; bool sign; // Only possible when parent is cAdd or cMul inline void flipsign() { sign = !sign; } public: SubTree(); SubTree(double value); SubTree(const SubTree &b); SubTree(const CodeTree &b); ~SubTree(); const SubTree &operator= (const SubTree &b); const SubTree &operator= (const CodeTree &b); bool getsign() const { return sign; } const CodeTree* operator-> () const { return tree; } const CodeTree& operator* () const { return *tree; } struct CodeTree* operator-> () { return tree; } struct CodeTree& operator* () { return *tree; } bool operator< (const SubTree& b) const; bool operator== (const SubTree& b) const; void Negate(); // Note: Parent must be cAdd void Invert(); // Note: Parent must be cMul void CheckConstNeg(); void CheckConstInv(); }; bool IsNegate(const SubTree &p1, const SubTree &p2); bool IsInverse(const SubTree &p1, const SubTree &p2); typedef list paramlist; struct CodeTreeData { paramlist args; private: unsigned op; // Operation double value; // In case of cImmed unsigned var; // In case of cVar unsigned funcno; // In case of cFCall, cPCall public: CodeTreeData() : op(cAdd) {} ~CodeTreeData() {} void SetOp(unsigned newop) { op=newop; } void SetFuncNo(unsigned newno) { funcno=newno; } unsigned GetFuncNo() const { return funcno; } bool IsFunc() const { return op == cFCall || op == cPCall; } bool IsImmed() const { return op == cImmed; } bool IsVar() const { return op == cVar; } inline unsigned GetOp() const { return op; } inline double GetImmed() const { return value; } inline unsigned GetVar() const { return var; } void AddParam(const SubTree &p) { args.push_back(p); } void SetVar(unsigned v) { args.clear(); op = cVar; var = v; } void SetImmed(double v) { args.clear(); op = cImmed; value = orig = v; inverted = negated = false; } void NegateImmed() { negated = !negated; UpdateValue(); } void InvertImmed() { inverted = !inverted; UpdateValue(); } bool IsOriginal() const { return !(IsInverted() || IsNegated()); } bool IsInverted() const { return inverted; } bool IsNegated() const { return negated; } bool IsInvertedOriginal() const { return IsInverted() && !IsNegated(); } bool IsNegatedOriginal() const { return !IsInverted() && IsNegated(); } private: void UpdateValue() { value = orig; if(IsInverted()) { value = 1.0 / value; // FIXME: potential divide by zero. } if(IsNegated()) value = -value; } double orig; bool inverted; bool negated; protected: // Ensure we don't accidentally copy this void operator=(const CodeTreeData &b); }; class CodeTreeDataPtr { typedef pair p_t; typedef p_t* pp; mutable pp p; void Alloc() const { ++p->second; } void Dealloc() const { if(!--p->second) delete p; p = 0; } void PrepareForWrite() { // We're ready if we're the only owner. if(p->second == 1) return; // Then make a clone. p_t *newtree = new p_t(p->first, 1); // Forget the old Dealloc(); // Keep the new p = newtree; } public: CodeTreeDataPtr() : p(new p_t) { p->second = 1; } CodeTreeDataPtr(const CodeTreeDataPtr &b): p(b.p) { Alloc(); } ~CodeTreeDataPtr() { Dealloc(); } const CodeTreeDataPtr &operator= (const CodeTreeDataPtr &b) { b.Alloc(); Dealloc(); p = b.p; return *this; } const CodeTreeData *operator-> () const { return &p->first; } const CodeTreeData &operator* () const { return p->first; } CodeTreeData *operator-> () { PrepareForWrite(); return &p->first; } CodeTreeData &operator* () { PrepareForWrite(); return p->first; } void Shock(); }; #define CHECKCONSTNEG(item, op) \ ((op)==cMul) \ ? (item).CheckConstInv() \ : (item).CheckConstNeg() struct CodeTree { CodeTreeDataPtr data; private: typedef paramlist::iterator pit; typedef paramlist::const_iterator pcit; /* template inline void chk() const { } */ public: const pcit GetBegin() const { return data->args.begin(); } const pcit GetEnd() const { return data->args.end(); } const pit GetBegin() { return data->args.begin(); } const pit GetEnd() { return data->args.end(); } const SubTree& getp0() const { /*chk<1>();*/pcit tmp=GetBegin(); return *tmp; } const SubTree& getp1() const { /*chk<2>();*/pcit tmp=GetBegin(); ++tmp; return *tmp; } const SubTree& getp2() const { /*chk<3>();*/pcit tmp=GetBegin(); ++tmp; ++tmp; return *tmp; } unsigned GetArgCount() const { return data->args.size(); } void Erase(const pit p) { data->args.erase(p); } SubTree& getp0() { /*chk<1>();*/pit tmp=GetBegin(); return *tmp; } SubTree& getp1() { /*chk<2>();*/pit tmp=GetBegin(); ++tmp; return *tmp; } SubTree& getp2() { /*chk<3>();*/pit tmp=GetBegin(); ++tmp; ++tmp; return *tmp; } // set void SetImmed(double v) { data->SetImmed(v); } void SetOp(unsigned op) { data->SetOp(op); } void SetVar(unsigned v) { data->SetVar(v); } // get double GetImmed() const { return data->GetImmed(); } unsigned GetVar() const { return data->GetVar(); } unsigned GetOp() const { return data->GetOp(); } // test bool IsImmed() const { return data->IsImmed(); } bool IsVar() const { return data->IsVar(); } // act void AddParam(const SubTree &p) { data->AddParam(p); } void NegateImmed() { data->NegateImmed(); } // don't use when op!=cImmed void InvertImmed() { data->InvertImmed(); } // don't use when op!=cImmed compres NonZero() const { if(!IsImmed()) return maybe; return GetImmed() != 0.0; } compres IsPositive() const { if(!IsImmed()) return maybe; return GetImmed() > 0.0; } private: struct ConstList { double voidvalue; list cp; double value; unsigned size() const { return cp.size(); } }; struct ConstList BuildConstList(); void KillConst(const ConstList &cl) { for(list::const_iterator i=cl.cp.begin(); i!=cl.cp.end(); ++i) Erase(*i); } void FinishConst(const ConstList &cl) { if(cl.value != cl.voidvalue && cl.size() > 1) AddParam(cl.value); if(cl.value == cl.voidvalue || cl.size() > 1) KillConst(cl); } public: CodeTree() {} CodeTree(double v) { SetImmed(v); } CodeTree(unsigned op, const SubTree &p) { SetOp(op); AddParam(p); } CodeTree(unsigned op, const SubTree &p1, const SubTree &p2) { SetOp(op); AddParam(p1); AddParam(p2); } bool operator== (const CodeTree& b) const; bool operator< (const CodeTree& b) const; private: bool IsSortable() const { switch(GetOp()) { case cAdd: case cMul: case cEqual: case cAnd: case cOr: case cMax: case cMin: return true; default: return false; } } void SortIfPossible() { if(IsSortable()) { data->args.sort(); } } void ReplaceWithConst(double value) { SetImmed(value); /* REMEMBER TO CALL CheckConstInv / CheckConstNeg * FOR PARENT SubTree, OR MAYHEM HAPPENS */ } void ReplaceWith(const CodeTree &b) { // If b is child of *this, mayhem // happens. So we first make a clone // and then proceed with copy. CodeTreeDataPtr tmp = b.data; tmp.Shock(); data = tmp; } void ReplaceWith(unsigned op, const SubTree &p) { ReplaceWith(CodeTree(op, p)); } void ReplaceWith(unsigned op, const SubTree &p1, const SubTree &p2) { ReplaceWith(CodeTree(op, p1, p2)); } void OptimizeConflict() { // This optimization does this: x-x = 0, x/x = 1, a+b-a = b. if(GetOp() == cAdd || GetOp() == cMul) { Redo: pit a, b; for(a=GetBegin(); a!=GetEnd(); ++a) { for(b=GetBegin(); ++b != GetEnd(); ) { const SubTree &p1 = *a; const SubTree &p2 = *b; if(GetOp() == cMul ? IsInverse(p1,p2) : IsNegate(p1,p2)) { // These parameters complement each others out Erase(b); Erase(a); goto Redo; } } } } OptimizeRedundant(); } void OptimizeRedundant() { // This optimization does this: min()=0, max()=0, add()=0, mul()=1 if(!GetArgCount()) { if(GetOp() == cAdd || GetOp() == cMin || GetOp() == cMax) ReplaceWithConst(0); else if(GetOp() == cMul) ReplaceWithConst(1); return; } // And this: mul(x) = x, min(x) = x, max(x) = x, add(x) = x if(GetArgCount() == 1) { if(GetOp() == cMul || GetOp() == cAdd || GetOp() == cMin || GetOp() == cMax) if(!getp0().getsign()) ReplaceWith(*getp0()); } OptimizeDoubleNegations(); } void OptimizeDoubleNegations() { if(GetOp() == cAdd) { // Eschew double negations // If any of the elements is cMul // and has a numeric constant, negate // the constant and negate sign. for(pit a=GetBegin(); a!=GetEnd(); ++a) { SubTree &pa = *a; if(pa.getsign() && pa->GetOp() == cMul) { CodeTree &p = *pa; for(pit b=p.GetBegin(); b!=p.GetEnd(); ++b) { SubTree &pb = *b; if(pb->IsImmed()) { pb.Negate(); pa.Negate(); break; } } } } } if(GetOp() == cMul) { // If any of the elements is cPow // and has a numeric exponent, negate // the exponent and negate sign. for(pit a=GetBegin(); a!=GetEnd(); ++a) { SubTree &pa = *a; if(pa.getsign() && pa->GetOp() == cPow) { CodeTree &p = *pa; if(p.getp1()->IsImmed()) { // negate ok for pow when op=cImmed p.getp1().Negate(); pa.Negate(); } } } } } void OptimizeConstantMath1() { // This optimization does three things: // - For adding groups: // Constants are added together. // - For multiplying groups: // Constants are multiplied together. // - For function calls: // If all parameters are constants, // the call is replaced with constant value. // First, do this: OptimizeAddMulFlat(); switch(GetOp()) { case cAdd: { ConstList cl = BuildConstList(); FinishConst(cl); break; } case cMul: { ConstList cl = BuildConstList(); if(cl.value == 0.0) ReplaceWithConst(0.0); else FinishConst(cl); break; } #define ConstantUnaryFun(token, fun) \ case token: { const SubTree &p0 = getp0(); \ if(p0->IsImmed()) ReplaceWithConst(fun(p0->GetImmed())); \ break; } #define ConstantBinaryFun(token, fun) \ case token: { const SubTree &p0 = getp0(); \ const SubTree &p1 = getp1(); \ if(p0->IsImmed() && \ p1->IsImmed()) ReplaceWithConst(fun(p0->GetImmed(), p1->GetImmed())); \ break; } // FIXME: potential invalid parameters for functions // can cause exceptions here ConstantUnaryFun(cAbs, fabs); ConstantUnaryFun(cAcos, acos); ConstantUnaryFun(cAsin, asin); ConstantUnaryFun(cAtan, atan); ConstantUnaryFun(cCeil, ceil); ConstantUnaryFun(cCos, cos); ConstantUnaryFun(cCosh, cosh); ConstantUnaryFun(cFloor, floor); ConstantUnaryFun(cLog, log); ConstantUnaryFun(cSin, sin); ConstantUnaryFun(cSinh, sinh); ConstantUnaryFun(cTan, tan); ConstantUnaryFun(cTanh, tanh); ConstantBinaryFun(cAtan2, atan2); ConstantBinaryFun(cMax, Max); ConstantBinaryFun(cMin, Min); ConstantBinaryFun(cMod, fmod); // not a func, but belongs here too ConstantBinaryFun(cPow, pow); case cNeg: case cSub: case cDiv: /* Unreached (nonexistent operator) * TODO: internal error here? */ break; case cCot: case cCsc: case cSec: case cDeg: case cRad: case cLog10: case cSqrt: case cExp: /* Unreached (nonexistent function) * TODO: internal error here? */ break; } OptimizeConflict(); } void OptimizeAddMulFlat() { // This optimization flattens the topography of the tree. // Examples: // x + (y+z) = x+y+z // x * (y/z) = x*y/z // x / (y/z) = x/y*z if(GetOp() == cAdd || GetOp() == cMul) { // If children are same type as parent add them here for(pit b, a=GetBegin(); a!=GetEnd(); a=b) { const SubTree &pa = *a; b=a; ++b; if(pa->GetOp() != GetOp()) continue; // Child is same type for(pcit c=pa->GetBegin(); c!=pa->GetEnd(); ++c) { const SubTree &pb = *c; if(pa.getsign()) { // +a -(+b +c) // means b and c will be negated SubTree tmp = pb; if(GetOp() == cMul) tmp.Invert(); else tmp.Negate(); AddParam(tmp); } else AddParam(pb); } Erase(a); // Note: OptimizeConstantMath1() would be a good thing to call next. } } } void OptimizeLinearCombine() { // This optimization does the following: // // x*x*x*x -> x^4 // x+x+x+x -> x*4 // x*x -> x^2 // x/z/z -> // // Remove conflicts first, so we don't have to worry about signs. OptimizeConflict(); bool didchanges = false; if(GetOp() == cAdd || GetOp() == cMul) { Redo: for(pit a=GetBegin(); a!=GetEnd(); ++a) { const SubTree &pa = *a; list poslist; for(pit b=a; ++b!=GetEnd(); ) { const SubTree &pb = *b; if(*pa == *pb) poslist.push_back(b); } unsigned min = 2; if(poslist.size() >= min) { SubTree arvo = pa; bool negate = arvo.getsign(); double factor = poslist.size() + 1; if(negate) { arvo.Negate(); factor = -factor; } CodeTree tmp(GetOp()==cAdd ? cMul : cPow, arvo, factor); list::const_iterator j; for(j=poslist.begin(); j!=poslist.end(); ++j) Erase(*j); poslist.clear(); *a = tmp; didchanges = true; goto Redo; } } } if(didchanges) { // As a result, there might be need for this: OptimizeAddMulFlat(); // And this: OptimizeRedundant(); } } void OptimizeLogarithm() { /* This is basic logarithm math: pow(X,Y)/log(Y) = X log(X)/log(Y) = logY(X) log(X^Y) = log(X)*Y log(X*Y) = log(X)+log(Y) exp(log(X)*Y) = X^Y This function does these optimizations: pow(const_E, log(x)) = x pow(const_E, log(x)*y) = x^y pow(10, log(x)*const_L10I*y) = x^y pow(z, log(x)/log(z)*y) = x^y And this: log(x^z) = z * log(x) Which automatically causes these too: log(pow(const_E, x)) = x log(pow(y, x)) = x * log(y) log(pow(pow(const_E, y), x)) = x*y And it does this too: log(x) + log(y) + log(z) = log(x * y * z) log(x * exp(y)) = log(x) + y */ // Must be already in exponential form. // Optimize exponents before doing something. OptimizeExponents(); if(GetOp() == cLog) { // We should have one parameter for log() function. // If we don't, we're screwed. const SubTree &p = getp0(); if(p->GetOp() == cPow) { // Found log(x^y) SubTree p0 = p->getp0(); // x SubTree p1 = p->getp1(); // y // Build the new logarithm. CodeTree tmp(GetOp(), p0); // log(x) // Become log(x) * y ReplaceWith(cMul, tmp, p1); } else if(p->GetOp() == cMul) { // Redefine &p nonconst SubTree &p = getp0(); p->OptimizeAddMulFlat(); p->OptimizeExponents(); CHECKCONSTNEG(p, p->GetOp()); list adds; for(pit b, a = p->GetBegin(); a != p->GetEnd(); a=b) { SubTree &pa = *a; b=a; ++b; if(pa->GetOp() == cPow && pa->getp0()->IsImmed() && pa->getp0()->GetImmed() == CONSTANT_E) { adds.push_back(pa->getp1()); p->Erase(a); continue; } } if(adds.size()) { CodeTree tmp(cAdd, *this); list::const_iterator i; for(i=adds.begin(); i!=adds.end(); ++i) tmp.AddParam(*i); ReplaceWith(tmp); } } } if(GetOp() == cAdd) { // Check which ones are logs. list poslist; for(pit a=GetBegin(); a!=GetEnd(); ++a) { const SubTree &pa = *a; if(pa->GetOp() == cLog) poslist.push_back(a); } if(poslist.size() >= 2) { CodeTree tmp(cMul, 1.0); // eek list::const_iterator j; for(j=poslist.begin(); j!=poslist.end(); ++j) { const SubTree &pb = **j; // Take all of its children for(pcit b=pb->GetBegin(); b!=pb->GetEnd(); ++b) { SubTree tmp2 = *b; if(pb.getsign()) tmp2.Negate(); tmp.AddParam(tmp2); } Erase(*j); } poslist.clear(); AddParam(CodeTree(cLog, tmp)); } // Done, hopefully } if(GetOp() == cPow) { const SubTree &p0 = getp0(); SubTree &p1 = getp1(); if(p0->IsImmed() && p0->GetImmed() == CONSTANT_E && p1->GetOp() == cLog) { // pow(const_E, log(x)) = x ReplaceWith(*(p1->getp0())); } else if(p1->GetOp() == cMul) { //bool didsomething = true; pit poslogpos /*= NULL*/; bool foundposlog = false; pit neglogpos /*= NULL*/; bool foundneglog = false; ConstList cl = p1->BuildConstList(); for(pit a=p1->GetBegin(); a!=p1->GetEnd(); ++a) { const SubTree &pa = *a; if(pa->GetOp() == cLog) { if(!pa.getsign()) { foundposlog = true; poslogpos = a; } else if(*p0 == *(pa->getp0())) { foundneglog = true; neglogpos = a; } } } if(p0->IsImmed() && p0->GetImmed() == 10.0 && cl.value == CONSTANT_L10I && foundposlog) { SubTree base = (*poslogpos)->getp0(); p1->KillConst(cl); p1->Erase(poslogpos); p1->OptimizeRedundant(); SubTree mul = p1; ReplaceWith(cPow, base, mul); // FIXME: what optimizations should be done now? return; } // Put back the constant FinishConst(cl); if(p0->IsImmed() && p0->GetImmed() == CONSTANT_E && foundposlog) { SubTree base = (*poslogpos)->getp0(); p1->Erase(poslogpos); p1->OptimizeRedundant(); SubTree mul = p1; ReplaceWith(cPow, base, mul); // FIXME: what optimizations should be done now? return; } if(foundposlog && foundneglog && *((*neglogpos)->getp0()) == *p0) { SubTree base = (*poslogpos)->getp0(); p1->Erase(poslogpos); p1->Erase(neglogpos); p1->OptimizeRedundant(); SubTree mul = p1; ReplaceWith(cPow, base, mul); // FIXME: what optimizations should be done now? return; } } } } void OptimizeFunctionCalls() { /* Goals: sin(asin(x)) = x * cos(acos(x)) = x * tan(atan(x)) = x * NOTE: * Do NOT do these: * asin(sin(x)) * acos(cos(x)) * atan(tan(x)) * Because someone might want to wrap the angle. */ // FIXME: TODO } void OptimizePowMulAdd() { // x^3 * x -> x^4 // x*3 + x -> x*4 // FIXME: Do those // x^1 -> x if(GetOp() == cPow) { const SubTree &base = getp0(); const SubTree &exponent = getp1(); if(exponent->IsImmed()) { if(exponent->GetImmed() == 1.0) ReplaceWith(*base); else if(exponent->GetImmed() == 0.0 && base->NonZero()) ReplaceWithConst(1.0); } } } void OptimizeExponents() { /* Goals: * (x^y)^z -> x^(y*z) * x^y * x^z -> x^(y+z) */ // First move to exponential form. OptimizeLinearCombine(); bool didchanges = false; Redo: if(GetOp() == cPow) { // (x^y)^z -> x^(y*z) const SubTree &p0 = getp0(); const SubTree &p1 = getp1(); if(p0->GetOp() == cPow) { CodeTree tmp(cMul, p0->getp1(), p1); tmp.Optimize(); ReplaceWith(cPow, p0->getp0(), tmp); didchanges = true; goto Redo; } } if(GetOp() == cMul) { // x^y * x^z -> x^(y+z) for(pit a=GetBegin(); a!=GetEnd(); ++a) { const SubTree &pa = *a; if(pa->GetOp() != cPow) continue; list poslist; for(pit b=a; ++b != GetEnd(); ) { const SubTree &pb = *b; if(pb->GetOp() == cPow && *(pa->getp0()) == *(pb->getp0())) { poslist.push_back(b); } } if(poslist.size() >= 1) { poslist.push_back(a); CodeTree base = *(pa->getp0()); CodeTree exponent(cAdd, 0.0); //eek // Collect all exponents to cAdd list::const_iterator i; for(i=poslist.begin(); i!=poslist.end(); ++i) { const SubTree &pb = **i; SubTree tmp2 = pb->getp1(); if(pb.getsign()) tmp2.Invert(); exponent.AddParam(tmp2); } exponent.Optimize(); CodeTree result(cPow, base, exponent); for(i=poslist.begin(); i!=poslist.end(); ++i) Erase(*i); poslist.clear(); AddParam(result); // We're cMul, remember didchanges = true; goto Redo; } } } OptimizePowMulAdd(); if(didchanges) { // As a result, there might be need for this: OptimizeConflict(); } } void OptimizeLinearExplode() { // x^2 -> x*x // But only if x is just a simple thing // Won't work on anything else. if(GetOp() != cPow) return; // TODO TODO TODO } void OptimizePascal() { #if 0 // Too big, too specific, etc // Won't work on anything else. if(GetOp() != cAdd) return; // Must be done after OptimizeLinearCombine(); // Don't need pascal triangle // Coefficient for x^a * y^b * z^c = 3! / (a! * b! * c!) // We are greedy and want other than just binomials // FIXME // note: partial ones are also nice // x*x + x*y + y*y // = (x+y)^2 - x*y // // x x * x y * + y y * + // -> x y + dup * x y * - #endif } public: void Optimize(); void Assemble(vector &byteCode, vector &immed) const; void FinalOptimize() { // First optimize each parameter. for(pit a=GetBegin(); a!=GetEnd(); ++a) (*a)->FinalOptimize(); /* These things are to be done: * * x * CONSTANT_DR -> cDeg(x) * x * CONSTANT_RD -> cRad(x) * pow(x, 0.5) -> sqrt(x) * log(x) * CONSTANT_L10I -> log10(x) * pow(CONSTANT_E, x) -> exp(x) * inv(sin(x)) -> csc(x) * inv(cos(x)) -> sec(x) * inv(tan(x)) -> cot(x) */ if(GetOp() == cPow) { const SubTree &p0 = getp0(); const SubTree &p1 = getp1(); if(p0->GetOp() == cImmed && p0->GetImmed() == CONSTANT_E) { ReplaceWith(cExp, p1); } else if(p1->GetOp() == cImmed && p1->GetImmed() == 0.5) { ReplaceWith(cSqrt, p0); } } if(GetOp() == cMul) { if(GetArgCount() == 1 && getp0().getsign()) { /***/if(getp0()->GetOp() == cSin)ReplaceWith(cCsc, getp0()->getp0()); else if(getp0()->GetOp() == cCos)ReplaceWith(cSec, getp0()->getp0()); else if(getp0()->GetOp() == cTan)ReplaceWith(cCot, getp0()->getp0()); } } // Separate "if", because op may have just changed if(GetOp() == cMul) { CodeTree *found_log = 0; ConstList cl = BuildConstList(); for(pit a=GetBegin(); a!=GetEnd(); ++a) { SubTree &pa = *a; if(pa->GetOp() == cLog && !pa.getsign()) found_log = &*pa; } if(cl.value == CONSTANT_L10I && found_log) { // Change the log() to log10() found_log->SetOp(cLog10); // And forget the constant KillConst(cl); } else if(cl.value == CONSTANT_DR) { OptimizeRedundant(); ReplaceWith(cDeg, *this); } else if(cl.value == CONSTANT_RD) { OptimizeRedundant(); ReplaceWith(cRad, *this); } else FinishConst(cl); } SortIfPossible(); } }; void CodeTreeDataPtr::Shock() { /* PrepareForWrite(); paramlist &p2 = (*this)->args; for(paramlist::iterator i=p2.begin(); i!=p2.end(); ++i) { (*i)->data.Shock(); } */ } CodeTree::ConstList CodeTree::BuildConstList() { ConstList result; result.value = result.voidvalue = GetOp()==cMul ? 1.0 : 0.0; list &cp = result.cp; for(pit b, a=GetBegin(); a!=GetEnd(); a=b) { SubTree &pa = *a; b=a; ++b; if(!pa->IsImmed()) continue; double thisvalue = pa->GetImmed(); if(thisvalue == result.voidvalue) { // This value is no good, forget it Erase(a); continue; } if(GetOp() == cMul) result.value *= thisvalue; else result.value += thisvalue; cp.push_back(a); } if(GetOp() == cMul) { /* Jos joku niista arvoista on -1 eika se ole ainoa arvo, niin joku muu niista arvoista negatoidaan. */ for(bool done=false; cp.size() > 1 && !done; ) { done = true; for(list::iterator b,a=cp.begin(); a!=cp.end(); a=b) { b=a; ++b; if((**a)->GetImmed() == -1.0) { Erase(*a); cp.erase(a); // take randomly something (**cp.begin())->data->NegateImmed(); if(cp.size() < 2)break; done = false; } } } } return result; } void CodeTree::Assemble (vector &byteCode, vector &immed) const { #define AddCmd(op) byteCode.push_back((op)) #define AddConst(v) do { \ byteCode.push_back(cImmed); \ immed.push_back((v)); \ } while(0) if(IsVar()) { AddCmd(GetVar()); return; } if(IsImmed()) { AddConst(GetImmed()); return; } switch(GetOp()) { case cAdd: case cMul: { unsigned opcount = 0; for(pcit a=GetBegin(); a!=GetEnd(); ++a) { const SubTree &pa = *a; if(opcount < 2) ++opcount; bool pnega = pa.getsign(); bool done = false; if(pa->IsImmed()) { if(GetOp() == cMul && pa->data->IsInverted() && (pnega || opcount==2) ) { CodeTree tmp = *pa; tmp.data->InvertImmed(); tmp.Assemble(byteCode, immed); pnega = !pnega; done = true; } else if(GetOp() == cAdd && (pa->data->IsNegatedOriginal() // || pa->GetImmed() < 0 ) && (pnega || opcount==2) ) { CodeTree tmp = *pa; tmp.data->NegateImmed(); tmp.Assemble(byteCode, immed); pnega = !pnega; done = true; } } if(!done) pa->Assemble(byteCode, immed); if(opcount == 2) { unsigned tmpop = GetOp(); if(pnega) // negate { tmpop = (tmpop == cMul) ? cDiv : cSub; } AddCmd(tmpop); } else if(pnega) { if(GetOp() == cMul) AddCmd(cInv); else AddCmd(cNeg); } } break; } case cIf: { // If the parameter amount is != 3, we're screwed. getp0()->Assemble(byteCode, immed); unsigned ofs = byteCode.size(); AddCmd(cIf); AddCmd(0); // code index AddCmd(0); // immed index getp1()->Assemble(byteCode, immed); byteCode[ofs+1] = byteCode.size()+2; byteCode[ofs+2] = immed.size(); ofs = byteCode.size(); AddCmd(cJump); AddCmd(0); // code index AddCmd(0); // immed index getp2()->Assemble(byteCode, immed); byteCode[ofs+1] = byteCode.size()-1; byteCode[ofs+2] = immed.size(); break; } case cFCall: { // If the parameter count is invalid, we're screwed. for(pcit a=GetBegin(); a!=GetEnd(); ++a) { const SubTree &pa = *a; pa->Assemble(byteCode, immed); } AddCmd(GetOp()); AddCmd(data->GetFuncNo()); break; } case cPCall: { // If the parameter count is invalid, we're screwed. for(pcit a=GetBegin(); a!=GetEnd(); ++a) { const SubTree &pa = *a; pa->Assemble(byteCode, immed); } AddCmd(GetOp()); AddCmd(data->GetFuncNo()); break; } default: { // If the parameter count is invalid, we're screwed. for(pcit a=GetBegin(); a!=GetEnd(); ++a) { const SubTree &pa = *a; pa->Assemble(byteCode, immed); } AddCmd(GetOp()); break; } } } void CodeTree::Optimize() { // Phase: // Phase 0: Do local optimizations. // Phase 1: Optimize each. // Phase 2: Do local optimizations again. for(unsigned phase=0; phase<=2; ++phase) { if(phase == 1) { // Optimize each parameter. for(pit a=GetBegin(); a!=GetEnd(); ++a) { (*a)->Optimize(); CHECKCONSTNEG(*a, GetOp()); } continue; } if(phase == 0 || phase == 2) { // Do local optimizations. OptimizeConstantMath1(); OptimizeLogarithm(); OptimizeFunctionCalls(); OptimizeExponents(); OptimizeLinearExplode(); OptimizePascal(); /* Optimization paths: doublenegations= redundant= * doublenegations conflict= * redundant addmulflat= constantmath1= addmulflat * conflict linearcombine= conflict * addmulflat(1) redundant(1) powmuladd= exponents= linearcombine * powmuladd conflict(1) logarithm= exponents * functioncalls= IDLE linearexplode= IDLE pascal= IDLE * = actions here (1) = only if made changes */ } } } bool CodeTree::operator== (const CodeTree& b) const { if(GetOp() != b.GetOp()) return false; if(IsImmed()) if(GetImmed() != b.GetImmed()) return false; if(IsVar()) if(GetVar() != b.GetVar()) return false; if(data->IsFunc()) if(data->GetFuncNo() != b.data->GetFuncNo()) return false; return data->args == b.data->args; } bool CodeTree::operator< (const CodeTree& b) const { if(GetArgCount() != b.GetArgCount()) return GetArgCount() > b.GetArgCount(); if(GetOp() != b.GetOp()) { // sort immeds last if(IsImmed() != b.IsImmed()) return IsImmed() < b.IsImmed(); return GetOp() < b.GetOp(); } if(IsImmed()) { if(GetImmed() != b.GetImmed()) return GetImmed() < b.GetImmed(); } if(IsVar() && GetVar() != b.GetVar()) { return GetVar() < b.GetVar(); } if(data->IsFunc() && data->GetFuncNo() != b.data->GetFuncNo()) { return data->GetFuncNo() < b.data->GetFuncNo(); } pcit i = GetBegin(), j = b.GetBegin(); for(; i != GetEnd(); ++i, ++j) { const SubTree &pa = *i, &pb = *j; if(!(pa == pb)) return pa < pb; } return false; } bool IsNegate(const SubTree &p1, const SubTree &p2) /*const */ { if(p1->IsImmed() && p2->IsImmed()) { return p1->GetImmed() == -p2->GetImmed(); } if(p1.getsign() == p2.getsign()) return false; return *p1 == *p2; } bool IsInverse(const SubTree &p1, const SubTree &p2) /*const*/ { if(p1->IsImmed() && p2->IsImmed()) { // FIXME: potential divide by zero. return p1->GetImmed() == 1.0 / p2->GetImmed(); } if(p1.getsign() == p2.getsign()) return false; return *p1 == *p2; } SubTree::SubTree() : tree(new CodeTree), sign(false) { } SubTree::SubTree(const SubTree &b) : tree(new CodeTree(*b.tree)), sign(b.sign) { } #define SubTreeDecl(p1, p2) \ SubTree::SubTree p1 : tree(new CodeTree p2), sign(false) { } SubTreeDecl( (const CodeTree &b), (b) ) SubTreeDecl( (double value), (value) ) #undef SubTreeDecl SubTree::~SubTree() { delete tree; tree=0; } const SubTree &SubTree::operator= (const SubTree &b) { sign = b.sign; CodeTree *oldtree = tree; tree = new CodeTree(*b.tree); delete oldtree; return *this; } const SubTree &SubTree::operator= (const CodeTree &b) { sign = false; CodeTree *oldtree = tree; tree = new CodeTree(b); delete oldtree; return *this; } bool SubTree::operator< (const SubTree& b) const { if(getsign() != b.getsign()) return getsign() < b.getsign(); return *tree < *b.tree; } bool SubTree::operator== (const SubTree& b) const { return sign == b.sign && *tree == *b.tree; } void SubTree::Negate() // Note: Parent must be cAdd { flipsign(); CheckConstNeg(); } void SubTree::CheckConstNeg() { if(tree->IsImmed() && getsign()) { tree->NegateImmed(); sign = false; } } void SubTree::Invert() // Note: Parent must be cMul { flipsign(); CheckConstInv(); } void SubTree::CheckConstInv() { if(tree->IsImmed() && getsign()) { tree->InvertImmed(); sign = false; } } }//namespace void FunctionParser::MakeTree(void *r) const { // Dirty hack. Should be fixed. CodeTree* result = static_cast(r); vector stack(1); #define GROW(n) do { \ stacktop += n; \ if(stack.size() <= stacktop) stack.resize(stacktop+1); \ } while(0) #define EAT(n, opcode) do { \ unsigned newstacktop = stacktop-n; \ stack[stacktop].SetOp((opcode)); \ for(unsigned a=0, b=(n); a labels; const unsigned* const ByteCode = data->ByteCode; const unsigned ByteCodeSize = data->ByteCodeSize; const double* const Immed = data->Immed; for(unsigned IP=0, DP=0; ; ++IP) { while(labels.size() > 0 && *labels.begin() == IP) { // The "else" of an "if" ends here EAT(3, cIf); labels.erase(labels.begin()); } if(IP >= ByteCodeSize) { break; } unsigned opcode = ByteCode[IP]; if(opcode == cIf) { IP += 2; } else if(opcode == cJump) { labels.push_front(ByteCode[IP+1]+1); IP += 2; } else if(opcode == cImmed) { ADDCONST(Immed[DP++]); } else if(opcode < VarBegin) { switch(opcode) { // Unary operators case cNeg: { EAT(1, cAdd); // Unary minus is negative adding. stack[stacktop-1].getp0().Negate(); break; } // Binary operators case cSub: { EAT(2, cAdd); // Minus is negative adding stack[stacktop-1].getp1().Negate(); break; } case cDiv: { EAT(2, cMul); // Divide is inverse multiply stack[stacktop-1].getp1().Invert(); break; } // ADD ALL TWO PARAMETER NON-FUNCTIONS HERE case cAdd: case cMul: case cMod: case cPow: case cEqual: case cLess: case cGreater: case cAnd: case cOr: EAT(2, opcode); break; case cFCall: { unsigned index = ByteCode[++IP]; unsigned params = data->FuncPtrs[index].params; EAT(params, opcode); stack[stacktop-1].data->SetFuncNo(index); break; } case cPCall: { unsigned index = ByteCode[++IP]; unsigned params = data->FuncParsers[index]->data->varAmount; EAT(params, opcode); stack[stacktop-1].data->SetFuncNo(index); break; } // Converted to cMul on fly case cDeg: ADDCONST(CONSTANT_DR); EAT(2, cMul); break; // Converted to cMul on fly case cRad: ADDCONST(CONSTANT_RD); EAT(2, cMul); break; // Functions default: { const FuncDefinition& func = Functions[opcode-cAbs]; unsigned paramcount = func.params; #ifndef DISABLE_EVAL if(opcode == cEval) paramcount = data->varAmount; #endif if(opcode == cSqrt) { // Converted on fly: sqrt(x) = x^0.5 opcode = cPow; paramcount = 2; ADDCONST(0.5); } if(opcode == cExp) { // Converted on fly: exp(x) = CONSTANT_E^x opcode = cPow; paramcount = 2; // reverse the parameters... kludgey stack[stacktop] = stack[stacktop-1]; stack[stacktop-1].SetImmed(CONSTANT_E); GROW(1); } bool do_inv = false; if(opcode == cCot) { do_inv = true; opcode = cTan; } if(opcode == cCsc) { do_inv = true; opcode = cSin; } if(opcode == cSec) { do_inv = true; opcode = cCos; } bool do_log10 = false; if(opcode == cLog10) { // Converted on fly: log10(x) = log(x) * CONSTANT_L10I opcode = cLog; do_log10 = true; } EAT(paramcount, opcode); if(do_log10) { ADDCONST(CONSTANT_L10I); EAT(2, cMul); } if(do_inv) { // Unary cMul, inverted. No need for "1.0" EAT(1, cMul); stack[stacktop-1].getp0().Invert(); } break; } } } else { stack[stacktop].SetVar(opcode); GROW(1); } } if(!stacktop) { // ERROR: Stack does not have any values! return; } --stacktop; // Ignore the last element, it is always nop (cAdd). if(stacktop > 0) { // ERROR: Stack has too many values! return; } // Okay, the tree is now stack[0] *result = stack[0]; } void FunctionParser::Optimize() { copyOnWrite(); CodeTree tree; MakeTree(&tree); // Do all sorts of optimizations tree.Optimize(); // Last changes before assembly tree.FinalOptimize(); // Now rebuild from the tree. vector byteCode; vector immed; #if 0 byteCode.resize(Comp.ByteCodeSize); for(unsigned a=0; aByteCode; data->ByteCode = 0; if((data->ByteCodeSize = byteCode.size()) > 0) { data->ByteCode = new unsigned[data->ByteCodeSize]; for(unsigned a=0; aByteCode[a] = byteCode[a]; } delete[] data->Immed; data->Immed = 0; if((data->ImmedSize = immed.size()) > 0) { data->Immed = new double[data->ImmedSize]; for(unsigned a=0; aImmed[a] = immed[a]; } } #else /* !SUPPORT_OPTIMIZER */ /* keep the linker happy */ void FunctionParser::MakeTree(void *) const {} void FunctionParser::Optimize() { // Do nothing if no optimizations are supported. } #endif gambit-0.2010.09.01/src/labenski/src/fparser.hh0000644000076500007650000001125211350032206015562 00000000000000/***************************************************************************\ |* Function parser v2.71 by Warp *| |* ---------------------------- *| |* Parses and evaluates the given function with the given variable values. *| |* *| \***************************************************************************/ #ifndef ONCE_FPARSER_H_ #define ONCE_FPARSER_H_ // Slightly modified for use with wxWidgets by John Labenski 1/20/04 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "fparser.hh" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif #include #include #include #ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT #include #endif class FunctionParser { public: enum ParseErrorType { SYNTAX_ERROR=0, MISM_PARENTH, MISSING_PARENTH, EMPTY_PARENTH, EXPECT_OPERATOR, OUT_OF_MEMORY, UNEXPECTED_ERROR, INVALID_VARS, ILL_PARAMS_AMOUNT, PREMATURE_EOS, EXPECT_PARENTH_FUNC, FP_NO_ERROR }; int Parse(const std::string& Function, const std::string& Vars, bool useDegrees = false); const char* ErrorMsg() const; inline ParseErrorType GetParseErrorType() const { return parseErrorType; } double Eval(const double* Vars); inline int EvalError() const { return evalErrorType; } bool AddConstant(const std::string& name, double value); typedef double (*FunctionPtr)(const double*); bool AddFunction(const std::string& name, FunctionPtr, unsigned paramsAmount); bool AddFunction(const std::string& name, FunctionParser&); void Optimize(); int GetNumberVariables() const { return data->varAmount; } bool GetUseDegrees() const { return data->useDegreeConversion; } FunctionParser(); ~FunctionParser(); // Copy constructor and assignment operator (implemented using the // copy-on-write technique for efficiency): FunctionParser(const FunctionParser&); FunctionParser& operator=(const FunctionParser&); #ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT // For debugging purposes only: void PrintByteCode(std::ostream& dest) const; #endif //======================================================================== private: //======================================================================== // Private data: // ------------ ParseErrorType parseErrorType; int evalErrorType; struct Data { unsigned referenceCounter; int varAmount; bool useDegreeConversion; typedef std::map VarMap_t; VarMap_t Variables; typedef std::map ConstMap_t; ConstMap_t Constants; VarMap_t FuncPtrNames; struct FuncPtrData { FunctionPtr ptr; unsigned params; FuncPtrData(FunctionPtr p, unsigned par): ptr(p), params(par) {} }; std::vector FuncPtrs; VarMap_t FuncParserNames; std::vector FuncParsers; unsigned* ByteCode; unsigned ByteCodeSize; double* Immed; unsigned ImmedSize; double* Stack; unsigned StackSize; Data(); ~Data(); Data(const Data&); Data& operator=(const Data&); // not implemented on purpose }; Data* data; // Temp data needed in Compile(): unsigned StackPtr; std::vector* tempByteCode; std::vector* tempImmed; // Private methods: // --------------- inline void copyOnWrite(); bool checkRecursiveLinking(const FunctionParser*) const; bool isValidName(const std::string&) const; Data::VarMap_t::const_iterator FindVariable(const char*, const Data::VarMap_t&) const; Data::ConstMap_t::const_iterator FindConstant(const char*) const; int CheckSyntax(const char*); bool Compile(const char*); bool IsVariable(int); void AddCompiledByte(unsigned); void AddImmediate(double); void AddFunctionOpcode(unsigned); inline void incStackPtr(); int CompileIf(const char*, int); int CompileFunctionParams(const char*, int, unsigned); int CompileElement(const char*, int); int CompilePow(const char*, int); int CompileUnaryMinus(const char*, int); int CompileMult(const char*, int); int CompileAddition(const char*, int); int CompileComparison(const char*, int); int CompileAnd(const char*, int); int CompileOr(const char*, int); int CompileExpression(const char*, int, bool=false); void MakeTree(void*) const; }; #endif gambit-0.2010.09.01/src/labenski/src/genergdi.cpp0000644000076500007650000005242711350032206016100 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: genergdi.cpp // Purpose: Generic gdi pen and colour // Author: John Labenski // Modified by: // Created: 12/01/2000 // Copyright: (c) John Labenski // Licence: wxWidgets license ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "genergdi.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #include "wx/wxthings/genergdi.h" #include "wx/tokenzr.h" const wxGenericColour wxNullGenericColour; const wxGenericPen wxNullGenericPen; const wxGenericBrush wxNullGenericBrush; #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArrayGenericColour) WX_DEFINE_OBJARRAY(wxArrayGenericPen) WX_DEFINE_OBJARRAY(wxArrayGenericBrush) //---------------------------------------------------------------------------- // wxGenericColour //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxGenericColour, wxObject) class wxGenericColourRefData : public wxObjectRefData { public: wxGenericColourRefData(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, unsigned char a = 255) : wxObjectRefData(), m_r(r), m_g(g), m_b(b), m_a(a) {} wxGenericColourRefData( const wxGenericColourRefData& data ) : wxObjectRefData(), m_r(data.m_r), m_g(data.m_g), m_b(data.m_b), m_a(data.m_a) {} unsigned char m_r, m_g, m_b, m_a; }; #define M_GCOLOURDATA ((wxGenericColourRefData*)m_refData) //---------------------------------------------------------------------------- wxObjectRefData *wxGenericColour::CreateRefData() const { return new wxGenericColourRefData; } wxObjectRefData *wxGenericColour::CloneRefData(const wxObjectRefData *data) const { return new wxGenericColourRefData(*(const wxGenericColourRefData *)data); } void wxGenericColour::Create( const wxGenericColour& c ) { Ref(c); } void wxGenericColour::Create( const wxColour& c) { UnRef(); m_refData = new wxGenericColourRefData; Set(c); } void wxGenericColour::Create( unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha ) { UnRef(); m_refData = new wxGenericColourRefData(red, green, blue, alpha); } void wxGenericColour::CreateABGR( unsigned long colABGR ) { UnRef(); m_refData = new wxGenericColourRefData; SetABGR(colABGR); } void wxGenericColour::CreateARGB( unsigned long colARGB ) { UnRef(); m_refData = new wxGenericColourRefData; SetARGB(colARGB); } void wxGenericColour::Create( const wxString& colourName ) { UnRef(); m_refData = new wxGenericColourRefData; Set(colourName); } void wxGenericColour::Set( const wxGenericColour &c ) { wxCHECK_RET(Ok() && c.Ok(), wxT("Invalid generic colour")); M_GCOLOURDATA->m_r = c.GetRed(); M_GCOLOURDATA->m_g = c.GetGreen(); M_GCOLOURDATA->m_b = c.GetBlue(); M_GCOLOURDATA->m_a = c.GetAlpha(); } void wxGenericColour::Set( const wxColour& c ) { wxCHECK_RET(Ok() && c.Ok(), wxT("Invalid colour")); M_GCOLOURDATA->m_r = c.Red(); M_GCOLOURDATA->m_g = c.Green(); M_GCOLOURDATA->m_b = c.Blue(); } void wxGenericColour::Set( unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha ) { wxCHECK_RET(Ok(), wxT("Invalid generic colour")); M_GCOLOURDATA->m_r = red; M_GCOLOURDATA->m_g = green; M_GCOLOURDATA->m_b = blue; M_GCOLOURDATA->m_a = alpha; } void wxGenericColour::SetABGR( unsigned long colABGR ) { wxCHECK_RET(Ok(), wxT("Invalid generic colour")); M_GCOLOURDATA->m_r = (unsigned char)(0xFF& colABGR); M_GCOLOURDATA->m_g = (unsigned char)(0xFF&(colABGR >> 8)); M_GCOLOURDATA->m_b = (unsigned char)(0xFF&(colABGR >> 16)); M_GCOLOURDATA->m_a = (unsigned char)(0xFF&(colABGR >> 24)); } void wxGenericColour::SetARGB( unsigned long colARGB ) { wxCHECK_RET(Ok(), wxT("Invalid generic colour")); M_GCOLOURDATA->m_b = (unsigned char)(0xFF& colARGB); M_GCOLOURDATA->m_g = (unsigned char)(0xFF&(colARGB >> 8)); M_GCOLOURDATA->m_r = (unsigned char)(0xFF&(colARGB >> 16)); M_GCOLOURDATA->m_a = (unsigned char)(0xFF&(colARGB >> 24)); } void wxGenericColour::Set( const wxString& colourName ) { wxCHECK_RET(Ok(), wxT("Invalid generic colour")); Set(wxColour(colourName)); } void wxGenericColour::SetRed( unsigned char r ) { wxCHECK_RET(Ok(), wxT("Invalid generic colour")); M_GCOLOURDATA->m_r = r; } void wxGenericColour::SetGreen( unsigned char g ) { wxCHECK_RET(Ok(), wxT("Invalid generic colour")); M_GCOLOURDATA->m_g = g; } void wxGenericColour::SetBlue( unsigned char b ) { wxCHECK_RET(Ok(), wxT("Invalid generic colour")); M_GCOLOURDATA->m_b = b; } void wxGenericColour::SetAlpha( unsigned char a ) { wxCHECK_RET(Ok(), wxT("Invalid generic colour")); M_GCOLOURDATA->m_a = a; } unsigned char wxGenericColour::GetRed() const { wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); return M_GCOLOURDATA->m_r; } unsigned char wxGenericColour::GetGreen() const { wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); return M_GCOLOURDATA->m_g; } unsigned char wxGenericColour::GetBlue() const { wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); return M_GCOLOURDATA->m_b; } unsigned char wxGenericColour::GetAlpha() const { wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); return M_GCOLOURDATA->m_a; } bool wxGenericColour::IsSameAs( const wxGenericColour& c ) const { wxCHECK_MSG(Ok() && c.Ok(), false, wxT("Invalid generic colour")); wxGenericColourRefData *cData = (wxGenericColourRefData*)c.GetRefData(); return (M_GCOLOURDATA->m_r == cData->m_r) && (M_GCOLOURDATA->m_g == cData->m_g) && (M_GCOLOURDATA->m_b == cData->m_b) && (M_GCOLOURDATA->m_a == cData->m_a); } bool wxGenericColour::IsSameAs( const wxColour& c ) const { wxCHECK_MSG(Ok() && c.Ok(), false, wxT("Invalid colour")); return (M_GCOLOURDATA->m_r == c.Red()) && (M_GCOLOURDATA->m_g == c.Green()) && (M_GCOLOURDATA->m_b == c.Blue()); } // This code is assumed to be public domain, originally from Paul Bourke, July 1996 // http://astronomy.swin.edu.au/~pbourke/colour/colourramp/source1.c wxGenericColour wxGenericColour::GetHotColdColour(double v) const { wxGenericColour c(255, 255, 255); const double vmin = 0.0, vmax = 255.0, dv = vmax - vmin; if (v < vmin) v = vmin; if (v > vmax) v = vmax; if (v < (vmin + 0.25 * dv)) { c.SetRed(0); c.SetGreen(int(vmax*(4.0 * (v - vmin) / dv) + 0.5)); } else if (v < (vmin + 0.5 * dv)) { c.SetRed(0); c.SetBlue(int(vmax*(1.0 + 4.0 * (vmin + 0.25 * dv - v) / dv) + 0.5)); } else if (v < (vmin + 0.75 * dv)) { c.SetRed(int(vmax*(4.0 * (v - vmin - 0.5 * dv) / dv) + 0.5)); c.SetBlue(0); } else { c.SetGreen(int(vmax*(1.0 + 4.0 * (vmin + 0.75 * dv - v) / dv) + 0.5)); c.SetBlue(0); } return c; } /* wxString wxGenericColour::WriteString(const wxString& format) const { return wxString::Format(format.c_str(), m_r, m_g, m_b, m_a); } bool wxGenericColour::ReadString(const wxString& str, const wxString& format) { int r,g,b,a; if (4 == wxSscanf(str, format.c_str(), &r, &g, &b, &a)) { m_r = r; m_g = g; m_b = b; m_a = a; return true; } return false; } */ //---------------------------------------------------------------------------- // wxGenericPen //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxGenericPen, wxObject) class wxGenericPenRefData : public wxObjectRefData { public: wxGenericPenRefData(int width = 1, int style = wxSOLID, int cap = wxCAP_ROUND, int join = wxJOIN_ROUND) : wxObjectRefData(), m_width(width), m_style(style), m_cap(cap), m_join(join), m_dash_count(0), m_dash(NULL) {} wxGenericPenRefData(const wxGenericPenRefData& data) : wxObjectRefData(), m_colour(data.m_colour), m_width(data.m_width), m_style(data.m_style), m_cap(data.m_cap), m_join(data.m_join), m_dash_count(data.m_dash_count), m_dash(NULL) { if (data.m_dash) { m_dash = (wxDash*)malloc(m_dash_count*sizeof(wxDash)); memcpy(m_dash, data.m_dash, m_dash_count*sizeof(wxDash)); } } ~wxGenericPenRefData() { if (m_dash) free(m_dash); } wxGenericColour m_colour; int m_width; int m_style; int m_cap; int m_join; int m_dash_count; // don't arbitrarily adjust these! wxDash *m_dash; }; #define M_GPENDATA ((wxGenericPenRefData*)m_refData) //---------------------------------------------------------------------------- wxObjectRefData *wxGenericPen::CreateRefData() const { return new wxGenericPenRefData; } wxObjectRefData *wxGenericPen::CloneRefData(const wxObjectRefData *data) const { return new wxGenericPenRefData(*(const wxGenericPenRefData *)data); } void wxGenericPen::Create( const wxGenericPen &pen ) { Ref(pen); } void wxGenericPen::Create( const wxPen &pen ) { UnRef(); m_refData = new wxGenericPenRefData; Set(pen); } void wxGenericPen::Create(const wxGenericColour &colour, int width, int style, int cap, int join ) { UnRef(); m_refData = new wxGenericPenRefData(width, style, cap, join); M_GPENDATA->m_colour = colour; } void wxGenericPen::Create(const wxColour &colour, int width, int style, int cap, int join ) { Create(wxGenericColour(colour), width, style, cap, join); } void wxGenericPen::Set( const wxGenericPen& pen ) { wxCHECK_RET(Ok() && pen.Ok(), wxT("Invalid generic pen")); SetColour(pen.GetColour()); M_GPENDATA->m_width = pen.GetWidth(); M_GPENDATA->m_style = pen.GetStyle(); M_GPENDATA->m_cap = pen.GetCap(); M_GPENDATA->m_join = pen.GetJoin(); wxDash* dash; int n_dashes = pen.GetDashes(&dash); SetDashes(n_dashes, dash); } void wxGenericPen::Set( const wxPen &pen ) { wxCHECK_RET(Ok() && pen.Ok(), wxT("Invalid generic pen")); SetColour(pen.GetColour()); M_GPENDATA->m_width = pen.GetWidth(); M_GPENDATA->m_style = pen.GetStyle(); M_GPENDATA->m_cap = pen.GetCap(); M_GPENDATA->m_join = pen.GetJoin(); wxDash* dash; int n_dashes = pen.GetDashes(&dash); SetDashes(n_dashes, dash); // or SetDashes(pen.GetDashCount(), pen.GetDash()); not in msw 2.4 } void wxGenericPen::SetColour( const wxGenericColour &colour ) { wxCHECK_RET(Ok() && colour.Ok(), wxT("Invalid generic pen or colour")); M_GPENDATA->m_colour = colour; } void wxGenericPen::SetColour( const wxColour &colour ) { SetColour(wxGenericColour(colour)); } void wxGenericPen::SetColour( int red, int green, int blue, int alpha ) { SetColour(wxGenericColour(red, green, blue, alpha)); } void wxGenericPen::SetCap( int capStyle ) { wxCHECK_RET(Ok(), wxT("Invalid generic pen")); M_GPENDATA->m_cap = capStyle; } void wxGenericPen::SetJoin( int joinStyle ) { wxCHECK_RET(Ok(), wxT("Invalid generic pen")); M_GPENDATA->m_join = joinStyle; } void wxGenericPen::SetStyle( int style ) { wxCHECK_RET(Ok(), wxT("Invalid generic pen")); M_GPENDATA->m_style = style; } void wxGenericPen::SetWidth( int width ) { wxCHECK_RET(Ok(), wxT("Invalid generic pen")); M_GPENDATA->m_width = width; } void wxGenericPen::SetDashes( int number_of_dashes, const wxDash *dash ) { wxCHECK_RET(Ok(), wxT("Invalid generic pen")); wxCHECK_RET(((number_of_dashes == 0) && !dash) || ((number_of_dashes > 0) && dash), wxT("Invalid dashes for pen")); // internal double check to see if somebody's messed with this //wxCHECK_RET(((M_GPENDATA->m_dash_count == 0) && !M_GPENDATA->m_dash) || // ((M_GPENDATA->m_dash_count != 0) && M_GPENDATA->m_dash), wxT("Invalid internal dashes for pen")); if (M_GPENDATA->m_dash) { free(M_GPENDATA->m_dash); M_GPENDATA->m_dash = NULL; M_GPENDATA->m_dash_count = 0; } if (!dash) return; M_GPENDATA->m_dash_count = number_of_dashes; M_GPENDATA->m_dash = (wxDash*)malloc(number_of_dashes*sizeof(wxDash)); memcpy(M_GPENDATA->m_dash, dash, number_of_dashes*sizeof(wxDash)); } wxPen wxGenericPen::GetPen() const { wxCHECK_MSG(Ok(), wxNullPen, wxT("Invalid generic pen")); wxPen pen(M_GPENDATA->m_colour.GetColour(), M_GPENDATA->m_width, M_GPENDATA->m_style); pen.SetCap(M_GPENDATA->m_cap); pen.SetJoin(M_GPENDATA->m_join); if (M_GPENDATA->m_dash_count > 0) pen.SetDashes(M_GPENDATA->m_dash_count, M_GPENDATA->m_dash); return pen; } wxGenericColour wxGenericPen::GetGenericColour() const { wxCHECK_MSG(Ok(), wxNullGenericColour, wxT("Invalid generic pen")); return M_GPENDATA->m_colour; } wxColour wxGenericPen::GetColour() const { wxCHECK_MSG(Ok(), wxNullColour, wxT("Invalid generic pen")); return M_GPENDATA->m_colour.GetColour(); } int wxGenericPen::GetWidth() const { wxCHECK_MSG(Ok(), 1, wxT("Invalid generic pen")); return M_GPENDATA->m_width; } int wxGenericPen::GetStyle() const { wxCHECK_MSG(Ok(), wxSOLID, wxT("Invalid generic pen")); return M_GPENDATA->m_style; } int wxGenericPen::GetCap() const { wxCHECK_MSG(Ok(), wxCAP_ROUND, wxT("Invalid generic pen")); return M_GPENDATA->m_cap; } int wxGenericPen::GetJoin() const { wxCHECK_MSG(Ok(), wxJOIN_ROUND, wxT("Invalid generic pen")); return M_GPENDATA->m_join; } int wxGenericPen::GetDashes(wxDash **ptr) const { wxCHECK_MSG(Ok(), 0, wxT("Invalid generic pen")); *ptr = (wxDash*)M_GPENDATA->m_dash; return M_GPENDATA->m_dash_count; } int wxGenericPen::GetDashCount() const { wxCHECK_MSG(Ok(), 0, wxT("Invalid generic pen")); return M_GPENDATA->m_dash_count; } wxDash* wxGenericPen::GetDash() const { wxCHECK_MSG(Ok(), NULL, wxT("Invalid generic pen")); return M_GPENDATA->m_dash; } bool wxGenericPen::IsSameAs(const wxGenericPen &pen) const { wxCHECK_MSG(Ok() && pen.Ok(), false, wxT("Invalid generic pen")); wxGenericPenRefData *pData = (wxGenericPenRefData*)pen.GetRefData(); if ((M_GPENDATA->m_colour != pData->m_colour) || (M_GPENDATA->m_width != pData->m_width) || (M_GPENDATA->m_style != pData->m_style) || (M_GPENDATA->m_cap != pData->m_cap) || (M_GPENDATA->m_join != pData->m_join) || (M_GPENDATA->m_dash_count != pen.GetDashCount())) return false; if (M_GPENDATA->m_dash_count > 0) return memcmp(M_GPENDATA->m_dash, pen.GetDash(), M_GPENDATA->m_dash_count*sizeof(wxDash)) == 0; return true; } bool wxGenericPen::IsSameAs(const wxPen &pen) const { wxCHECK_MSG(Ok() && pen.Ok(), false, wxT("Invalid generic pen")); wxGenericPen gp(pen); gp.GetGenericColour().SetAlpha(M_GPENDATA->m_colour.GetAlpha()); return IsSameAs(gp); } /* wxString wxGenericPen::WriteString() const { wxString str; str.Printf(wxT("%s,%d,%d,%d,%d,%d"), m_colour.WriteString().c_str(), m_width, m_style, m_cap, m_join, m_dash_count); for (int i = 0; i < m_dash_count; i++) str += wxString::Format(wxT(",%d"), m_dash[i]); return str; } bool wxGenericPen::ReadString(const wxString& str) { wxArrayString tokens = wxStringTokenize(str, wxT(", "), wxTOKEN_DEFAULT); size_t n, count = tokens.GetCount(); if (count < 9u) return false; long val; for (n = 0; n < count; n++) { if (!tokens[n].ToLong(&val)) return false; values.Add(int(val)); } m_colour.Set(values[0], values[1], values[2], values[3]); size_t num_dashes = values[8]; if (num_dashes != count - 9) return false; if (num_dashes > 0) { wxDash *dash = new wxDash[num_dashes]; for (n = 0; n < num_dashes; n++) dash[n] = (wxDash)values[n]; SetDashes(num_dashes, dash); delete dash; } m_width = values[4]; m_style = values[5]; m_cap = values[6]; m_join = values[7]; //m_dash_count = values[8]; return true; } */ #include "wx/bitmap.h" //---------------------------------------------------------------------------- // wxGenericBrush //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxGenericBrush, wxObject) class wxGenericBrushRefData : public wxObjectRefData { public: wxGenericBrushRefData(const wxGenericColour& c = wxNullGenericColour, int style = wxSOLID) : wxObjectRefData(), m_colour(c), m_style(style) {} wxGenericBrushRefData(const wxGenericBrushRefData& data) : wxObjectRefData(), m_colour(data.m_colour), m_style(data.m_style), m_stipple(data.m_stipple) {} ~wxGenericBrushRefData() { } wxGenericColour m_colour; int m_style; wxBitmap m_stipple; }; #define M_GBRUSHDATA ((wxGenericBrushRefData*)m_refData) //---------------------------------------------------------------------------- wxObjectRefData *wxGenericBrush::CreateRefData() const { return new wxGenericBrushRefData; } wxObjectRefData *wxGenericBrush::CloneRefData(const wxObjectRefData *data) const { return new wxGenericBrushRefData(*(const wxGenericBrushRefData *)data); } void wxGenericBrush::Create( const wxGenericBrush &brush ) { Ref(brush); } void wxGenericBrush::Create( const wxBrush &brush ) { UnRef(); m_refData = new wxGenericBrushRefData; Set(brush); } void wxGenericBrush::Create(const wxGenericColour &colour, int style) { UnRef(); m_refData = new wxGenericBrushRefData(colour, style); } void wxGenericBrush::Create(const wxColour &colour, int style) { Create(wxGenericColour(colour), style); } void wxGenericBrush::Create( const wxBitmap &stipple ) { UnRef(); wxCHECK_RET(stipple.Ok(), wxT("Invalid bitmap in wxGenericBrush::Create")); int style = stipple.GetMask() ? wxSTIPPLE_MASK_OPAQUE : wxSTIPPLE; m_refData = new wxGenericBrushRefData(wxNullGenericColour, style); M_GBRUSHDATA->m_stipple = stipple; } void wxGenericBrush::Set( const wxGenericBrush& brush ) { wxCHECK_RET(Ok() && brush.Ok(), wxT("Invalid generic brush")); SetColour(brush.GetColour()); M_GBRUSHDATA->m_style = brush.GetStyle(); wxBitmap* stipple = brush.GetStipple(); if (stipple && stipple->Ok()) M_GBRUSHDATA->m_stipple = *stipple; } void wxGenericBrush::Set( const wxBrush &brush ) { wxCHECK_RET(Ok() && brush.Ok(), wxT("Invalid generic brush")); SetColour(brush.GetColour()); M_GBRUSHDATA->m_style = brush.GetStyle(); wxBitmap* stipple = brush.GetStipple(); if (stipple && stipple->Ok()) M_GBRUSHDATA->m_stipple = *stipple; } void wxGenericBrush::SetColour( const wxGenericColour &colour ) { wxCHECK_RET(Ok() && colour.Ok(), wxT("Invalid generic brush or colour")); M_GBRUSHDATA->m_colour = colour; } void wxGenericBrush::SetColour( const wxColour &colour ) { SetColour(wxGenericColour(colour)); } void wxGenericBrush::SetColour( int red, int green, int blue, int alpha ) { SetColour(wxGenericColour(red, green, blue, alpha)); } void wxGenericBrush::SetStyle( int style ) { wxCHECK_RET(Ok(), wxT("Invalid generic brush")); M_GBRUSHDATA->m_style = style; } void wxGenericBrush::SetStipple(const wxBitmap& stipple) { wxCHECK_RET(Ok(), wxT("Invalid generic brush")); M_GBRUSHDATA->m_stipple = stipple; M_GBRUSHDATA->m_style = stipple.GetMask() ? wxSTIPPLE_MASK_OPAQUE : wxSTIPPLE; } wxBrush wxGenericBrush::GetBrush() const { wxCHECK_MSG(Ok(), wxNullBrush, wxT("Invalid generic brush")); if (M_GBRUSHDATA->m_stipple.Ok()) return wxBrush(M_GBRUSHDATA->m_stipple); return wxBrush(M_GBRUSHDATA->m_colour.GetColour(), M_GBRUSHDATA->m_style); } wxGenericColour wxGenericBrush::GetGenericColour() const { wxCHECK_MSG(Ok(), wxNullGenericColour, wxT("Invalid generic brush")); return M_GBRUSHDATA->m_colour; } wxColour wxGenericBrush::GetColour() const { wxCHECK_MSG(Ok(), wxNullColour, wxT("Invalid generic brush")); return M_GBRUSHDATA->m_colour.GetColour(); } int wxGenericBrush::GetStyle() const { wxCHECK_MSG(Ok(), wxSOLID, wxT("Invalid generic brush")); return M_GBRUSHDATA->m_style; } wxBitmap* wxGenericBrush::GetStipple() const { wxCHECK_MSG(Ok(), NULL, wxT("Invalid generic brush")); return &M_GBRUSHDATA->m_stipple; } bool wxGenericBrush::IsSameAs(const wxGenericBrush& brush) const { wxCHECK_MSG(Ok() && brush.Ok(), 1, wxT("Invalid generic brush")); wxGenericBrushRefData *bData = (wxGenericBrushRefData*)brush.GetRefData(); #if wxCHECK_VERSION(2,7,0) // FIXME: Hack for wx2.7; how do we test wxBitmap for equality now? return (M_GBRUSHDATA->m_colour == bData->m_colour) && (M_GBRUSHDATA->m_style == bData->m_style); #else return (M_GBRUSHDATA->m_colour == bData->m_colour) && (M_GBRUSHDATA->m_style == bData->m_style) && (M_GBRUSHDATA->m_stipple == bData->m_stipple); #endif } bool wxGenericBrush::IsSameAs(const wxBrush& brush) const { wxCHECK_MSG(Ok() && brush.Ok(), 1, wxT("Invalid generic brush")); wxGenericBrush gB(brush); gB.GetGenericColour().SetAlpha(M_GBRUSHDATA->m_colour.GetAlpha()); return IsSameAs(gB); } gambit-0.2010.09.01/src/labenski/src/geometry.cpp0000644000076500007650000001554611350032206016150 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: geometry.cpp // Author: John Labenski // Created: 07/01/02 // Copyright: John Labenski, 2002 // License: wxWidgets v2 ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "geometry.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include #ifdef __BORLANDC__ #pragma hdrstop #endif #include "wx/wxthings/geometry.h" /* 2.4 : How do I generate a circle through three points? Let the three given points be a, b, c. Use _0 and _1 to represent x and y coordinates. The coordinates of the center p=(p_0,p_1) of the circle determined by a, b, and c are: A = b_0 - a_0; B = b_1 - a_1; C = c_0 - a_0; D = c_1 - a_1; E = A*(a_0 + b_0) + B*(a_1 + b_1); F = C*(a_0 + c_0) + D*(a_1 + c_1); G = 2.0*(A*(c_1 - b_1)-B*(c_0 - b_0)); p_0 = (D*E - B*F) / G; p_1 = (A*F - C*E) / G; If G is zero then the three points are collinear and no finite-radius circle through them exists. Otherwise, the radius of the circle is: r^2 = (a_0 - p_0)^2 + (a_1 - p_1)^2 [O' Rourke (C)] p. 201. Simplified by Jim Ward. */ wxCircleDouble::wxCircleDouble(const wxPoint2DDouble &p1, const wxPoint2DDouble &p2, const wxPoint2DDouble &p3) { wxDouble A = p2.m_x - p1.m_x, B = p2.m_y - p1.m_y, C = p3.m_x - p1.m_x, D = p3.m_y - p1.m_y; wxDouble E = A*(p1.m_x + p2.m_x) + B*(p1.m_y + p2.m_y), F = C*(p1.m_x + p3.m_x) + D*(p1.m_y + p3.m_y), G = 2.0*(A*(p3.m_y - p2.m_y)-B*(p3.m_x - p2.m_x)); if (G == 0) { m_x = m_y = m_r = 0; return; } m_x = (D*E - B*F) / G, m_y = (A*F - C*E) / G; m_r = sqrt( (p1.m_x - m_x)*(p1.m_x - m_x) + (p1.m_y - m_y)*(p1.m_y - m_y) ); } int wxCircleDouble::IntersectLine( const wxRay2DDouble &line, wxPoint2DDouble *pt1, wxPoint2DDouble *pt2 ) const { //if (line.GetDistanceToPoint(m_origin) > m_r) return 0; wxDouble l1_x = m_x-m_r, l1_y = line.GetYFromX(l1_x); wxDouble l2_x = m_x+m_r, l2_y = line.GetYFromX(l2_x); // quick check to see it it intersects at all //wxDouble top = m_origin.m_y-m_r, bot = m_origin.m_y+m_r; //if (((l1_y < top)&&(l2_y < top))||((l1_y > bot)&&(l2_y > bot))) return 0; wxDouble l2_l1_x = l2_x - l1_x, l2_l1_y = l2_y - l1_y; wxDouble a = l2_l1_x*l2_l1_x + l2_l1_y*l2_l1_y; wxDouble b = 2.0 * (l2_l1_x * (l1_x - m_x) + l2_l1_y * (l1_y - m_y) ); wxDouble c = m_x*m_x + m_y*m_y + l1_x*l1_x + l1_y*l1_y - 2.0*(m_x*l1_x + m_y*l1_y) - m_r*m_r; wxDouble det = b*b - 4.0*a*c; if ( det < 0 ) { return 0; } else if ( det == 0 ) { if (pt1) { wxDouble u = -b/(2.0*a); pt1->m_x = l2_x + u*l2_l1_x; pt1->m_y = l2_y + u*l2_l1_y; } return 1; } // else det > 0 so 2 points intersect wxDouble e = sqrt(det); if (pt1) { wxDouble u1 = (-b - e)/( 2.0*a ); pt1->m_x = l1_x + u1*l2_l1_x; pt1->m_y = l1_y + u1*l2_l1_y; } if (pt2) { wxDouble u2 = (-b + e)/( 2.0*a ); pt2->m_x = l1_x + u2*l2_l1_x; pt2->m_y = l1_y + u2*l2_l1_y; } return 2; } /* int wxEllipseInt::IntersectLine( const wxLine2DInt &line, wxPoint2DInt &pt1, wxPoint2DInt &pt2 ) const { //Intersection.intersectEllipseLine = function(c, rx, ry, a1, a2) { //var result; //line.m_pt // var origin = new Vector2D(a1.x, a1.y); wxPoint2DInt dir = pt2 - p21; // var dir = Vector2D.fromPoints(a1, a2); //m_origin //var center = new Vector2D(c.x, c.y); wxPoint2DInt diff = line.m_pt - m_origin; //var diff = origin.subtract(center); //var mDir = new Vector2D( dir.x/(rx*rx), dir.y/(ry*ry) ); wxPoint2DDouble mDir = wxPoint2DDouble(wxDouble(dir.m_x)/(m_radius.m_x*m_radius.m_x), wxDouble(dir.m_y)/(m_radius.m_y*m_radius.m_y)); //var mDiff = new Vector2D( diff.x/(rx*rx), diff.y/(ry*ry) ); wxPoint2DDouble mDiff = wxPoint2DDouble(wxDouble(diff.m_x)/(m_radius.m_x*m_radius.m_x), wxDouble(diff.m_y)/(m_radius.m_y*m_radius.m_y)); wxDouble a = dir.GetDotProduct(mDir); //var a = dir.dot(mDir); wxDouble b = dir.GetDotProduct(mDiff); //var b = dir.dot(mDiff); wxDouble c = diff.GetDotProduct(m_diff); //var c = diff.dot(mDiff) - 1.0; wxDouble d = b*b - a*c; //var d = b*b - a*c; if ( d < 0 ) { return 0; //result = new Intersection("Outside"); } else if ( d > 0 ) { wxDouble root = sqrt(d); //var root = Math.sqrt(d); wxDouble t_a = (-b - root)/a; //var t_a = (-b - root) / a; wxDouble t_b = (-b + root)/a; //var t_b = (-b + root) / a; if ( (t_a < 0 || 1 < t_a) && (t_b < 0 || 1 < t_b) ) { if ( (t_a < 0 && t_b < 0) || (t_a > 1 && t_b > 1) ) result = new Intersection("Outside"); else result = new Intersection("Inside"); } else { result = new Intersection("Intersection"); if ( 0 <= t_a && t_a <= 1 ) result.appendPoint( a1.lerp(a2, t_a) ); if ( 0 <= t_b && t_b <= 1 ) result.appendPoint( a1.lerp(a2, t_b) ); } } else { var t = -b/a; if ( 0 <= t && t <= 1 ) { result = new Intersection("Intersection"); result.appendPoint( a1.lerp(a2, t) ); } else { result = new Intersection("Outside"); } } return result; } */ /* > I am looking for the algorithm to calculate the intersection of a line with > an ellipse, that is not necessarily parrallel to x,y axis. > > I cannot find anything that is easy to understand. The ellipse can be represented by a quadratic polynomial, a00+a10*x+a01*y+a20*x^2+a11*x*y+a02*y^2 = 0. The line is b0+b1*x+b2*y = 0 where one of b1 or b2 is not zero. For the sake of argument, suppose b2 is not zero. Solve for y = -(b0+b1*x)/b2. Replace this in the quadratic equation and multiply through by b2^2 to get Q(x) = c0 + c1*x + c2*x^2 = 0 where c0 = a02*b0^2-a01*b0*b2+a00*b2^2 c1 = 2*a02*b0*b1-a11*b0*b2-a01*b1*b2+a10*b2^2 c2 = a02*b1^2-a11*b1*b2+a02*b2^2 If Q(x) has no real roots, the line and ellipse do not intersect. If Q(x) has a single, repeated real root x0, the line and ellipse are tangent. The y-value is y0 = -(b0+b1*x0)/b2. If Q(x) has two distinct real roots x0 and x1, the line and ellipse intersect in two points (x0,y0) and (x1,y1) where y0 = -(b0+b1*x0)/b2 and y1 = -(b0+b1*x1)/b2. */ gambit-0.2010.09.01/src/labenski/src/lm_lsqr.cpp0000644000076500007650000015131511350032206015761 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: lm_lsqr.cpp // Purpose: Levenberg-Marquart nonlinear least squares 2-D curve fitting // Author: John Labenski, mostly others (see lm_lsqr.h) // Modified by: // Created: 6/5/2002 // Copyright: (c) John Labenski, mostly others (see lm_lsqr.h) // Licence: Public domain ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "lm_lsqr.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/dynarray.h" #include "wx/log.h" #endif // WX_PRECOMP #include "wx/math.h" #include "wx/plotctrl/plotdata.h" #include "wx/plotctrl/lm_lsqr.h" #undef BUG #define BUG 0 //---------------------------------------------------------------------------- // LM_LeastSquareProgressHandler_ //---------------------------------------------------------------------------- static LM_LeastSquareProgressHandler_ s_lm_leastsquarehandler = (LM_LeastSquareProgressHandler_)NULL; void SetLM_LeastSquareProgressHandler( LM_LeastSquareProgressHandler_ handler ) { s_lm_leastsquarehandler = handler; } static int s_nprint = 0; void SetLM_LeastSquareProgressHandlerTicks( int iterations ) { wxCHECK_RET( (iterations>=0), wxT("invalid iteration step size")); s_nprint = iterations; } /************************lmmisc.c*************************/ inline double dmax1(double a, double b) { return ( a >= b ) ? a : b; } inline double dmin1(double a, double b) { return ( a <= b ) ? a : b; } inline int min0(int a, int b) { return ( a <= b ) ? a : b; } inline int mod( int k, int m ) { return ( k % m ); } void pmat( int m, int n, double y[] ) { int i, j, k = 0; for( i=0; i 1) && (plotData.GetCount() >= plotFunc.GetNumberVariables() - 1), false, wxT("invalid dimensions")); m_plotData = new wxPlotData(plotData); m_plotFunc = new wxPlotFunction(plotFunc); double *x_data = m_plotData->GetXData(); double *y_data = m_plotData->GetYData(); int data_count = m_plotData->GetCount(); for (int i=0; i 0)) { wxCHECK_MSG(init_count <= m_n, 0, wxT("Invalid initializer count")); // initialize the variables for (i=0; i=0)&&(nGetFunctionString(), m_nfev, m_maxfev))) *iflag = -1; } return; } double *x_data = m_plotData->GetXData(); double *y_data = m_plotData->GetYData(); double f = 0; memcpy(m_vars, x, n*sizeof(double)); for (int i=0; iGetValue(m_vars); if (!wxFinite(f)) { m_nan++; fvec[i] = 0; continue; } fvec[i] = (*y_data) - f; } } /*********************** lmdif.c ****************************/ #define BUG 0 /* * ********** * * subroutine lmdif * * the purpose of lmdif is to minimize the sum of the squares of * m nonlinear functions in n variables by a modification of * the levenberg-marquardt algorithm. the user must provide a * subroutine which calculates the functions. the jacobian is * then calculated by a forward-difference approximation. * * the subroutine statement is * * subroutine lmdif(fcn,m,n,x,fvec,ftol,xtol,gtol,maxfev,epsfcn, * diag,mode,factor,nprint,info,nfev,fjac, * ldfjac,ipvt,qtf,wa1,wa2,wa3,wa4) * * where * * fcn is the name of the user-supplied subroutine which * calculates the functions. fcn must be declared * in an external statement in the user calling * program, and should be written as follows. * * subroutine fcn(m,n,x,fvec,iflag) * integer m,n,iflag * double precision x(n),fvec(m) * ---------- * calculate the functions at x and * return this vector in fvec. * ---------- * return * end * * the value of iflag should not be changed by fcn unless * the user wants to terminate execution of lmdif. * in this case set iflag to a negative integer. * * m is a positive integer input variable set to the number * of functions. * * n is a positive integer input variable set to the number * of variables. n must not exceed m. * * x is an array of length n. on input x must contain * an initial estimate of the solution vector. on output x * contains the final estimate of the solution vector. * * fvec is an output array of length m which contains * the functions evaluated at the output x. * * ftol is a nonnegative input variable. termination * occurs when both the actual and predicted relative * reductions in the sum of squares are at most ftol. * therefore, ftol measures the relative error desired * in the sum of squares. * * xtol is a nonnegative input variable. termination * occurs when the relative error between two consecutive * iterates is at most xtol. therefore, xtol measures the * relative error desired in the approximate solution. * * gtol is a nonnegative input variable. termination * occurs when the cosine of the angle between fvec and * any column of the jacobian is at most gtol in absolute * value. therefore, gtol measures the orthogonality * desired between the function vector and the columns * of the jacobian. * * maxfev is a positive integer input variable. termination * occurs when the number of calls to fcn is at least * maxfev by the end of an iteration. * * epsfcn is an input variable used in determining a suitable * step length for the forward-difference approximation. this * approximation assumes that the relative errors in the * functions are of the order of epsfcn. if epsfcn is less * than the machine precision, it is assumed that the relative * errors in the functions are of the order of the machine * precision. * * diag is an array of length n. if mode = 1 (see * below), diag is internally set. if mode = 2, diag * must contain positive entries that serve as * multiplicative scale factors for the variables. * * mode is an integer input variable. if mode = 1, the * variables will be scaled internally. if mode = 2, * the scaling is specified by the input diag. other * values of mode are equivalent to mode = 1. * * factor is a positive input variable used in determining the * initial step bound. this bound is set to the product of * factor and the euclidean norm of diag*x if nonzero, or else * to factor itself. in most cases factor should lie in the * interval (.1,100.). 100. is a generally recommended value. * * nprint is an integer input variable that enables controlled * printing of iterates if it is positive. in this case, * fcn is called with iflag = 0 at the beginning of the first * iteration and every nprint iterations thereafter and * immediately prior to return, with x and fvec available * for printing. if nprint is not positive, no special calls * of fcn with iflag = 0 are made. * * info is an integer output variable. if the user has * terminated execution, info is set to the (negative) * value of iflag. see description of fcn. otherwise, * info is set as follows. * * info = 0 improper input parameters. * * info = 1 both actual and predicted relative reductions * in the sum of squares are at most ftol. * * info = 2 relative error between two consecutive iterates * is at most xtol. * * info = 3 conditions for info = 1 and info = 2 both hold. * * info = 4 the cosine of the angle between fvec and any * column of the jacobian is at most gtol in * absolute value. * * info = 5 number of calls to fcn has reached or * exceeded maxfev. * * info = 6 ftol is too small. no further reduction in * the sum of squares is possible. * * info = 7 xtol is too small. no further improvement in * the approximate solution x is possible. * * info = 8 gtol is too small. fvec is orthogonal to the * columns of the jacobian to machine precision. * * nfev is an integer output variable set to the number of * calls to fcn. * * fjac is an output m by n array. the upper n by n submatrix * of fjac contains an upper triangular matrix r with * diagonal elements of nonincreasing magnitude such that * * t t t * p *(jac *jac)*p = r *r, * * where p is a permutation matrix and jac is the final * calculated jacobian. column j of p is column ipvt(j) * (see below) of the identity matrix. the lower trapezoidal * part of fjac contains information generated during * the computation of r. * * ldfjac is a positive integer input variable not less than m * which specifies the leading dimension of the array fjac. * * ipvt is an integer output array of length n. ipvt * defines a permutation matrix p such that jac*p = q*r, * where jac is the final calculated jacobian, q is * orthogonal (not stored), and r is upper triangular * with diagonal elements of nonincreasing magnitude. * column j of p is column ipvt(j) of the identity matrix. * * qtf is an output array of length n which contains * the first n elements of the vector (q transpose)*fvec. * * wa1, wa2, and wa3 are work arrays of length n. * * wa4 is a work array of length m. * * subprograms called * * user-supplied ...... fcn * * minpack-supplied ... dpmpar,enorm,fdjac2,lmpar,qrfac * * fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod * * argonne national laboratory. minpack project. march 1980. * burton s. garbow, kenneth e. hillstrom, jorge j. more * * ********** */ void LM_LeastSquare::lmdif( int m, int n, double x[], double fvec[], double ftol, double xtol, double gtol, int maxfev, double epsfcn, double diag[], int mode, double factor, int nprint, int *info, int *nfev, double fjac[], int ldfjac, int ipvt[], double qtf[], double wa1[], double wa2[], double wa3[], double wa4[]) { int i, iflag, ij, jj, iter, j, l; double actred, delta, dirder, fnorm, fnorm1, gnorm; double par, pnorm, prered, ratio; double sum, temp, temp1, temp2, temp3, xnorm; static double one = 1.0; static double p1 = 0.1; static double p5 = 0.5; static double p25 = 0.25; static double p75 = 0.75; static double p0001 = 1.0e-4; static double zero = 0.0; // static double p05 = 0.05; *info = 0; iflag = 0; *nfev = 0; delta = 0.0; xnorm = 0.0; // check the input parameters for errors. if ( (n <= 0) || (m < n) || (ldfjac < m) || (ftol < zero) || (xtol < zero) || (gtol < zero) || (maxfev <= 0) || (factor <= zero) ) goto L300; if( mode == 2 ) { // scaling by diag[] for( j=0; j 0 ) { iflag = 0; if(mod(iter-1,nprint) == 0) { fcn(m,n,x,fvec,&iflag); if(iflag < 0) goto L300; #if BUG printf( "fnorm %.15e\n", enorm(m,fvec) ); #endif } } // compute the qr factorization of the jacobian. qrfac(m,n,fjac,ldfjac,1,ipvt,n,wa1,wa2,wa3); // on the first iteration and if mode is 1, scale according // to the norms of the columns of the initial jacobian. if(iter == 1) { if(mode != 2) { for( j=0; j= zero) temp = p5; else temp = p5*dirder/(dirder + p5*actred); if( ((p1*fnorm1) >= fnorm) || (temp < p1) ) temp = p1; delta = temp*dmin1(delta,pnorm/p1); par = par/temp; } else { if( (par == zero) || (ratio >= p75) ) { delta = pnorm/p5; par = p5*par; } } // test for successful iteration. if(ratio >= p0001) { // successful iteration. update x, fvec, and their norms. for( j=0; j= maxfev) *info = 5; if( (fabs(actred) <= m_eps) && (prered <= m_eps) && (p5*ratio <= one) ) *info = 6; if(delta <= m_eps*xnorm) *info = 7; if(gnorm <= m_eps) *info = 8; if( *info != 0) goto L300; // end of the inner loop. repeat if iteration unsuccessful. if(ratio < p0001) goto L200; // end of the outer loop. goto L30; L300: // termination, either normal or user imposed. if(iflag < 0) *info = iflag; iflag = 0; if(nprint > 0) fcn(m,n,x,fvec,&iflag); } /************************lmpar.c*************************/ #define BUG 0 /* ********** * * subroutine lmpar * * given an m by n matrix a, an n by n nonsingular diagonal * matrix d, an m-vector b, and a positive number delta, * the problem is to determine a value for the parameter * par such that if x solves the system * * a*x = b , sqrt(par)*d*x = 0 , * * in the least squares sense, and dxnorm is the euclidean * norm of d*x, then either par is zero and * * (dxnorm-delta) .le. 0.1*delta , * * or par is positive and * * abs(dxnorm-delta) .le. 0.1*delta . * * this subroutine completes the solution of the problem * if it is provided with the necessary information from the * qr factorization, with column pivoting, of a. that is, if * a*p = q*r, where p is a permutation matrix, q has orthogonal * columns, and r is an upper triangular matrix with diagonal * elements of nonincreasing magnitude, then lmpar expects * the full upper triangle of r, the permutation matrix p, * and the first n components of (q transpose)*b. on output * lmpar also provides an upper triangular matrix s such that * * t t t * p *(a *a + par*d*d)*p = s *s . * * s is employed within lmpar and may be of separate interest. * * only a few iterations are generally needed for convergence * of the algorithm. if, however, the limit of 10 iterations * is reached, then the output par will contain the best * value obtained so far. * * the subroutine statement is * * subroutine lmpar(n,r,ldr,ipvt,diag,qtb,delta,par,x,sdiag, * wa1,wa2) * * where * * n is a positive integer input variable set to the order of r. * * r is an n by n array. on input the full upper triangle * must contain the full upper triangle of the matrix r. * on output the full upper triangle is unaltered, and the * strict lower triangle contains the strict upper triangle * (transposed) of the upper triangular matrix s. * * ldr is a positive integer input variable not less than n * which specifies the leading dimension of the array r. * * ipvt is an integer input array of length n which defines the * permutation matrix p such that a*p = q*r. column j of p * is column ipvt(j) of the identity matrix. * * diag is an input array of length n which must contain the * diagonal elements of the matrix d. * * qtb is an input array of length n which must contain the first * n elements of the vector (q transpose)*b. * * delta is a positive input variable which specifies an upper * bound on the euclidean norm of d*x. * * par is a nonnegative variable. on input par contains an * initial estimate of the levenberg-marquardt parameter. * on output par contains the final estimate. * * x is an output array of length n which contains the least * squares solution of the system a*x = b, sqrt(par)*d*x = 0, * for the output par. * * sdiag is an output array of length n which contains the * diagonal elements of the upper triangular matrix s. * * wa1 and wa2 are work arrays of length n. * * subprograms called * * minpack-supplied ... dpmpar,enorm,qrsolv * * fortran-supplied ... dabs,dmax1,dmin1,dsqrt * * argonne national laboratory. minpack project. march 1980. * burton s. garbow, kenneth e. hillstrom, jorge j. more * * ********** */ void LM_LeastSquare::lmpar(int n, double r[], int ldr, int ipvt[], double diag[], double qtb[], double delta, double *par, double x[], double sdiag[], double wa1[], double wa2[]) { int i,iter,ij,jj,j,jm1,jp1,k,l,nsing; double dxnorm,fp,gnorm,parc,parl,paru; double sum,temp; static double zero = 0.0; // static double one = 1.0; static double p1 = 0.1; static double p001 = 0.001; #if BUG printf( "lmpar\n" ); #endif // compute and store in x the gauss-newton direction. if the // jacobian is rank-deficient, obtain a least squares solution. nsing = n; jj = 0; for( j=0; j= 1) { for( k=0; k= 0) { ij = ldr * j; for( i=0; i<=jm1; i++ ) { wa1[i] -= r[ij]*temp; ij += 1; } } } } for( j=0; j= n) { for( j=0; j= 0) { ij = jj; for( i=0; i<=jm1; i++ ) { sum += r[ij]*wa1[i]; ij += 1; } } wa1[j] = (wa1[j] - sum)/r[j+ldr*j]; jj += ldr; // [i+ldr*j] } temp = enorm(n,wa1); parl = ((fp/delta)/temp)/temp; } // calculate an upper bound, paru, for the zero of the function. jj = 0; for( j=0; j zero) parl = dmax1(parl, *par); if(fp < zero) paru = dmin1(paru, *par); // compute an improved estimate for par. *par = dmax1(parl, *par + parc); // end of an iteration. goto L150; L220: // termination. if(iter == 0) *par = zero; } /************************qrfac.c*************************/ #define BUG 0 /* * ********** * * subroutine qrfac * * this subroutine uses householder transformations with column * pivoting (optional) to compute a qr factorization of the * m by n matrix a. that is, qrfac determines an orthogonal * matrix q, a permutation matrix p, and an upper trapezoidal * matrix r with diagonal elements of nonincreasing magnitude, * such that a*p = q*r. the householder transformation for * column k, k = 1,2,...,min(m,n), is of the form * * t * i - (1/u(k))*u*u * * where u has zeros in the first k-1 positions. the form of * this transformation and the method of pivoting first * appeared in the corresponding linpack subroutine. * * the subroutine statement is * * subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa) * * where * * m is a positive integer input variable set to the number * of rows of a. * * n is a positive integer input variable set to the number * of columns of a. * * a is an m by n array. on input a contains the matrix for * which the qr factorization is to be computed. on output * the strict upper trapezoidal part of a contains the strict * upper trapezoidal part of r, and the lower trapezoidal * part of a contains a factored form of q (the non-trivial * elements of the u vectors described above). * * lda is a positive integer input variable not less than m * which specifies the leading dimension of the array a. * * pivot is a logical input variable. if pivot is set true, * then column pivoting is enforced. if pivot is set false, * then no column pivoting is done. * * ipvt is an integer output array of length lipvt. ipvt * defines the permutation matrix p such that a*p = q*r. * column j of p is column ipvt(j) of the identity matrix. * if pivot is false, ipvt is not referenced. * * lipvt is a positive integer input variable. if pivot is false, * then lipvt may be as small as 1. if pivot is true, then * lipvt must be at least n. * * rdiag is an output array of length n which contains the * diagonal elements of r. * * acnorm is an output array of length n which contains the * norms of the corresponding columns of the input matrix a. * if this information is not needed, then acnorm can coincide * with rdiag. * * wa is a work array of length n. if pivot is false, then wa * can coincide with rdiag. * * subprograms called * * minpack-supplied ... dpmpar,enorm * * fortran-supplied ... dmax1,dsqrt,min0 * * argonne national laboratory. minpack project. march 1980. * burton s. garbow, kenneth e. hillstrom, jorge j. more * * ********** */ void LM_LeastSquare::qrfac(int m, int n, double a[], int WXUNUSED(lda), int pivot, int ipvt[], int WXUNUSED(lipvt), double rdiag[], double acnorm[], double wa[]) { int i,ij,jj,j,jp1,k,kmax,minmn; double ajnorm,sum,temp; static double zero = 0.0; static double one = 1.0; static double p05 = 0.05; // compute the initial column norms and initialize several arrays. ij = 0; for( j=0; j rdiag[kmax]) kmax = k; } if(kmax == j) goto L40; ij = m * j; jj = m * kmax; for( i=0; i kp1 ) { ik = kk + 1; for( i=kp1; i jp1) { ij = jp1 + ldr * j; for( i=jp1; i rdwarf) && (xabs < agiant) ) { // sum for intermediate components. s2 += xabs*xabs; continue; } if(xabs > rdwarf) { // sum for large components. if(xabs > x1max) { temp = x1max/xabs; s1 = one + s1*temp*temp; x1max = xabs; } else { temp = xabs/x1max; s1 += temp*temp; } continue; } // sum for small components. if(xabs > x3max) { temp = x3max/xabs; s3 = one + s3*temp*temp; x3max = xabs; } else { if(xabs != zero) { temp = xabs/x3max; s3 += temp*temp; } } } // calculation of norm. if(s1 != zero) { temp = s1 + (s2/x1max)/x1max; ans = x1max*sqrt(temp); return(ans); } if(s2 != zero) { if(s2 >= x3max) temp = s2*(one+(x3max/s2)*(x3max*s3)); else temp = x3max*((s2/x3max)+(x3max*s3)); ans = sqrt(temp); } else { ans = x3max*sqrt(s3); } return(ans); } /************************fdjac2.c*************************/ #define BUG 0 /* * ********** * * subroutine fdjac2 * * this subroutine computes a forward-difference approximation * to the m by n jacobian matrix associated with a specified * problem of m functions in n variables. * * the subroutine statement is * * subroutine fdjac2(fcn,m,n,x,fvec,fjac,ldfjac,iflag,epsfcn,wa) * * where * * fcn is the name of the user-supplied subroutine which * calculates the functions. fcn must be declared * in an external statement in the user calling * program, and should be written as follows. * * subroutine fcn(m,n,x,fvec,iflag) * integer m,n,iflag * double precision x(n),fvec(m) * ---------- * calculate the functions at x and * return this vector in fvec. * ---------- * return * end * * the value of iflag should not be changed by fcn unless * the user wants to terminate execution of fdjac2. * in this case set iflag to a negative integer. * * m is a positive integer input variable set to the number * of functions. * * n is a positive integer input variable set to the number * of variables. n must not exceed m. * * x is an input array of length n. * * fvec is an input array of length m which must contain the * functions evaluated at x. * * fjac is an output m by n array which contains the * approximation to the jacobian matrix evaluated at x. * * ldfjac is a positive integer input variable not less than m * which specifies the leading dimension of the array fjac. * * iflag is an integer variable which can be used to terminate * the execution of fdjac2. see description of fcn. * * epsfcn is an input variable used in determining a suitable * step length for the forward-difference approximation. this * approximation assumes that the relative errors in the * functions are of the order of epsfcn. if epsfcn is less * than the machine precision, it is assumed that the relative * errors in the functions are of the order of the machine * precision. * * wa is a work array of length m. * * subprograms called * * user-supplied ...... fcn * * minpack-supplied ... dpmpar * * fortran-supplied ... dabs,dmax1,dsqrt * * argonne national laboratory. minpack project. march 1980. * burton s. garbow, kenneth e. hillstrom, jorge j. more * ********** */ void LM_LeastSquare::fdjac2(int m,int n, double x[], double fvec[], double fjac[], int WXUNUSED(ldfjac), int *iflag, double epsfcn, double wa[]) { int i,j,ij; double eps,h,temp; static double zero = 0.0; temp = dmax1(epsfcn,m_eps); eps = sqrt(temp); #if BUG printf( "fdjac2\n" ); #endif ij = 0; for( j=0; jGetLabelButton(); // pretend that both buttons have focus (for flat style) if (labelBut) { wxPoint p = GetParent()->ScreenToClient(wxGetMousePosition()); #if wxCHECK_VERSION(2,7,0) if (GetRect().Contains(p) || labelBut->GetRect().Contains(p)) #else if (GetRect().Inside(p) || labelBut->GetRect().Inside(p)) #endif { m_focused = true; if (!labelBut->GetFocused()) labelBut->SetFocused(true); } else { m_focused = false; if (labelBut->GetFocused()) labelBut->SetFocused(false); } } wxCustomButton::Paint(dc); } }; // ========================================================================== // MenuLabelButton // ========================================================================== class MenuLabelButton : public wxCustomButton { public: MenuLabelButton( wxWindow* parent, wxWindowID id, const wxString &label, const wxBitmap &bitmap, long style ) : wxCustomButton() { Create(parent, id, label, bitmap, wxDefaultPosition, wxDefaultSize, style); } virtual void Paint( wxDC &dc ) { wxCustomButton *dropBut = ((wxMenuButton*)GetParent())->GetDropDownButton(); // pretend that both buttons have focus (for flat style) if (dropBut) { wxPoint p = GetParent()->ScreenToClient(wxGetMousePosition()); #if wxCHECK_VERSION(2,7,0) if (GetRect().Contains(p) || dropBut->GetRect().Contains(p)) #else if (GetRect().Inside(p) || dropBut->GetRect().Inside(p)) #endif { m_focused = true; if (!dropBut->GetFocused()) dropBut->SetFocused(true); } else { m_focused = false; if (dropBut->GetFocused()) dropBut->SetFocused(false); } } wxCustomButton::Paint(dc); } }; // ========================================================================== // wxMenuButton // ========================================================================== IMPLEMENT_DYNAMIC_CLASS( wxMenuButton, wxControl ) BEGIN_EVENT_TABLE(wxMenuButton,wxControl) EVT_BUTTON(wxID_ANY, wxMenuButton::OnButton) #ifdef __WXMSW__ EVT_MENU(wxID_ANY, wxMenuButton::OnMenu) #endif END_EVENT_TABLE() wxMenuButton::~wxMenuButton() { AssignMenu(NULL, true); } void wxMenuButton::Init() { m_labelButton = NULL; m_dropdownButton = NULL; m_menu = NULL; m_menu_static = false; m_style = 0; } bool wxMenuButton::Create( wxWindow* parent, wxWindowID id, const wxString &label, const wxBitmap &bitmap, const wxPoint& pos, const wxSize& size, long style, const wxValidator& val, const wxString& name) { m_style = style; long flat = style & wxMENUBUT_FLAT; wxControl::Create(parent,id,pos,size,wxNO_BORDER|wxCLIP_CHILDREN,val,name); wxControl::SetLabel(label); SetBackgroundColour(parent->GetBackgroundColour()); SetForegroundColour(parent->GetForegroundColour()); SetFont(parent->GetFont()); m_labelButton = new MenuLabelButton(this, id, label, bitmap, wxCUSTBUT_BUTTON|flat); m_dropdownButton = new MenuDropButton(this, IDD_DROPDOWN_BUTTON, wxCUSTBUT_BUTTON|flat); wxSize bestSize = DoGetBestSize(); SetSize( wxSize(size.x < 0 ? bestSize.x : size.x, size.y < 0 ? bestSize.y : size.y) ); //SetBestSize(GetSize()); return true; } #ifdef __WXMSW__ // FIXME - I think there was a patch to fix this void wxMenuButton::OnMenu( wxCommandEvent &event ) { event.Skip(); wxMenuItem *mi = m_menu->FindItem(event.GetId()); if (mi && (mi->GetKind() == wxITEM_RADIO)) m_menu->Check(event.GetId(), true); } #endif // __WXMSW__ void wxMenuButton::OnButton( wxCommandEvent &event) { int win_id = event.GetId(); if (win_id == IDD_DROPDOWN_BUTTON) { if (m_menu) { wxNotifyEvent mevent(wxEVT_MENUBUTTON_OPEN, GetId()); mevent.SetEventObject(this); if (GetEventHandler()->ProcessEvent(mevent) && !mevent.IsAllowed()) return; if (!m_menu) return; PopupMenu(m_menu, wxPoint(0, GetSize().y)); m_labelButton->Refresh(false); m_dropdownButton->Refresh(false); } } else if (win_id == m_labelButton->GetId()) { if (!m_menu) return; const wxMenuItemList &items = m_menu->GetMenuItems(); int first_radio_id = -1; int checked_id = -1; bool check_next = false; // find the next available radio item to check for (wxMenuItemList::Node *node = items.GetFirst(); node; node = node->GetNext()) { wxMenuItem *mi = (wxMenuItem*)node->GetData(); if (mi && (mi->GetKind() == wxITEM_RADIO)) { if (first_radio_id == -1) first_radio_id = mi->GetId(); if (check_next) { check_next = false; checked_id = mi->GetId(); break; } else if (mi->IsChecked()) check_next = true; } } // the last item was checked, go back to the first if (check_next && (first_radio_id != -1)) checked_id = first_radio_id; if (checked_id != -1) { m_menu->Check(checked_id, true); wxCommandEvent mevent( wxEVT_COMMAND_MENU_SELECTED, checked_id); mevent.SetEventObject( m_menu ); mevent.SetInt(1); GetEventHandler()->ProcessEvent(mevent); } } } int wxMenuButton::GetSelection() const { wxCHECK_MSG(m_menu != NULL, wxNOT_FOUND, wxT("No attached menu in wxMenuButton::GetSelection")); const wxMenuItemList &items = m_menu->GetMenuItems(); for (wxMenuItemList::Node *node = items.GetFirst(); node; node = node->GetNext()) { wxMenuItem *mi = (wxMenuItem*)node->GetData(); if (mi && (mi->GetKind() == wxITEM_RADIO)) { if (mi->IsChecked()) return mi->GetId(); } } return wxNOT_FOUND; } void wxMenuButton::AssignMenu(wxMenu *menu, bool static_menu) { if (!m_menu_static && m_menu) delete m_menu; m_menu = menu; m_menu_static = static_menu; } void wxMenuButton::SetToolTip(const wxString &tip) { wxWindow::SetToolTip(tip); ((wxWindow*)m_labelButton)->SetToolTip(tip); ((wxWindow*)m_dropdownButton)->SetToolTip(tip); } void wxMenuButton::SetToolTip(wxToolTip *tip) { wxWindow::SetToolTip(tip); ((wxWindow*)m_labelButton)->SetToolTip(tip); ((wxWindow*)m_dropdownButton)->SetToolTip(tip); } void wxMenuButton::DoSetSize(int x, int y, int width, int height, int sizeFlags) { wxSize curSize( GetSize() ); wxSize bestSize( DoGetBestSize() ); if (width == -1) width = curSize.GetWidth(); if (width < 10) width = bestSize.GetWidth(); if (height == -1) height = curSize.GetHeight(); if (height < 5) height = bestSize.GetHeight(); wxWindow::DoSetSize(x, y, width, height, sizeFlags); if (m_labelButton) m_labelButton->SetSize(0, 0, width - wxMENUBUTTON_DROP_WIDTH, height); if (m_dropdownButton) m_dropdownButton->SetSize(width-wxMENUBUTTON_DROP_WIDTH, 0, wxMENUBUTTON_DROP_WIDTH, height); } wxSize wxMenuButton::DoGetBestSize() { if (!m_labelButton || !m_dropdownButton) return wxSize(wxMENUBUTTON_DROP_WIDTH+wxMENUBUTTON_DROP_HEIGHT, wxMENUBUTTON_DROP_HEIGHT); wxSize size = m_labelButton->GetBestSize(); size.x += wxMENUBUTTON_DROP_WIDTH; return size; } gambit-0.2010.09.01/src/labenski/src/optvalue.cpp0000644000076500007650000004154511350032206016152 00000000000000///////////////////////////////////////////////////////////////////////////// // Name : optvalue.cpp // Author : John Labenski // Created : 07/01/02 // Copyright: John Labenski, 2002 // License : wxWidgets v2 ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "optvalue.h" #endif // For compilers that support precompilation, includes "wx/wx.h" #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/object.h" #include "wx/string.h" #include "wx/gdicmn.h" #endif // WX_PRECOMP #include "wx/tokenzr.h" #include "wx/wxthings/optvalue.h" #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArrayOptionValue); //---------------------------------------------------------------------------- // Global wxString utilities //---------------------------------------------------------------------------- /* wxArrayString wxStringToWords( const wxString &string ) { // wxArrayString arr; // wxString word, s = string.Strip(wxString::both); // wxMemoryInputStream memstream( s.c_str(), string.Length() ); // wxTextInputStream textstream(memstream); // while (!memstream.Eof()) // { // word = textstream.ReadWord(); // if (!word.IsEmpty()) arr.Add(word.Strip(wxString::both)); // } // return arr; wxArrayString arr; wxString s = string.Strip(wxString::both); while (!s.IsEmpty()) { arr.Add(s.BeforeFirst(wxT(' '))); s = s.AfterFirst(wxT(' ')).Strip(wxString::both); } return arr; } */ //---------------------------------------------------------------------------- // wxOptionValueRefData //---------------------------------------------------------------------------- class wxOptionValueRefData: public wxObjectRefData { public: wxOptionValueRefData() : wxObjectRefData() {} wxOptionValueRefData(const wxOptionValueRefData& data) : wxObjectRefData() { m_type = data.m_type; m_optionNames = data.m_optionNames; m_optionValues = data.m_optionValues; m_children = data.m_children;; } ~wxOptionValueRefData() {} wxString m_type; wxArrayString m_optionNames; wxArrayString m_optionValues; wxArrayOptionValue m_children; }; #define M_OPTVALUDATA ((wxOptionValueRefData *)m_refData) //---------------------------------------------------------------------------- // wxOptionValue - a ref counted wxString key, wxString value container //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxOptionValue, wxObject); wxObjectRefData *wxOptionValue::CreateRefData() const { return new wxOptionValueRefData; } wxObjectRefData *wxOptionValue::CloneRefData(const wxObjectRefData *data) const { return new wxOptionValueRefData(*(const wxOptionValueRefData *)data); } bool wxOptionValue::Create() { UnRef(); m_refData = new wxOptionValueRefData(); return Ok(); } bool wxOptionValue::Create( const wxOptionValue &optValue ) { wxCHECK_MSG( optValue.Ok(), false, wxT("Invalid wxOptionValue") ); UnRef(); Ref( optValue ); return Ok(); } bool wxOptionValue::Create( const wxString &string ) { UnRef(); m_refData = new wxOptionValueRefData(); int i, start = 0, length = string.Length(); wxString buff; const wxChar *s = string.GetData(); // const wxChar comma = 44; // comma const wxChar tab = 9; // tab // const wxChar space = 32; // space const wxChar cr = 13; // carrage return const wxChar lf = 10; // line feed const wxChar openbracket = wxT('['); const wxChar closebracket = wxT(']'); const wxChar equals = wxT('='); const wxChar ccr = wxT('\n'); bool has_type = false; for (i=0; im_type = buff; s++; start = i+1; break; } else if ((*s != tab) && (*s != cr) && (*s != lf) && (*s != ccr)) { buff.Append(*s); } else return false; } } buff.Clear(); for (i=start; i=0; j--) { const wxChar c = t[j]; if ((c == cr) || (c == lf) || (c == ccr) || (c == tab)) { j++; break; } } if (j<0) j = 0; M_OPTVALUDATA->m_optionNames.Add(buff.Mid(j)); buff.Remove(j).Trim(true); } if (!buff.IsEmpty()) M_OPTVALUDATA->m_optionValues.Add(buff); buff.Clear(); } s++; } buff.Trim(false).Trim(true); if (!buff.IsEmpty()) M_OPTVALUDATA->m_optionValues.Add(buff); if ((M_OPTVALUDATA->m_optionValues.GetCount() != M_OPTVALUDATA->m_optionNames.GetCount())) { int i; wxPrintf(wxT("wxOptionValue::wxOptionValue( const wxString &string BUSTED\n")); wxPrintf(wxT("[%s]\n"), M_OPTVALUDATA->m_type.c_str()); for (i=0; i<(int)M_OPTVALUDATA->m_optionNames.GetCount(); i++) wxPrintf(wxT("{%s}\n"), M_OPTVALUDATA->m_optionNames[i].c_str()); for (i=0; i<(int)M_OPTVALUDATA->m_optionValues.GetCount(); i++) wxPrintf(wxT("{%s}\n"), M_OPTVALUDATA->m_optionValues[i].c_str()); fflush(stdout); } return ((M_OPTVALUDATA->m_optionValues.GetCount() > 0) && (M_OPTVALUDATA->m_optionValues.GetCount() != M_OPTVALUDATA->m_optionNames.GetCount())); } bool wxOptionValue::Copy( const wxOptionValue &optValue ) { wxCHECK_MSG( optValue.Ok(), false, wxT("Invalid wxOptionValue") ); if (!Ok()) Create(); M_OPTVALUDATA->m_type = optValue.GetType(); M_OPTVALUDATA->m_optionNames = optValue.GetOptionNames(); M_OPTVALUDATA->m_optionValues = optValue.GetOptionValues(); if (optValue.GetChildrenCount()) M_OPTVALUDATA->m_children = *optValue.GetChildren(); else M_OPTVALUDATA->m_children.Clear(); return true; } bool wxOptionValue::Ok() const { return M_OPTVALUDATA != NULL; } void wxOptionValue::Destroy() { UnRef(); } //----------------------------------------------------------------------------- wxString wxOptionValue::GetType() const { wxCHECK_MSG( Ok(), wxEmptyString, wxT("Invalid wxOptionValue") ); return M_OPTVALUDATA->m_type; } void wxOptionValue::SetType( const wxString &type ) { wxCHECK_RET( Ok(), wxT("Invalid wxOptionValue") ); M_OPTVALUDATA->m_type = type; } //----------------------------------------------------------------------------- size_t wxOptionValue::GetChildrenCount() const { wxCHECK_MSG( Ok(), 0, wxT("Invalid wxOptionValue") ); return M_OPTVALUDATA->m_children.GetCount(); } wxArrayOptionValue *wxOptionValue::GetChildren() const { wxCHECK_MSG( Ok(), NULL, wxT("Invalid wxOptionValue") ); return &M_OPTVALUDATA->m_children; } bool wxOptionValue::AddChild( const wxOptionValue& child ) { wxCHECK_MSG( Ok() && child.Ok(), 0, wxT("Invalid wxOptionValue") ); M_OPTVALUDATA->m_children.Add(child); return true; } void wxOptionValue::DeleteChildren() { wxCHECK_RET( Ok(), wxT("Invalid wxOptionValue") ); M_OPTVALUDATA->m_children.Clear(); } //----------------------------------------------------------------------------- size_t wxOptionValue::GetOptionCount() const { wxCHECK_MSG( Ok(), 0, wxT("Invalid wxOptionValue") ); return M_OPTVALUDATA->m_optionNames.GetCount(); } wxArrayString wxOptionValue::GetOptionNames() const { wxCHECK_MSG( Ok(), wxArrayString(), wxT("Invalid wxOptionValue") ); return M_OPTVALUDATA->m_optionNames; } wxArrayString wxOptionValue::GetOptionValues() const { wxCHECK_MSG( Ok(), wxArrayString(), wxT("Invalid wxOptionValue") ); return M_OPTVALUDATA->m_optionValues; } wxString wxOptionValue::GetOptionName( size_t n ) const { wxCHECK_MSG( Ok() && (nm_optionNames.GetCount()), wxEmptyString, wxT("Invalid wxOptionValue") ); return M_OPTVALUDATA->m_optionNames[n]; } wxString wxOptionValue::GetOptionValue( size_t n ) const { wxCHECK_MSG( Ok() && (nm_optionValues.GetCount()), wxEmptyString, wxT("Invalid wxOptionValue") ); return M_OPTVALUDATA->m_optionValues[n]; } int wxOptionValue::HasOption(const wxString& name) const { wxCHECK_MSG( Ok(), wxNOT_FOUND, wxT("Invalid wxOptionValue") ); int index = M_OPTVALUDATA->m_optionNames.Index(name, false); return index; } int wxOptionValue::FindOption(const wxString &part_of_option_name) const { wxCHECK_MSG( Ok(), wxNOT_FOUND, wxT("Invalid wxOptionValue") ); int i, count = M_OPTVALUDATA->m_optionNames.GetCount(); for (i=0; im_optionNames[i].Contains(part_of_option_name)) return i; } return wxNOT_FOUND; } bool wxOptionValue::DeleteOption(const wxString &name) { wxCHECK_MSG( Ok(), false, wxT("Invalid wxOptionValue")); int index = M_OPTVALUDATA->m_optionNames.Index(name, false); if (index == wxNOT_FOUND) return false; M_OPTVALUDATA->m_optionNames.RemoveAt(index); M_OPTVALUDATA->m_optionValues.RemoveAt(index); return true; } bool wxOptionValue::DeleteOption( size_t n ) { wxCHECK_MSG( Ok(), false, wxT("Invalid wxOptionValue") ); wxCHECK_MSG( n < M_OPTVALUDATA->m_optionValues.GetCount(), false, wxT("invalid index")); M_OPTVALUDATA->m_optionNames.RemoveAt(n); M_OPTVALUDATA->m_optionValues.RemoveAt(n); return true; } //----------------------------------------------------------------------------- // Set Options // Option functions (arbitrary name/value mapping) void wxOptionValue::SetOption(const wxString& name, const wxString& value, bool force) { wxCHECK_RET( Ok() && (name.Length() > 0), wxT("Invalid wxOptionValue or option") ); int idx = M_OPTVALUDATA->m_optionNames.Index(name, false); if (idx == wxNOT_FOUND) { M_OPTVALUDATA->m_optionNames.Add(name); M_OPTVALUDATA->m_optionValues.Add(value); } else if (force) { M_OPTVALUDATA->m_optionNames[idx] = name; M_OPTVALUDATA->m_optionValues[idx] = value; } } void wxOptionValue::SetOption(const wxString &name, bool update, const wxChar *format, ...) { va_list argptr; va_start(argptr, format); wxString s; s.PrintfV(format, argptr); va_end(argptr); SetOption(name, s, update); } //----------------------------------------------------------------------------- // Get Options wxString wxOptionValue::GetOption(const wxString& name) const { wxCHECK_MSG( Ok(), wxEmptyString, wxT("Invalid wxOptionValue") ); int idx = M_OPTVALUDATA->m_optionNames.Index(name, false); if (idx != wxNOT_FOUND) return M_OPTVALUDATA->m_optionValues[idx]; return wxEmptyString; } int wxOptionValue::GetOptionInt(const wxString& name) const { return wxAtoi(GetOption(name)); } bool wxOptionValue::GetOption(const wxString& name, wxString &value ) const { wxString s = GetOption(name); if (!s.IsEmpty()) { value = s; return true; } return false; } bool wxOptionValue::GetOption(const wxString& name, int *value ) const { long n; if (GetOption(name).ToLong(&n)) { *value = (int)n; return true; } return false; } bool wxOptionValue::GetOption(const wxString& name, float *value ) const { double n; if (GetOption(name, &n)) { *value = (float)n; return true; } return false; } bool wxOptionValue::GetOption(const wxString& name, double *value ) const { double n; if (GetOption(name).ToDouble(&n)) { *value = n; return true; } return false; } int wxOptionValue::GetOption(const wxString& name, const wxChar *format, ...) const { wxString n = GetOption(name); if (n.IsEmpty()) return 0; va_list argptr; va_start(argptr, format); // int i = wxVsscanf(n.c_str(), format, argptr); // VisualStudio doesn't have this int i = wxSscanf(n.c_str(), format, argptr); va_end(argptr); return i; } int wxOptionValue::GetOption(const wxString& name, wxArrayInt &values, int count, const wxString& delims) const { wxString value = GetOption(name); wxStringTokenizer tokens(value, delims, wxTOKEN_STRTOK); int read_count = 0; while (((count < 0) || (read_count <= count)) && tokens.HasMoreTokens()) { long num; if (!tokens.GetNextToken().ToLong(&num)) return read_count; values.Add(num); read_count++; } return read_count; } bool wxOptionValue::GetOption(const wxString& name, unsigned char *value, int count, const wxString& delims) const { wxArrayInt intArr; intArr.Alloc(count); if (GetOption(name, intArr, count, delims) != count) return false; for (int i = 0; i < count; i++) value[i] = (unsigned char)intArr[i]; return true; } bool wxOptionValue::GetOption(const wxString& name, int *value, int count, const wxString& delims) const { wxArrayInt intArr; intArr.Alloc(count); if (GetOption(name, intArr, count, delims) != count) return false; for (int i = 0; i < count; i++) value[i] = intArr[i]; return true; } bool wxOptionValue::GetOption(const wxString& name, long *value, int count, const wxString& delims) const { wxArrayInt intArr; intArr.Alloc(count); if (GetOption(name, intArr, count, delims) != count) return false; for (int i = 0; i < count; i++) value[i] = intArr[i]; return true; } bool wxOptionValue::GetOption(const wxString& name, float *value, int count, const wxString& delims) const { double *nums = (double*)malloc(sizeof(double)*count); if (GetOption(name, nums, count, delims)) { for (int i=0; i < count; i++) value[i] = (float)nums[i]; free(nums); return true; } free(nums); return false; } bool wxOptionValue::GetOption(const wxString& name, double *value, int count, const wxString& delims) const { wxString optValue = GetOption(name); wxStringTokenizer tokens(optValue, delims, wxTOKEN_STRTOK); int read_count = 0; double *nums = (double*)malloc(sizeof(double)*count); double num; while ((read_count <= count) && tokens.HasMoreTokens()) { if (!tokens.GetNextToken().ToDouble(&num)) { free(nums); return false; } if (read_count >= count) break; read_count++; } if (read_count == count) { for (int i = 0; i < count; i++) value[i] = nums[i]; free(nums); return true; } free(nums); return false; } bool wxOptionValue::GetOption(const wxString& name, int *v1, int *v2, const wxString& delims) const { wxArrayInt intArr; if (GetOption(name, intArr, 2, delims) != 2) return false; if (v1) *v1 = intArr[0]; if (v2) *v2 = intArr[1]; return true; } bool wxOptionValue::GetOption(const wxString& name, int *v1, int *v2, int *v3, const wxString& delims) const { wxArrayInt intArr; if (GetOption(name, intArr, 3, delims) != 3) return false; if (v1) *v1 = intArr[0]; if (v2) *v2 = intArr[1]; if (v3) *v3 = intArr[2]; return true; } bool wxOptionValue::GetOption(const wxString& name, float *v1, float *v2, float *v3, const wxString& delims) const { double nums[3]; if (GetOption(name, nums, 3, delims)) return false; if (v1) *v1 = (float)nums[0]; if (v2) *v2 = (float)nums[1]; if (v3) *v3 = (float)nums[2]; return true; } bool wxOptionValue::GetOption(const wxString& name, wxRect &value, const wxString& delims) const { wxArrayInt intArr; if (GetOption(name, intArr, 4, delims) != 4) return false; value = wxRect(intArr[0], intArr[1], intArr[2], intArr[3]); return true; } gambit-0.2010.09.01/src/labenski/src/plotctrl.cpp0000644000076500007650000040570511441453421016167 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotctrl.cpp // Purpose: wxPlotCtrl // Author: John Labenski, Robert Roebling // Modified by: // Created: 8/27/2002 // Copyright: (c) John Labenski, Robert Roebling // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// //#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #if defined(__GNUG__) #pragma implementation "plotctrl.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/panel.h" #include "wx/scrolbar.h" #include "wx/event.h" #include "wx/timer.h" #include "wx/dcmemory.h" #include "wx/msgdlg.h" #include "wx/geometry.h" #include "wx/sizer.h" #include "wx/dcscreen.h" #include "wx/textctrl.h" #endif // WX_PRECOMP #include "wx/splitter.h" #include "wx/math.h" #include "wx/image.h" #include "wx/plotctrl/plotctrl.h" #include #include #include // MSVC hogs global namespace with these min/max macros - remove them #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef GetYValue // Visual Studio 7 defines this #undef GetYValue #endif //#define LONG_TO_WXCOLOUR(c) wxColour((unsigned char)((c>>16)&0xFF), (unsigned char)((c>>8 )&0xFF), (unsigned char)((c)&0xFF)) //#define WXCOLOUR_TO_LONG(c) ((c.Red()<<16)|(c.Green()<<8)|(c.Blue())) #define RINT(x) int((x) >= 0 ? ((x) + 0.5) : ((x) - 0.5)) #if !wxCHECK_VERSION(2,5,0) bool WXRECT2DDOUBLE_EQUAL(const wxRect2DDouble& r1, const wxRect2DDouble& r2) { return (r1.m_x == r1.m_x) && (r1.m_y == r1.m_y) && (r1.m_width == r1.m_width) && (r1.m_height == r1.m_height); } #else #define WXRECT2DDOUBLE_EQUAL(r1, r2) ((r1) == (r2)) #endif // wxCHECK_VERSION(2,5,0) #if !wxCHECK_VERSION(2,6,0) #define wxIMAGE_OPTION_CUR_HOTSPOT_X wxCUR_HOTSPOT_X #define wxIMAGE_OPTION_CUR_HOTSPOT_Y wxCUR_HOTSPOT_Y #endif //wxCHECK_VERSION(2,6,0) //----------------------------------------------------------------------------- // Consts //----------------------------------------------------------------------------- #define MAX_PLOT_ZOOMS 5 #define TIC_STEPS 3 std::numeric_limits wxDouble_limits; const wxDouble wxPlot_MIN_DBL = wxDouble_limits.min()*10; const wxDouble wxPlot_MAX_DBL = wxDouble_limits.max()/10; const wxDouble wxPlot_MAX_RANGE = wxDouble_limits.max()/5; //#define BORDER 4 // Draw borders around the axes, title, and labels for sizing testing //#define DRAW_BORDERS #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY( wxArrayPoint2DDouble ); WX_DEFINE_OBJARRAY( wxArrayRect2DDouble ); WX_DEFINE_OBJARRAY( wxArrayPlotCurve ); #include "../art/ledgrey.xpm" #include "../art/ledgreen.xpm" #include "../art/hand.xpm" #include "../art/grab.xpm" static wxCursor s_handCursor; static wxCursor s_grabCursor; // Skip the wxWidgets drawing routines since they calc an unnecessary bounding rect // You may turn this off by defining wxPLOT_FAST_GRAPHICS=0 to the compilier #ifndef wxPLOT_FAST_GRAPHICS #define wxPLOT_FAST_GRAPHICS 0 #endif // wxPLOT_FAST_GRAPHICS #if defined(__WXGTK__) && wxPLOT_FAST_GRAPHICS extern "C" { #include } #define INITIALIZE_FAST_GRAPHICS \ double dc_scale_x = 1, dc_scale_y = 1; \ dc->GetUserScale( &dc_scale_x, &dc_scale_y ); \ wxPoint dc_origin = dc->GetDeviceOrigin(); \ wxWindowDC *winDC = wxDynamicCast(dc, wxWindowDC); \ GdkWindow *window = NULL; \ GdkGC *pen = NULL; \ if (winDC && (dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0,0))) \ { \ window = winDC->m_window; \ pen = winDC->m_penGC; \ } // inline void wxPLOT_DRAW_LINE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0, int x1, int y1) #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ if (win && pen) \ gdk_draw_line( win, pen, x0, y0, x1, y1 ); \ else \ dc->DrawLine( x0, y0, x1, y1 ); // note : need to draw outline since the filled part isn't really a circle // gdk_draw_arc( win, pen, false, x0-2, y0-2, 4, 4, 0, 360*64 ); // false for outline, true for inside //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0) #define wxPLOT_DRAW_CIRCLE(dc, win, pen, x0, y0) \ if (win && pen) \ gdk_draw_arc( win, pen, false, x0-2, y0-2, 4, 4, 0, 360*64 ); \ else \ dc->DrawCircle(x0, y0, 2); #elif defined(__WXMSW__) && wxPLOT_FAST_GRAPHICS #define INITIALIZE_FAST_GRAPHICS \ double dc_scale_x = 1, dc_scale_y = 1; \ dc->GetUserScale( &dc_scale_x, &dc_scale_y ); \ wxPoint dc_origin = dc->GetDeviceOrigin(); \ HDC window = 0; \ if ((dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0,0))) \ window = (HDC)dc->GetHDC(); \ int pen = 0; pen = 0; // no unused var warning //inline void wxPLOT_DRAW_LINE(wxDC *dc, HDC win, int pen, int x0, int y0, int x1, int y1) #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ if (win) \ { \ (void)MoveToEx(win, x0, y0, NULL); \ (void)LineTo(win, x1, y1); \ } \ else \ dc->DrawLine( x0, y0, x1, y1 ); //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, HDC win, int pen, int x0, int y0) #define wxPLOT_DRAW_CIRCLE(dc, win, pen, x0, y0) \ if (win) \ (void)Ellipse(win, x0-2, y0-2, x0+4, y0+4); \ else \ dc->DrawCircle(x0, y0, 2); #else // !wxPLOT_FAST_GRAPHICS or not gtk/msw #define INITIALIZE_FAST_GRAPHICS \ int window = 0; window = 0; \ int pen = 0; pen = 0; //inline void wxPLOT_DRAW_LINE(wxDC *dc, int win, int pen, int x0, int y0, int x1, int y1) #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ dc->DrawLine( x0, y0, x1, y1 ); //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, int win, int pen, int x0, int y0) #define wxPLOT_DRAW_CIRCLE(dc, win, pen, x0, y0) \ dc->DrawCircle(x0, y0, 2); #endif // wxPLOT_FAST_GRAPHICS // differs from wxRect2DDouble::Intersects by allowing for 0 width or height inline bool wxPlotRect2DDoubleIntersects(const wxRect2DDouble &a, const wxRect2DDouble &b) { return (wxMax(a.m_x, b.m_x) <= wxMin(a.GetRight(), b.GetRight())) && (wxMax(a.m_y, b.m_y) <= wxMin(a.GetBottom(), b.GetBottom())); } // same as wxPlotRect2DDouble::Contains, but doesn't convert to wxPoint2DDouble inline bool wxPlotRect2DDoubleContains(double x, double y, const wxRect2DDouble &rect) { return ((x>=rect.m_x) && (y>=rect.m_y) && (x<=rect.GetRight()) && (y<=rect.GetBottom())); } // differs from wxRect2DDouble::GetOutCode by swaping top and bottom for plot origin //inline wxOutCode wxPlotRect2DDoubleOutCode( double x, double y, const wxRect2DDouble &rect ) //{ // return wxOutCode((x < rect.m_x ? wxOutLeft : // (x > rect.GetRight() ? wxOutRight : wxInside )) + // (y < rect.m_y ? wxOutTop : // (y > rect.GetBottom() ? wxOutBottom : wxInside )) ); //} #define wxPlotRect2DDoubleOutCode( x, y, rect ) \ wxOutCode((x < rect.m_x ? wxOutLeft : \ (x > rect.GetRight() ? wxOutRight : wxInside )) + \ (y < rect.m_y ? wxOutTop : \ (y > rect.GetBottom() ? wxOutBottom : wxInside )) ) // modified Cohen-Sutherland Algorithm for line clipping in at most two passes // the the original endless loop is too unstable // http://www.cc.gatech.edu/grads/h/Hao-wei.Hsieh/Haowei.Hsieh/code1.html for psuedo code // The line connecting (x0,y0)-(x1,y1) is clipped to rect and which // points were clipped is returned. enum ClipLine_Type { ClippedNeither = 0x0000, ClippedFirstX = 0x0001, ClippedFirstY = 0x0002, ClippedFirst = ClippedFirstX | ClippedFirstY, ClippedSecondX = 0x0010, ClippedSecondY = 0x0020, ClippedSecond = ClippedSecondX | ClippedSecondY, ClippedBoth = ClippedFirst | ClippedSecond, ClippedOut = 0x0100 // no intersection, so can't clip }; // in plotdraw.cpp extern int ClipLineToRect( double &x0, double &y0, double &x1, double &y1, const wxRect2DDouble &rect ); //*************************************************************************** #include "wx/plotctrl/plotdraw.h" //---------------------------------------------------------------------------- // Event types //---------------------------------------------------------------------------- // wxPlotEvent DEFINE_EVENT_TYPE(wxEVT_PLOT_ADD_CURVE) DEFINE_EVENT_TYPE(wxEVT_PLOT_DELETING_CURVE) DEFINE_EVENT_TYPE(wxEVT_PLOT_DELETED_CURVE) DEFINE_EVENT_TYPE(wxEVT_PLOT_CURVE_SEL_CHANGING) DEFINE_EVENT_TYPE(wxEVT_PLOT_CURVE_SEL_CHANGED) DEFINE_EVENT_TYPE(wxEVT_PLOT_MOUSE_MOTION) DEFINE_EVENT_TYPE(wxEVT_PLOT_CLICKED) DEFINE_EVENT_TYPE(wxEVT_PLOT_DOUBLECLICKED) DEFINE_EVENT_TYPE(wxEVT_PLOT_POINT_CLICKED) DEFINE_EVENT_TYPE(wxEVT_PLOT_POINT_DOUBLECLICKED) DEFINE_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CREATING) DEFINE_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CHANGING) DEFINE_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CREATED) DEFINE_EVENT_TYPE(wxEVT_PLOT_VIEW_CHANGING) DEFINE_EVENT_TYPE(wxEVT_PLOT_VIEW_CHANGED) DEFINE_EVENT_TYPE(wxEVT_PLOT_CURSOR_CHANGING) DEFINE_EVENT_TYPE(wxEVT_PLOT_CURSOR_CHANGED) DEFINE_EVENT_TYPE(wxEVT_PLOT_ERROR) DEFINE_EVENT_TYPE(wxEVT_PLOT_BEGIN_TITLE_EDIT) DEFINE_EVENT_TYPE(wxEVT_PLOT_END_TITLE_EDIT) DEFINE_EVENT_TYPE(wxEVT_PLOT_BEGIN_X_LABEL_EDIT) DEFINE_EVENT_TYPE(wxEVT_PLOT_END_X_LABEL_EDIT) DEFINE_EVENT_TYPE(wxEVT_PLOT_BEGIN_Y_LABEL_EDIT) DEFINE_EVENT_TYPE(wxEVT_PLOT_END_Y_LABEL_EDIT) DEFINE_EVENT_TYPE(wxEVT_PLOT_MOUSE_FUNC_CHANGING) DEFINE_EVENT_TYPE(wxEVT_PLOT_MOUSE_FUNC_CHANGED) // wxPlotSelectionEvent //DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATING) //DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATED) //DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGING) DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGED) /* DEFINE_EVENT_TYPE(wxEVT_PLOT_VALUE_SEL_CREATING) DEFINE_EVENT_TYPE(wxEVT_PLOT_VALUE_SEL_CREATED) DEFINE_EVENT_TYPE(wxEVT_PLOT_VALUE_SEL_CHANGING) DEFINE_EVENT_TYPE(wxEVT_PLOT_VALUE_SEL_CHANGED) DEFINE_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CHANGED) DEFINE_EVENT_TYPE(wxEVT_PLOT_AREA_CREATE) */ // The code below translates the event.GetEventType to a string name for debugging #define aDEFINE_LOCAL_EVENT_TYPE(t) if (event.GetEventType() == t) return wxT(#t); wxString GetEventName(const wxPlotEvent& event) { aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_ADD_CURVE) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_DELETING_CURVE) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_DELETED_CURVE) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURVE_SEL_CHANGING) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURVE_SEL_CHANGED) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_MOUSE_MOTION) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CLICKED) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_DOUBLECLICKED) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_POINT_CLICKED) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_POINT_DOUBLECLICKED) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CREATING) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CHANGING) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CREATED) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_VIEW_CHANGING) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_VIEW_CHANGED) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURSOR_CHANGING) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURSOR_CHANGED) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_ERROR) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_BEGIN_TITLE_EDIT) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_END_TITLE_EDIT) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_BEGIN_X_LABEL_EDIT) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_END_X_LABEL_EDIT) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_BEGIN_Y_LABEL_EDIT) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_END_Y_LABEL_EDIT) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_MOUSE_FUNC_CHANGING) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_MOUSE_FUNC_CHANGED) // wxPlotSelectionEvent //DEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATING) //DEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATED) //DEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGING) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGED) return wxT("Unknown Event Type"); } //----------------------------------------------------------------------------- // wxPlotEvent //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotEvent, wxNotifyEvent) wxPlotEvent::wxPlotEvent(wxEventType commandType, int id, wxPlotCtrl *window) :wxNotifyEvent(commandType, id), m_curve(NULL), m_curveIndex(-1), m_curveData_index(-1), m_x(0), m_y(0) { SetEventObject( (wxObject*)window ); } IMPLEMENT_ABSTRACT_CLASS(wxPlotSelectionEvent, wxPlotEvent) wxPlotSelectionEvent::wxPlotSelectionEvent(wxEventType commandType, int id, wxPlotCtrl *window) :wxPlotEvent(commandType, id, window), m_selecting(false) { } //----------------------------------------------------------------------------- // wxPlotArea //----------------------------------------------------------------------------- IMPLEMENT_CLASS(wxPlotArea, wxWindow) BEGIN_EVENT_TABLE(wxPlotArea, wxWindow) EVT_ERASE_BACKGROUND( wxPlotArea::OnEraseBackground ) EVT_PAINT ( wxPlotArea::OnPaint ) EVT_MOUSE_EVENTS ( wxPlotArea::OnMouse ) EVT_CHAR ( wxPlotArea::OnChar ) EVT_KEY_DOWN ( wxPlotArea::OnKeyDown ) EVT_KEY_UP ( wxPlotArea::OnKeyUp ) END_EVENT_TABLE() bool wxPlotArea::Create( wxWindow *parent, wxWindowID win_id ) { if (!wxWindow::Create(parent, win_id, wxDefaultPosition, wxSize(100,100), wxNO_BORDER|wxWANTS_CHARS|wxCLIP_CHILDREN, wxT("wxPlotArea"))) return false; m_owner = wxDynamicCast(parent, wxPlotCtrl); return true; } void wxPlotArea::Init() { m_owner = NULL; } void wxPlotArea::OnChar( wxKeyEvent &event ) { if (m_owner) m_owner->ProcessAreaEVT_CHAR(event); } void wxPlotArea::OnKeyDown( wxKeyEvent &event ) { if (m_owner) m_owner->ProcessAreaEVT_KEY_DOWN(event); } void wxPlotArea::OnKeyUp( wxKeyEvent &event ) { if (m_owner) m_owner->ProcessAreaEVT_KEY_UP(event); } void wxPlotArea::OnMouse( wxMouseEvent &event ) { if (m_owner) m_owner->ProcessAreaEVT_MOUSE_EVENTS(event); } void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) { wxPaintDC dc( this ); if (!m_owner || (m_owner->GetRedrawType() & wxPLOT_REDRAW_BLOCKER)) return; int redraw_type = m_owner->GetRedrawType(); /* wxRegionIterator upd( GetUpdateRegion() ); while (upd) { //printf("Region %d %d %d %d \n", upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); fflush(stdout); Paint( &dc, upd.GetRect() ); upd++; } */ if (redraw_type & wxPLOT_REDRAW_PLOT) { CreateBitmap( m_owner->GetPlotAreaRect() ); m_owner->SetRedrawType(redraw_type & ~wxPLOT_REDRAW_PLOT); } if (m_bitmap.Ok()) dc.DrawBitmap(m_bitmap, 0, 0, false); #if wxCHECK_VERSION(2,7,0) if (m_owner->GetCrossHairCursor() && m_owner->GetPlotAreaRect().Contains(m_mousePt)) #else if (m_owner->GetCrossHairCursor() && m_owner->GetPlotAreaRect().Inside(m_mousePt)) #endif m_owner->DrawCrosshairCursor( &dc, m_mousePt ); m_owner->DrawMouseMarker(&dc, m_owner->GetAreaMouseMarker(), m_mouseRect); } void wxPlotArea::CreateBitmap( const wxRect &rect ) { if (!m_owner) return; wxRect refreshRect(rect); wxRect clientRect(m_owner->GetPlotAreaRect()); refreshRect.Intersect(clientRect); if ((refreshRect.width == 0) || (refreshRect.height == 0)) return; // if the bitmap need to be recreated then refresh everything if (!m_bitmap.Ok() || (clientRect.width != m_bitmap.GetWidth()) || (clientRect.height != m_bitmap.GetHeight()) ) { m_bitmap.Create(clientRect.width, clientRect.height); refreshRect = clientRect; } wxMemoryDC mdc; mdc.SelectObject( m_bitmap ); m_owner->DrawAreaWindow( &mdc, refreshRect ); mdc.SelectObject( wxNullBitmap ); } //----------------------------------------------------------------------------- // wxPlotAxis //----------------------------------------------------------------------------- IMPLEMENT_CLASS(wxPlotAxis, wxWindow) BEGIN_EVENT_TABLE(wxPlotAxis, wxWindow) EVT_ERASE_BACKGROUND( wxPlotAxis::OnEraseBackground ) EVT_PAINT ( wxPlotAxis::OnPaint ) EVT_MOUSE_EVENTS ( wxPlotAxis::OnMouse ) EVT_CHAR ( wxPlotAxis::OnChar ) END_EVENT_TABLE() bool wxPlotAxis::Create( wxWindow *parent, wxWindowID win_id, wxPlotAxis_Type style ) { if (!wxWindow::Create(parent, win_id, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxWANTS_CHARS|wxCLIP_CHILDREN, wxT("wxPlotAxis"))) return false; m_style = style; m_owner = wxDynamicCast(parent, wxPlotCtrl); if (style == wxPLOT_Y_AXIS) SetCursor( wxCursor(wxCURSOR_SIZENS) ); else SetCursor( wxCursor(wxCURSOR_SIZEWE) ); return true; } void wxPlotAxis::Init() { m_style = wxPLOT_X_AXIS; m_owner = NULL; } void wxPlotAxis::OnChar( wxKeyEvent &event ) { if (m_owner) m_owner->ProcessAxisEVT_CHAR(event); } void wxPlotAxis::OnMouse( wxMouseEvent &event ) { if (m_owner) m_owner->ProcessAxisEVT_MOUSE_EVENTS(event); } void wxPlotAxis::OnPaint( wxPaintEvent &WXUNUSED(event) ) { wxPaintDC dc( this ); int redraw_type = m_owner->GetRedrawType(); if (!m_owner || (redraw_type & wxPLOT_REDRAW_BLOCKER)) return; if (IsXAxis() && ((redraw_type & wxPLOT_REDRAW_XAXIS) != 0)) { m_owner->SetRedrawType(redraw_type & ~wxPLOT_REDRAW_XAXIS); CreateBitmap(); } else if (!IsXAxis() && ((redraw_type & wxPLOT_REDRAW_YAXIS) != 0)) { m_owner->SetRedrawType(redraw_type & ~wxPLOT_REDRAW_YAXIS); CreateBitmap(); } if (m_bitmap.Ok()) dc.DrawBitmap(m_bitmap, 0, 0, false); } void wxPlotAxis::CreateBitmap() { if (!m_owner) return; m_owner->UpdateWindowSize(); wxSize clientSize = GetClientSize(); if ((clientSize.x < 2) || (clientSize.y < 2)) return; if (!m_bitmap.Ok() || (clientSize.x != m_bitmap.GetWidth()) || (clientSize.y != m_bitmap.GetHeight()) ) { m_bitmap.Create(clientSize.x, clientSize.y); } wxMemoryDC mdc; mdc.SelectObject( m_bitmap ); if (IsXAxis()) m_owner->DrawXAxis( &mdc, true ); else m_owner->DrawYAxis( &mdc, true ); mdc.SelectObject( wxNullBitmap ); } //----------------------------------------------------------------------------- // wxPlotCtrl //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotCtrl, wxWindow ) BEGIN_EVENT_TABLE(wxPlotCtrl, wxWindow ) //EVT_ERASE_BACKGROUND ( wxPlotCtrl::OnEraseBackground ) // clear for MSW EVT_SIZE ( wxPlotCtrl::OnSize ) EVT_PAINT ( wxPlotCtrl::OnPaint ) EVT_CHAR ( wxPlotCtrl::OnChar ) EVT_SCROLL ( wxPlotCtrl::OnScroll ) EVT_IDLE ( wxPlotCtrl::OnIdle ) EVT_MOUSE_EVENTS ( wxPlotCtrl::OnMouse ) EVT_TIMER ( wxID_ANY, wxPlotCtrl::OnTimer ) EVT_TEXT_ENTER ( wxID_ANY, wxPlotCtrl::OnTextEnter) END_EVENT_TABLE() void wxPlotCtrl::Init() { m_activeCurve = NULL; m_active_index = -1; m_cursorMarker.CreateEllipseMarker(wxPoint2DDouble(0,0), wxSize(2, 2), wxGenericPen(wxGenericColour(0, 255, 0))); m_cursor_curve = -1; m_cursor_index = -1; m_selection_type = wxPLOT_SELECT_MULTIPLE; m_show_key = true; m_show_title = m_show_xlabel = m_show_ylabel = false; m_title = wxT("Title"); m_xLabel = wxT("X-Axis"); m_yLabel = wxT("Y-Axis"); m_titleFont = *wxSWISS_FONT; m_titleColour = *wxBLACK; m_borderColour = *wxBLACK; m_scroll_on_thumb_release = false; m_crosshair_cursor = false; m_draw_symbols = true; m_draw_lines = true; m_draw_spline = false; m_draw_grid = true; m_fit_on_new_curve = true; m_show_xAxis = true; m_show_yAxis = true; m_zoom = wxPoint2DDouble( 1.0, 1.0 ); m_history_views_index = -1; m_fix_aspectratio = false; m_aspectratio = 1.0; m_viewRect = m_defaultPlotRect; m_curveBoundingRect = m_defaultPlotRect; m_defaultPlotRect = wxRect2DDouble( -10.0, -10.0, 20.0, 20.0 ); m_areaClientRect = wxRect(0, 0, 10, 10); m_xAxisTickFormat = m_yAxisTickFormat = wxT("%lf"); m_xAxisTick_step = m_yAxisTick_step = 1.0; m_xAxisTick_count = m_yAxisTick_count = 4; m_correct_ticks = true; m_areaDrawer = NULL; m_xAxisDrawer = NULL; m_yAxisDrawer = NULL; m_keyDrawer = NULL; m_curveDrawer = NULL; m_dataCurveDrawer = NULL; m_markerDrawer = NULL; m_xAxis = NULL; m_yAxis = NULL; m_area = NULL; m_xAxisScrollbar = NULL; m_yAxisScrollbar = NULL; m_textCtrl = NULL; m_activeBitmap = new wxBitmap(ledgreen_xpm); m_inactiveBitmap = new wxBitmap(ledgrey_xpm); m_focused = false; m_greedy_focus = false; m_redraw_type = wxPLOT_REDRAW_BLOCKER; m_batch_count = 0; m_axisFontSize.x = 6; m_axisFontSize.y = 12; m_y_axis_text_width = 60; m_area_border_width = 1; m_border = 4; m_min_exponential = 1000; m_pen_print_width = 0.4; m_timer = NULL; m_winCapture = NULL; m_area_mouse_marker = wxPLOT_MARKER_RECT; m_area_mouse_func = wxPLOT_MOUSE_ZOOM; m_area_mouse_cursorid = wxCURSOR_CROSS; m_mouse_cursorid = wxCURSOR_ARROW; } bool wxPlotCtrl::Create( wxWindow *parent, wxWindowID win_id, const wxPoint &pos, const wxSize &size, wxPlotAxis_Type WXUNUSED(flag), const wxString &name ) { m_redraw_type = wxPLOT_REDRAW_BLOCKER; // no paints until finished if (!wxWindow::Create(parent, win_id, pos, size, wxWANTS_CHARS|wxCLIP_CHILDREN, name)) return false; //SetSizeHints( 100, 100 ); // Don't allow window to get smaller than this! if (!s_handCursor.Ok()) { wxImage image(wxBitmap(hand_xpm).ConvertToImage()); image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, image.GetWidth()/2); image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, image.GetHeight()/2); s_handCursor = wxCursor(image); } if (!s_grabCursor.Ok()) { wxImage image(wxBitmap(grab_xpm).ConvertToImage()); image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, image.GetWidth()/2); image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, image.GetHeight()/2); s_grabCursor = wxCursor(image); } m_areaDrawer = new wxPlotDrawerArea(this); m_xAxisDrawer = new wxPlotDrawerXAxis(this); m_yAxisDrawer = new wxPlotDrawerYAxis(this); m_keyDrawer = new wxPlotDrawerKey(this); m_curveDrawer = new wxPlotDrawerCurve(this); m_dataCurveDrawer = new wxPlotDrawerDataCurve(this); m_markerDrawer = new wxPlotDrawerMarker(this); m_xAxis = new wxPlotAxis( this, ID_PLOTCTRL_X_AXIS, wxPLOT_X_AXIS ); m_yAxis = new wxPlotAxis( this, ID_PLOTCTRL_Y_AXIS, wxPLOT_Y_AXIS ); m_area = new wxPlotArea( this, ID_PLOTCTRL_AREA ); m_xAxisScrollbar = new wxScrollBar(this, ID_PLOTCTRL_X_SCROLLBAR, wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL); m_yAxisScrollbar = new wxScrollBar(this, ID_PLOTCTRL_Y_SCROLLBAR, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL); wxFont axisFont(m_xAxis->GetFont()); GetTextExtent(wxT("5"), &m_axisFontSize.x, &m_axisFontSize.y, NULL, NULL, &axisFont); if ((m_axisFontSize.x < 2) || (m_axisFontSize.y < 2)) // don't want to divide by 0 { m_axisFontSize.x = 6; m_axisFontSize.y = 12; wxFAIL_MSG(wxT("Can't determine the font size for the axis! I'll guess.\n" "Thef display might be corrupted, however you may continue.")); } m_xAxisDrawer->SetTickFont(axisFont); m_yAxisDrawer->SetTickFont(axisFont); // m_xAxisDrawer->SetLabelFont(*wxSWISS_FONT); // needs to be rotated // m_yAxisDrawer->SetLabelFont(*wxSWISS_FONT); // swiss works m_area->SetCursor( wxCURSOR_CROSS ); m_area->SetBackgroundColour(*wxWHITE); m_xAxis->SetBackgroundColour(*wxWHITE); m_yAxis->SetBackgroundColour(*wxWHITE); wxWindow::SetBackgroundColour(*wxWHITE); m_area->SetForegroundColour(*wxLIGHT_GREY); m_redraw_type = 0; // redraw when all done Redraw(wxPLOT_REDRAW_WHOLEPLOT); return true; } wxPlotCtrl::~wxPlotCtrl() { delete m_activeBitmap; delete m_inactiveBitmap; delete m_areaDrawer; delete m_xAxisDrawer; delete m_yAxisDrawer; delete m_keyDrawer; delete m_curveDrawer; delete m_dataCurveDrawer; delete m_markerDrawer; } void wxPlotCtrl::OnPaint( wxPaintEvent &WXUNUSED(event) ) { wxPaintDC dc(this); DrawActiveBitmap(&dc); DrawPlotCtrl(&dc); } void wxPlotCtrl::DrawActiveBitmap( wxDC* dc ) { if (m_xAxisScrollbar && m_yAxisScrollbar) { wxSize size = GetClientSize(); int left = m_xAxisScrollbar->GetRect().GetRight(); int top = m_yAxisScrollbar->GetRect().GetBottom(); wxRect rect(left, top, size.x - left, size.y - top); // clear background dc->SetBrush(wxBrush(GetBackgroundColour(), wxSOLID)); dc->SetPen(*wxTRANSPARENT_PEN); dc->DrawRectangle(rect); // center the bitmap wxPoint pt(rect.x + (rect.width - 15)/2, rect.y + (rect.width - 15)/2); dc->DrawBitmap(m_focused ? *m_activeBitmap : *m_inactiveBitmap, pt.x, pt.y, true); } } void wxPlotCtrl::DrawPlotCtrl( wxDC *dc ) { wxCHECK_RET(dc, wxT("invalid window")); if (m_show_title && !m_title.IsEmpty()) { dc->SetFont(GetPlotTitleFont()); dc->SetTextForeground(GetPlotTitleColour()); dc->DrawText(m_title, m_titleRect.x, m_titleRect.y); } bool draw_xlabel = (m_show_xlabel && !m_xLabel.IsEmpty()); bool draw_ylabel = (m_show_ylabel && !m_yLabel.IsEmpty()); if (draw_xlabel || draw_ylabel) { dc->SetFont(GetAxisLabelFont()); dc->SetTextForeground(GetAxisLabelColour()); if (draw_xlabel) dc->DrawText(m_xLabel, m_xLabelRect.x, m_xLabelRect.y); if (draw_ylabel) dc->DrawRotatedText(m_yLabel, m_yLabelRect.x, m_yLabelRect.y + m_yLabelRect.height, 90); } #ifdef DRAW_BORDERS // Test code for sizing to show the extent of the axes dc->SetBrush( *wxTRANSPARENT_BRUSH ); dc->SetPen( wxPen(GetBorderColour(), 1, wxSOLID) ); dc->DrawRectangle(m_titleRect); dc->DrawRectangle(m_xLabelRect); dc->DrawRectangle(m_yLabelRect); #endif // DRAW_BORDERS } void wxPlotCtrl::SetPlotWinMouseCursor(int cursorid) { if (cursorid == m_mouse_cursorid) return; m_mouse_cursorid = cursorid; SetCursor(wxCursor(cursorid)); } void wxPlotCtrl::OnMouse( wxMouseEvent &event ) { if (event.ButtonDown() && IsTextCtrlShown()) { HideTextCtrl(true, true); return; } wxSize size(GetClientSize()); wxPoint mousePt(event.GetPosition()); #if wxCHECK_VERSION(2,7,0) if ((m_show_title && m_titleRect.Contains(mousePt)) || (m_show_xlabel && m_xLabelRect.Contains(mousePt)) || (m_show_ylabel && m_yLabelRect.Contains(mousePt))) #else if ((m_show_title && m_titleRect.Inside(mousePt)) || (m_show_xlabel && m_xLabelRect.Inside(mousePt)) || (m_show_ylabel && m_yLabelRect.Inside(mousePt))) #endif { SetPlotWinMouseCursor(wxCURSOR_IBEAM); } else SetPlotWinMouseCursor(wxCURSOR_ARROW); if (event.ButtonDClick(1) && !IsTextCtrlShown()) { #if wxCHECK_VERSION(2,7,0) if (m_show_title && m_titleRect.Contains(mousePt)) ShowTextCtrl(wxPLOT_EDIT_TITLE, true); else if (m_show_xlabel && m_xLabelRect.Contains(mousePt)) ShowTextCtrl(wxPLOT_EDIT_XAXIS, true); else if (m_show_ylabel && m_yLabelRect.Contains(mousePt)) ShowTextCtrl(wxPLOT_EDIT_YAXIS, true); #else if (m_show_title && m_titleRect.Inside(mousePt)) ShowTextCtrl(wxPLOT_EDIT_TITLE, true); else if (m_show_xlabel && m_xLabelRect.Inside(mousePt)) ShowTextCtrl(wxPLOT_EDIT_XAXIS, true); else if (m_show_ylabel && m_yLabelRect.Inside(mousePt)) ShowTextCtrl(wxPLOT_EDIT_YAXIS, true); #endif } } void wxPlotCtrl::ShowTextCtrl(wxPlotCtrlTextCtrl_Type type, bool send_event) { switch (type) { case wxPLOT_EDIT_TITLE : { if (m_textCtrl) { if (m_textCtrl->GetId() != wxEVT_PLOT_END_TITLE_EDIT) HideTextCtrl(true, true); else return; // already shown } if (send_event) { wxPlotEvent pevent(wxEVT_PLOT_BEGIN_TITLE_EDIT, GetId(), this); pevent.SetString(m_title); if (!DoSendEvent(pevent)) return; } m_textCtrl = new wxTextCtrl(this, wxEVT_PLOT_END_TITLE_EDIT, GetPlotTitle(), wxPoint(m_areaRect.x, 0), wxSize(m_areaRect.width, m_titleRect.height+2*m_border), wxTE_PROCESS_ENTER); m_textCtrl->SetFont(GetPlotTitleFont()); m_textCtrl->SetForegroundColour(GetPlotTitleColour()); m_textCtrl->SetBackgroundColour(GetBackgroundColour()); break; } case wxPLOT_EDIT_XAXIS : { if (m_textCtrl) { if (m_textCtrl->GetId() != wxEVT_PLOT_END_X_LABEL_EDIT) HideTextCtrl(true, true); else return; // already shown } if (send_event) { wxPlotEvent pevent(wxEVT_PLOT_BEGIN_X_LABEL_EDIT, GetId(), this); pevent.SetString(m_xLabel); if (!DoSendEvent(pevent)) return; } m_textCtrl = new wxTextCtrl(this, wxEVT_PLOT_END_X_LABEL_EDIT, GetXAxisLabel(), wxPoint(m_areaRect.x, m_xAxisRect.GetBottom()), wxSize(m_areaRect.width, m_xLabelRect.height+2*m_border), wxTE_PROCESS_ENTER); m_textCtrl->SetFont(GetAxisLabelFont()); m_textCtrl->SetForegroundColour(GetAxisLabelColour()); m_textCtrl->SetBackgroundColour(GetBackgroundColour()); break; } case wxPLOT_EDIT_YAXIS : { if (m_textCtrl) { if (m_textCtrl->GetId() != wxEVT_PLOT_END_Y_LABEL_EDIT) HideTextCtrl(true, true); else return; // already shown } if (send_event) { wxPlotEvent pevent(wxEVT_PLOT_BEGIN_Y_LABEL_EDIT, GetId(), this); pevent.SetString(m_yLabel); if (!DoSendEvent(pevent)) return; } m_textCtrl = new wxTextCtrl(this, wxEVT_PLOT_END_Y_LABEL_EDIT, GetYAxisLabel(), wxPoint(0, m_areaRect.y+m_areaRect.height/2), wxSize(m_clientRect.width - m_axisFontSize.y/2, m_yLabelRect.width+2*m_border), wxTE_PROCESS_ENTER); m_textCtrl->SetFont(GetAxisLabelFont()); m_textCtrl->SetForegroundColour(GetAxisLabelColour()); m_textCtrl->SetBackgroundColour(GetBackgroundColour()); break; } } } void wxPlotCtrl::HideTextCtrl(bool save_value, bool send_event) { wxCHECK_RET(m_textCtrl, wxT("HideTextCtrl, but textctrl is not shown")); long event_type = m_textCtrl->GetId(); wxString value = m_textCtrl->GetValue(); m_textCtrl->Destroy(); m_textCtrl = NULL; if (!save_value) return; bool changed = false; if (event_type == wxEVT_PLOT_END_TITLE_EDIT) changed = (value != GetPlotTitle()); else if (event_type == wxEVT_PLOT_END_X_LABEL_EDIT) changed = (value != GetXAxisLabel()); else if (event_type == wxEVT_PLOT_END_Y_LABEL_EDIT) changed = (value != GetYAxisLabel()); if (!changed) return; if (send_event) { wxPlotEvent event(event_type, GetId(), this); event.SetString(value); if (!DoSendEvent(event)) return; } if (event_type == wxEVT_PLOT_END_TITLE_EDIT) SetPlotTitle(value); else if (event_type == wxEVT_PLOT_END_X_LABEL_EDIT) SetXAxisLabel(value); else if (event_type == wxEVT_PLOT_END_Y_LABEL_EDIT) SetYAxisLabel(value); } bool wxPlotCtrl::IsTextCtrlShown() const { return m_textCtrl && m_textCtrl->IsShown(); } void wxPlotCtrl::OnTextEnter( wxCommandEvent &event ) { if (event.GetId() == 1) HideTextCtrl(true, true); else { wxCommandEvent newevt(wxEVT_COMMAND_TEXT_ENTER, 1); GetEventHandler()->AddPendingEvent( newevt ); } } void wxPlotCtrl::OnIdle( wxIdleEvent &event ) { CheckFocus(); event.Skip(); } bool wxPlotCtrl::CheckFocus() { wxWindow *win = FindFocus(); if ((win==m_area)||(win==m_xAxis)||(win==m_yAxis)||(win==this)) { if (!m_focused) { m_focused = true; wxClientDC dc(this); wxSize size = GetClientSize(); dc.DrawBitmap(*m_activeBitmap, size.GetWidth()-15, size.GetHeight()-15,true); } } else if (m_focused) { m_focused = false; wxClientDC dc(this); wxSize size = GetClientSize(); dc.DrawBitmap(*m_inactiveBitmap, size.GetWidth()-15, size.GetHeight()-15,true); } return m_focused; } void wxPlotCtrl::EndBatch(bool force_refresh) { if ( m_batch_count > 0 ) { m_batch_count--; if ( (m_batch_count <= 0) && force_refresh ) { Redraw(wxPLOT_REDRAW_WHOLEPLOT); AdjustScrollBars(); } } } bool wxPlotCtrl::SetBackgroundColour( const wxColour &colour ) { wxCHECK_MSG(colour.Ok(), false, wxT("invalid colour")); m_area->SetBackgroundColour(colour); m_xAxis->SetBackgroundColour(colour); m_yAxis->SetBackgroundColour(colour); wxWindow::SetBackgroundColour(colour); Redraw(wxPLOT_REDRAW_EVERYTHING); return true; } void wxPlotCtrl::SetGridColour( const wxColour &colour ) { wxCHECK_RET(colour.Ok(), wxT("invalid colour")); m_area->SetForegroundColour(colour); Redraw(wxPLOT_REDRAW_PLOT); } void wxPlotCtrl::SetBorderColour( const wxColour &colour ) { wxCHECK_RET(colour.Ok(), wxT("invalid colour")); m_borderColour = colour; Redraw(wxPLOT_REDRAW_PLOT); } void wxPlotCtrl::SetCursorColour( const wxColour &colour ) { wxCHECK_RET(colour.Ok(), wxT("invalid colour")); m_cursorMarker.GetPen().SetColour(colour); wxClientDC dc(m_area); DrawCurveCursor( &dc ); } wxColour wxPlotCtrl::GetCursorColour() const { return m_cursorMarker.GetPen().GetColour(); } int wxPlotCtrl::GetCursorSize() const { return m_cursorMarker.GetSize().x; } void wxPlotCtrl::SetCursorSize(int size) { m_cursorMarker.SetSize(wxSize(size, size)); } wxFont wxPlotCtrl::GetAxisFont() const { return m_xAxisDrawer->m_tickFont; // FIXME } wxColour wxPlotCtrl::GetAxisColour() const { return m_xAxisDrawer->m_tickColour.GetColour(); // FIXME } void wxPlotCtrl::SetAxisFont( const wxFont &font ) { wxCHECK_RET(font.Ok(), wxT("invalid font")); if (m_xAxisDrawer) m_xAxisDrawer->SetTickFont(font); if (m_yAxisDrawer) m_yAxisDrawer->SetTickFont(font); int x=6, y=12, decent=0, leading=0; GetTextExtent(wxT("5"), &x, &y, &decent, &leading, &font); m_axisFontSize.x = x+leading; m_axisFontSize.y = y+decent; GetTextExtent(wxT("-5.5e+555"), &x, &y, &decent, &leading, &font); m_y_axis_text_width = x + leading; //m_axisFontSize.x = m_xAxis->GetCharWidth(); //m_axisFontSize.y = m_xAxis->GetCharHeight(); if ((m_axisFontSize.x < 2) || (m_axisFontSize.y < 2)) // don't want to divide by 0 { static bool first_try = false; m_axisFontSize.x = 6; m_axisFontSize.y = 12; wxMessageBox(wxT("Can't determine the font size for the axis.\n") wxT("Reverting to a default font."), wxT("Font error")); if (!first_try) { first_try = true; SetAxisFont(*wxNORMAL_FONT); } else first_try = false; } DoSize(); Redraw(wxPLOT_REDRAW_XAXIS|wxPLOT_REDRAW_YAXIS); } void wxPlotCtrl::SetAxisColour( const wxColour &colour ) { wxCHECK_RET(colour.Ok(), wxT("invalid colour")); if (m_xAxisDrawer) m_xAxisDrawer->SetTickColour(colour); if (m_yAxisDrawer) m_yAxisDrawer->SetTickColour(colour); Redraw(wxPLOT_REDRAW_XAXIS|wxPLOT_REDRAW_YAXIS); } wxFont wxPlotCtrl::GetAxisLabelFont() const { return m_xAxisDrawer->m_labelFont; // FIXME } wxColour wxPlotCtrl::GetAxisLabelColour() const { return m_xAxisDrawer->m_labelColour.GetColour(); // FIXME } void wxPlotCtrl::SetAxisLabelFont( const wxFont &font ) { wxCHECK_RET(font.Ok(), wxT("invalid font")); if (m_xAxisDrawer) m_xAxisDrawer->SetLabelFont(font); if (m_yAxisDrawer) m_yAxisDrawer->SetLabelFont(font); SetXAxisLabel(GetXAxisLabel()); // FIXME - lazy hack SetYAxisLabel(GetYAxisLabel()); } void wxPlotCtrl::SetAxisLabelColour( const wxColour &colour ) { wxCHECK_RET(colour.Ok(), wxT("invalid colour")); if (m_xAxisDrawer) m_xAxisDrawer->SetLabelColour(colour); if (m_yAxisDrawer) m_yAxisDrawer->SetLabelColour(colour); SetXAxisLabel(GetXAxisLabel()); // FIXME - lazy hack SetYAxisLabel(GetYAxisLabel()); } void wxPlotCtrl::SetPlotTitleFont(const wxFont &font) { wxCHECK_RET(font.Ok(), wxT("invalid font")); m_titleFont = font; SetPlotTitle(GetPlotTitle()); } void wxPlotCtrl::SetPlotTitleColour(const wxColour &colour) { wxCHECK_RET(colour.Ok(), wxT("invalid colour")); m_titleColour = colour; SetPlotTitle(GetPlotTitle()); } wxFont wxPlotCtrl::GetKeyFont() const { return m_keyDrawer->m_font; // FIXME } wxColour wxPlotCtrl::GetKeyColour() const { return m_keyDrawer->m_fontColour.GetColour(); // FIXME } void wxPlotCtrl::SetKeyFont( const wxFont &font ) { wxCHECK_RET(font.Ok(), wxT("invalid font")); m_keyDrawer->SetFont(font); Redraw(wxPLOT_REDRAW_PLOT); } void wxPlotCtrl::SetKeyColour( const wxColour & colour ) { wxCHECK_RET(colour.Ok(), wxT("invalid colour")); m_keyDrawer->SetFontColour(colour); Redraw(wxPLOT_REDRAW_PLOT); } // ------------------------------------------------------------------------ // Title, axis labels, and key // ------------------------------------------------------------------------ void wxPlotCtrl::SetXAxisLabel(const wxString &label) { if (label.IsEmpty()) m_xLabel = wxT("X - Axis"); else m_xLabel = label; wxFont font = GetAxisLabelFont(); GetTextExtent(m_xLabel, &m_xLabelRect.width, &m_xLabelRect.height, NULL, NULL, &font); m_xLabel = label; Refresh(); DoSize(); } void wxPlotCtrl::SetYAxisLabel(const wxString &label) { if (label.IsEmpty()) m_yLabel = wxT("Y - Axis"); else m_yLabel = label; wxFont font = GetAxisLabelFont(); GetTextExtent(m_yLabel, &m_yLabelRect.height, &m_yLabelRect.width, NULL, NULL, &font); m_yLabel = label; Refresh(); DoSize(); } void wxPlotCtrl::SetPlotTitle(const wxString &title) { if (title.IsEmpty()) m_title = wxT("Title"); else m_title = title; wxFont font = GetPlotTitleFont(); GetTextExtent(m_title, &m_titleRect.width, &m_titleRect.height, NULL, NULL, &font); m_title = title; Refresh(); DoSize(); } wxPoint wxPlotCtrl::GetKeyPosition() const { return m_keyDrawer->m_keyPosition; } bool wxPlotCtrl::GetKeyInside() const { return m_keyDrawer->m_key_inside; } void wxPlotCtrl::SetKeyPosition(const wxPoint &pos, bool stay_inside) { m_keyDrawer->m_keyPosition = pos; m_keyDrawer->m_key_inside = stay_inside; Redraw(wxPLOT_REDRAW_PLOT); } void wxPlotCtrl::CreateKeyString() { m_keyString.Clear(); int n, count = m_curves.GetCount(); for (n = 0; n < count; n++) { wxString key; if (GetDataCurve(n)) key = GetDataCurve(n)->GetFilename(); else if (GetFunctionCurve(n)) key = GetFunctionCurve(n)->GetFunctionString(); else key.Printf(wxT("Curve %d"), n); m_keyString += (key + wxT("\n")); } } // ------------------------------------------------------------------------ // Curve Accessors // ------------------------------------------------------------------------ bool wxPlotCtrl::AddCurve( wxPlotCurve *curve, bool select, bool send_event ) { if (!curve || !curve->Ok()) { if (curve) delete curve; wxCHECK_MSG( false, false, wxT("Invalid curve") ); } m_curves.Add( curve ); m_curveSelections.Add(new wxRangeDoubleSelection()); m_dataSelections.Add(new wxRangeIntSelection()); CalcBoundingPlotRect(); CreateKeyString(); if (send_event) { wxPlotEvent event(wxEVT_PLOT_ADD_CURVE, GetId(), this); event.SetCurve(curve, m_curves.GetCount()-1); (void)DoSendEvent( event ); } m_batch_count++; if (select) SetActiveCurve(curve, send_event); m_batch_count--; if (m_fit_on_new_curve) SetZoom( -1, -1, 0, 0, true ); else Redraw(wxPLOT_REDRAW_PLOT); return true; } bool wxPlotCtrl::AddCurve( const wxPlotCurve &curve, bool select, bool send_event ) { wxCHECK_MSG(curve.Ok(), false, wxT("invalid wxPlotCurve")); if (wxDynamicCast(&curve, wxPlotData)) return AddCurve(new wxPlotData(*wxDynamicCast(&curve, wxPlotData)), select, send_event); if (wxDynamicCast(&curve, wxPlotFunction)) return AddCurve(new wxPlotFunction(*wxDynamicCast(&curve, wxPlotFunction)), select, send_event); wxFAIL_MSG(wxT("Unable to ref curve type added to plot")); return false; } bool wxPlotCtrl::DeleteCurve( wxPlotCurve* curve, bool send_event ) { wxCHECK_MSG(curve, false, wxT("invalid plotcurve")); int index = m_curves.Index( *curve ); wxCHECK_MSG( index != wxNOT_FOUND, false, wxT("Unknown PlotCurve") ); return DeleteCurve(index, send_event); } bool wxPlotCtrl::DeleteCurve( int n, bool send_event ) { wxCHECK_MSG((n>=-1)&&(n n) m_cursor_curve--; ClearSelectedRanges(n, send_event); m_dataSelections.RemoveAt(n); m_curveSelections.RemoveAt(n); m_curves.RemoveAt(n); } if (m_active_index >= int(m_curves.GetCount())) { // force this invalid, can't override this, the curve is "gone" m_active_index = -1; m_activeCurve = NULL; SetActiveIndex( m_curves.GetCount() - 1, send_event ); } else if (m_active_index >= 0) { SetActiveIndex( m_active_index, send_event ); } EndBatch(false); // still don't redraw CalcBoundingPlotRect(); CreateKeyString(); Redraw(wxPLOT_REDRAW_PLOT); if (send_event) { wxPlotEvent event1( wxEVT_PLOT_DELETED_CURVE, GetId(), this ); event1.SetCurveIndex(n); (void)DoSendEvent( event1 ); } return true; } wxPlotCurve* wxPlotCtrl::GetCurve( int n ) const { wxCHECK_MSG((n >= 0) && (n < GetCurveCount()), NULL, wxT("Invalid index")); return &(m_curves.Item(n)); } void wxPlotCtrl::SetActiveCurve( wxPlotCurve* current, bool send_event ) { wxCHECK_RET(current, wxT("Invalid curve")); int index = m_curves.Index( *current ); wxCHECK_RET( index != wxNOT_FOUND, wxT("Unknown PlotCurve") ); SetActiveIndex( index, send_event ); } void wxPlotCtrl::SetActiveIndex( int curve_index, bool send_event ) { wxCHECK_RET((curve_index < GetCurveCount()), wxT("Invalid index")); if (send_event) { wxPlotEvent event( wxEVT_PLOT_CURVE_SEL_CHANGING, GetId(), this); event.SetCurve(m_activeCurve, m_active_index); if (!DoSendEvent(event)) return; } if ((curve_index >= 0) && m_curves.Item(curve_index).Ok()) { m_active_index = curve_index; m_activeCurve = &(m_curves.Item(curve_index)); } else { m_active_index = -1; m_activeCurve = NULL; } if (send_event) { wxPlotEvent event( wxEVT_PLOT_CURVE_SEL_CHANGED, GetId(), this); event.SetCurve(m_activeCurve, m_active_index); (void)DoSendEvent( event ); } Redraw(wxPLOT_REDRAW_PLOT); } wxArrayInt wxPlotCtrl::GetPlotDataIndexes() const { wxArrayInt array; size_t n, count = m_curves.GetCount(); for (n=0; n= 0) && (marker < (int)m_plotMarkers.GetCount()), wxT("Invalid marker number")); m_plotMarkers.RemoveAt(marker); } void wxPlotCtrl::ClearMarkers() { m_plotMarkers.Clear(); } wxPlotMarker wxPlotCtrl::GetMarker(int marker) const { wxCHECK_MSG((marker >= 0) && (marker < (int)m_plotMarkers.GetCount()), wxPlotMarker(), wxT("Invalid marker number")); return m_plotMarkers[marker]; } //------------------------------------------------------------------------- // Cursor position //------------------------------------------------------------------------- void wxPlotCtrl::InvalidateCursor(bool send_event) { bool changed = m_cursor_curve >= 0; m_cursor_curve = -1; m_cursor_index = -1; m_cursorMarker.SetPlotPosition(wxPoint2DDouble(0, 0)); if (send_event && changed) { wxPlotEvent plotEvent(wxEVT_PLOT_CURSOR_CHANGED, GetId(), this ); (void)DoSendEvent( plotEvent ); } } bool wxPlotCtrl::IsCursorValid() { if (m_cursor_curve < 0) return false; // sanity check if (m_cursor_curve >= int(m_curves.GetCount())) { wxFAIL_MSG(wxT("Invalid cursor index")); InvalidateCursor(true); return false; } wxPlotData *plotData = GetDataCurve(m_cursor_curve); if (plotData) { // sanity check if (m_cursor_index < 0) { wxFAIL_MSG(wxT("Invalid cursor data index")); InvalidateCursor(true); return false; } // if the curve shrinks or is bad if (!plotData->Ok() || (m_cursor_index >= (int)plotData->GetCount())) { InvalidateCursor(true); return false; } m_cursorMarker.SetPlotPosition(plotData->GetPoint(m_cursor_index)); } else { wxDouble x = m_cursorMarker.GetPlotRect().m_x; m_cursorMarker.GetPlotRect().m_y = GetCurve(m_cursor_curve)->GetY(x); } return true; } wxPoint2DDouble wxPlotCtrl::GetCursorPoint() { wxCHECK_MSG(IsCursorValid(), wxPoint2DDouble(0, 0), wxT("invalid cursor")); return m_cursorMarker.GetPlotPosition(); } bool wxPlotCtrl::SetCursorDataIndex(int curve_index, int cursor_index, bool send_event) { wxCHECK_MSG(CurveIndexOk(curve_index) && GetDataCurve(curve_index), false, wxT("invalid curve index")); wxPlotData *plotData = GetDataCurve(curve_index); wxCHECK_MSG((cursor_index>=0) && plotData->Ok() && (cursor_index < (int)plotData->GetCount()), false, wxT("invalid index")); // do nothing if already set if ((m_cursor_curve == curve_index) && (m_cursor_index == cursor_index)) return false; wxPoint2DDouble cursorPt(plotData->GetPoint(cursor_index)); if (send_event) { wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGING, GetId(), this ); cursor_event.SetPosition( cursorPt.m_x, cursorPt.m_y ); cursor_event.SetCurve( plotData, curve_index ); cursor_event.SetCurveDataIndex(cursor_index); if (!DoSendEvent( cursor_event )) return false; } int old_cursor_curve = m_cursor_curve; int old_cursor_index = m_cursor_index; m_cursorMarker.SetPlotPosition(cursorPt); m_cursor_curve = curve_index; m_cursor_index = cursor_index; if (send_event) { wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGED, GetId(), this ); cursor_event.SetPosition( cursorPt.m_x, cursorPt.m_y ); cursor_event.SetCurve( plotData, curve_index ); cursor_event.SetCurveDataIndex(cursor_index); (void)DoSendEvent( cursor_event ); } if ((m_active_index == old_cursor_curve) && (m_active_index == m_cursor_curve)) { RedrawDataCurve(curve_index, old_cursor_index, old_cursor_index); RedrawDataCurve(curve_index, m_cursor_index, m_cursor_index); } else Redraw(wxPLOT_REDRAW_PLOT); return true; } bool wxPlotCtrl::SetCursorXPoint(int curve_index, double x, bool send_event) { wxCHECK_MSG(CurveIndexOk(curve_index), false, wxT("invalid curve index")); if (GetDataCurve(curve_index)) return SetCursorDataIndex(curve_index, GetDataCurve(curve_index)->GetIndexFromX(x), send_event); // do nothing if already set if ((m_cursor_curve == curve_index) && (m_cursorMarker.GetPlotRect().m_x == x)) return false; wxPlotCurve *plotCurve = GetCurve(curve_index); wxPoint2DDouble cursorPt(x, plotCurve->GetY(x)); if (send_event) { wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGING, GetId(), this ); cursor_event.SetPosition(cursorPt.m_x, cursorPt.m_y); cursor_event.SetCurve( plotCurve, curve_index ); if (!DoSendEvent( cursor_event )) return false; } m_cursorMarker.SetPlotPosition(cursorPt); m_cursor_curve = curve_index; m_cursor_index = -1; if (send_event) { wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGED, GetId(), this ); cursor_event.SetPosition(cursorPt.m_x, cursorPt.m_y); cursor_event.SetCurve( plotCurve, curve_index ); (void)DoSendEvent( cursor_event ); } Redraw(wxPLOT_REDRAW_PLOT); return true; } void wxPlotCtrl::MakeCursorVisible(bool center, bool send_event) { wxCHECK_RET(IsCursorValid(), wxT("invalid plot cursor")); if (center) { wxPoint2DDouble origin = m_viewRect.GetLeftTop() - m_viewRect.GetCentre() + GetCursorPoint(); SetOrigin(origin.m_x, origin.m_y, send_event); return; } wxPoint2DDouble origin = GetCursorPoint(); if (m_viewRect.Contains(origin)) return; double dx = 4/m_zoom.m_x; double dy = 4/m_zoom.m_y; if (origin.m_x < m_viewRect.m_x) origin.m_x -= dx; else if (origin.m_x > m_viewRect.GetRight()) origin.m_x = m_viewRect.m_x + (origin.m_x - m_viewRect.GetRight()) + dx; else origin.m_x = m_viewRect.m_x; if (origin.m_y < m_viewRect.m_y) origin.m_y -= dy; else if (origin.m_y > m_viewRect.GetBottom()) origin.m_y = m_viewRect.m_y + (origin.m_y - m_viewRect.GetBottom()) + dy; else origin.m_y = m_viewRect.m_y; SetOrigin(origin.m_x, origin.m_y, send_event); } //------------------------------------------------------------------------- // Selected points, data curves use //------------------------------------------------------------------------- bool wxPlotCtrl::HasSelection(int curve_index) const { if (curve_index == -1) { int n, count = m_curveSelections.GetCount(); for ( n = 0; n < count; n++ ) { if ((m_curveSelections[n].GetCount() > 0) || (m_dataSelections[n].GetCount() > 0)) return true; } return false; } wxCHECK_MSG(CurveIndexOk(curve_index), false, wxT("invalid curve index")); return (m_curveSelections[curve_index].GetCount() > 0) || (m_dataSelections[curve_index].GetCount() > 0); } wxRangeDoubleSelection *wxPlotCtrl::GetCurveSelection(int curve_index) const { wxCHECK_MSG(CurveIndexOk(curve_index), NULL, wxT("invalid curve index")); return &m_curveSelections[curve_index]; } wxRangeIntSelection *wxPlotCtrl::GetDataCurveSelection(int curve_index) const { wxCHECK_MSG(CurveIndexOk(curve_index), NULL, wxT("invalid curve index")); return &m_dataSelections[curve_index]; } bool wxPlotCtrl::UpdateSelectionState(int curve_index, bool send_event) { wxCHECK_MSG(CurveIndexOk(curve_index), false, wxT("invalid curve index")); switch (m_selection_type) { case wxPLOT_SELECT_NONE : break; // should have been handled case wxPLOT_SELECT_SINGLE : { if (HasSelection()) return ClearSelectedRanges(-1, send_event); break; } case wxPLOT_SELECT_SINGLE_CURVE : { int n, count = m_curves.GetCount(); bool done = false; for ( n = 0; n < count; n++ ) { if (n == curve_index) continue; if (HasSelection(n)) done |= ClearSelectedRanges(n, send_event); } return done; } case wxPLOT_SELECT_SINGLE_PER_CURVE : { if (HasSelection(curve_index)) return ClearSelectedRanges(curve_index, send_event); break; } case wxPLOT_SELECT_MULTIPLE : break; // anything goes default : break; } return false; } bool wxPlotCtrl::DoSelectRectangle(int curve_index, const wxRect2DDouble &rect, bool select, bool send_event) { wxCHECK_MSG((curve_index >= -1) && (curve_index 0) || (rect.m_height > 0), false, wxT("invalid selection range")); if (m_selection_type == wxPLOT_SELECT_NONE) return false; if (!IsFinite(rect.m_x, wxT("Selection x is NaN")) || !IsFinite(rect.m_y, wxT("Selection y is NaN")) || !IsFinite(rect.m_width, wxT("Selection width is NaN")) || !IsFinite(rect.m_height, wxT("Selection height is NaN")) ) return false; bool done = false; // Run this code for all the curves if curve == -1 then exit if (curve_index == -1) { size_t n, curve_count = m_curves.GetCount(); for (n = 0; n < curve_count; n++) done |= DoSelectRectangle(n, rect, select, send_event); return done; } // check the selection type and clear previous selections if necessary if (select) UpdateSelectionState(curve_index, send_event); bool is_x_range = rect.m_height <= 0; bool is_y_range = rect.m_width <= 0; wxRangeDouble xRange(rect.m_x, rect.GetRight()); wxRangeDouble yRange(rect.m_y, rect.GetBottom()); wxPlotData *plotData = GetDataCurve(curve_index); if (plotData) { wxCHECK_MSG(plotData->Ok(), false, wxT("Invalid data curve")); wxRect2DDouble r(plotData->GetBoundingRect()); if ((xRange.m_max < r.GetLeft()) || (xRange.m_min > r.GetRight())) return false; if (is_x_range && plotData->GetIsXOrdered()) { int min_ = plotData->GetIndexFromX(xRange.m_min); int max_ = plotData->GetIndexFromX(xRange.m_max); int count = plotData->GetCount(); if ( (plotData->GetXValue(min_) > xRange.m_min) && (min_ > 0) && (plotData->GetXValue(min_-1) > xRange.m_min) ) min_--; if ( (plotData->GetXValue(min_) < xRange.m_min) && (min_ < count -1) ) min_++; if ( (plotData->GetXValue(max_) > xRange.m_max) && (max_ > 0) ) max_--; if ( (plotData->GetXValue(max_) < xRange.m_max) && (max_ < count-1) && (plotData->GetXValue(max_+1) < xRange.m_max) ) max_++; wxRangeInt sel(min_, max_); // always check if max < min! - not a bug if (!sel.IsEmpty()) { if (select) m_curveSelections[curve_index].SelectRange(wxRangeDouble(rect.m_x, rect.GetRight())); else m_curveSelections[curve_index].DeselectRange(wxRangeDouble(rect.m_x, rect.GetRight())); return DoSelectDataRange(curve_index, sel, select, send_event); } else return false; } else // not ordered or not just an x selection { int i, count = plotData->GetCount(); int first_sel = -1; double *x_data = plotData->GetXData(); double *y_data = plotData->GetYData(); int min_ = plotData->GetCount()-1, max_ = 0; wxRangeIntSelection ranges; for (i=0; i= 0) && (range.m_max < (int)plotData->GetCount()), false, wxT("invalid index")); // check the selection type and clear previous selections if necessary if (select) UpdateSelectionState(curve_index, send_event); bool done = false; if (select) done = m_dataSelections[curve_index].SelectRange(range); else done = m_dataSelections[curve_index].DeselectRange(range); wxPrintf(wxT("Do sel %d %d %d\n"), range.m_min, range.m_max, done); if (send_event && done) { wxPlotSelectionEvent event( wxEVT_PLOT_RANGE_SEL_CHANGED, GetId(), this); event.SetCurve(GetCurve(curve_index), curve_index); event.SetDataSelectionRange( range, select ); event.m_dataSelection.SelectRange(range); (void)DoSendEvent( event ); } if (done) RedrawDataCurve(curve_index, range.m_min, range.m_max); return done; } int wxPlotCtrl::GetSelectedRangeCount(int curve_index) const { wxCHECK_MSG(CurveIndexOk(curve_index), 0, wxT("invalid plotcurve index")); if (GetDataCurve(curve_index)) return m_dataSelections[curve_index].GetCount(); else return m_curveSelections[curve_index].GetCount(); } bool wxPlotCtrl::ClearSelectedRanges(int curve_index, bool send_event) { wxCHECK_MSG((curve_index >= -1) && (curve_index 0; m_dataSelections[curve_index].Clear(); m_curveSelections[curve_index].Clear(); if (done) RedrawDataCurve(curve_index, 0, GetDataCurve(curve_index)->GetCount()-1); } else { done = m_curveSelections[curve_index].GetCount() > 0; m_curveSelections[curve_index].Clear(); m_dataSelections[curve_index].Clear(); if (done) RedrawCurve(curve_index, m_viewRect.m_x, m_viewRect.GetRight()); } } if (send_event && done) { wxPlotSelectionEvent event( wxEVT_PLOT_RANGE_SEL_CHANGED, GetId(), this); event.SetCurve(GetCurve(curve_index), curve_index); if (IsDataCurve(curve_index)) event.SetDataSelectionRange(wxRangeInt(0, GetDataCurve(curve_index)->GetCount()-1), false); else event.SetCurveSelectionRange(wxEmptyRangeDouble, false); (void)DoSendEvent( event ); } return done; } // ------------------------------------------------------------------------ // Get/Set origin, size, and Zoom in/out of view, set scaling, size... // ------------------------------------------------------------------------ /* // FIXME - can't shift the bitmap due to off by one errors in ClipLineToRect void wxPlotCtrl::ShiftOrigin( int dx, int dy, bool send_event ) { if ((dx == 0) && (dy == 0)) return; if (send_event) { wxPlotEvent event( wxEVT_PLOT_VIEW_CHANGING, GetId(), this); event.SetCurve(m_activeCurve, m_active_index); if (DoSendEvent(event)) return; } { wxBitmap tempBitmap(m_areaClientRect.width, m_areaClientRect.height); wxMemoryDC mdc; mdc.SelectObject(tempBitmap); mdc.DrawBitmap( m_area->m_bitmap, dx, dy, false ); mdc.SelectObject(wxNullBitmap); m_area->m_bitmap = tempBitmap; } wxRect rx, ry; m_viewRect.m_x -= dx / m_zoom.m_x; m_viewRect.m_y += dy / m_zoom.m_y; if (dx != 0) { rx = wxRect((dx>0 ? -5 : m_areaClientRect.width+dx-5), 0, labs(dx)+10, m_areaClientRect.height); RedrawXAxis(false); } if (dy != 0) { ry = wxRect(0, (dy>0 ? -5 : m_areaClientRect.height+dy-5), m_areaClientRect.width, labs(dy)+10); RedrawYAxis(false); } printf("Shift %d %d rx %d %d %d %d, ry %d %d %d %d\n", dx, dy, rx.x, rx.y, rx.width, rx.height, ry.x, ry.y, ry.width, ry.height); fflush(stdout); if (rx.width > 0) m_area->CreateBitmap( rx ); //m_area->Refresh(false, &rx); if (ry.height > 0) m_area->CreateBitmap( ry ); //m_area->Refresh(false, &ry); { wxClientDC cdc(m_area); cdc.DrawBitmap(m_area->m_bitmap, 0, 0); } AdjustScrollBars(); if (send_event) { wxPlotEvent event( wxEVT_PLOT_VIEW_CHANGED, GetId(), this); event.SetCurve(m_activeCurve, m_active_index); (void)DoSendEvent( event ); } } */ bool wxPlotCtrl::MakeCurveVisible(int curve_index, bool send_event) { if (curve_index < 0) return SetZoom( -1, -1, 0, 0, send_event ); wxCHECK_MSG(curve_index < GetCurveCount(), false, wxT("Invalid curve index")); wxPlotCurve *curve = GetCurve(curve_index); wxCHECK_MSG(curve && curve->Ok(), false, wxT("Invalid curve")); return SetViewRect(curve->GetBoundingRect(), send_event); } bool wxPlotCtrl::SetViewRect(const wxRect2DDouble &view, bool send_event) { double zoom_x = m_areaClientRect.width/view.m_width; double zoom_y = m_areaClientRect.height/view.m_height; return SetZoom(zoom_x, zoom_y, view.m_x, view.m_y, send_event); } bool wxPlotCtrl::SetZoom( const wxPoint2DDouble &zoom, bool around_center, bool send_event ) { if (around_center && (zoom.m_x > 0) && (zoom.m_y > 0)) { double origin_x = (m_viewRect.GetLeft() + m_viewRect.m_width/2.0); origin_x -= (m_viewRect.m_width/2.0)*m_zoom.m_x/zoom.m_x; double origin_y = (m_viewRect.GetTop() + m_viewRect.m_height/2.0); origin_y -= (m_viewRect.m_height/2.0)*m_zoom.m_y/zoom.m_y; return SetZoom( zoom.m_x, zoom.m_y, origin_x, origin_y, send_event ); } else return SetZoom( zoom.m_x, zoom.m_y, m_viewRect.GetLeft(), m_viewRect.GetTop(), send_event ); } bool wxPlotCtrl::SetZoom( const wxRect &window, bool send_event ) { if ((window.GetHeight()<1) || (window.GetWidth()<1)) return false; double origin_x = GetPlotCoordFromClientX(window.GetX()); double origin_y = GetPlotCoordFromClientY(window.GetY()+window.GetHeight()); double zoom_x = m_zoom.m_x * double(m_areaClientRect.width) /(window.GetWidth()); double zoom_y = m_zoom.m_y * double(m_areaClientRect.height)/(window.GetHeight()); bool ok = SetZoom( zoom_x, zoom_y, origin_x, origin_y, send_event ); if (ok) AddHistoryView(); return ok; } bool wxPlotCtrl::SetZoom( double zoom_x, double zoom_y, double origin_x, double origin_y, bool send_event ) { // fit to window if zoom <= 0 if (zoom_x <= 0) { zoom_x = double(m_areaClientRect.width)/(m_curveBoundingRect.m_width); origin_x = m_curveBoundingRect.m_x; } if (zoom_y <= 0) { zoom_y = double(m_areaClientRect.height)/(m_curveBoundingRect.m_height); origin_y = m_curveBoundingRect.m_y; } if (m_fix_aspectratio) FixAspectRatio( &zoom_x, &zoom_y, &origin_x, &origin_y ); double view_width = m_areaClientRect.width/zoom_x; double view_height = m_areaClientRect.height/zoom_y; if (!IsFinite(zoom_x, wxT("X zoom is NaN"))) return false; if (!IsFinite(zoom_y, wxT("Y zoom is NaN"))) return false; if (!IsFinite(origin_x, wxT("X origin is not finite"))) return false; if (!IsFinite(origin_y, wxT("Y origin is not finite"))) return false; if (!IsFinite(view_width, wxT("Plot width is NaN"))) return false; if (!IsFinite(view_height, wxT("Plot height is NaN"))) return false; bool x_changed = false, y_changed = false; if ((m_viewRect.m_x != origin_x) || (m_zoom.m_x != zoom_x)) x_changed = true; if ((m_viewRect.m_y != origin_y) || (m_zoom.m_y != zoom_y)) y_changed = true; if (x_changed || y_changed) { if (send_event) { wxPlotEvent event( wxEVT_PLOT_VIEW_CHANGING, GetId(), this); event.SetCurve(m_activeCurve, m_active_index); if (!DoSendEvent(event)) return false; } m_zoom.m_x = zoom_x; m_zoom.m_y = zoom_y; m_viewRect.m_x = origin_x; m_viewRect.m_y = origin_y; m_viewRect.m_width = view_width; m_viewRect.m_height = view_height; } // redraw even if unchanged since we expect that it should be different Redraw(wxPLOT_REDRAW_PLOT | (x_changed?wxPLOT_REDRAW_XAXIS:0) | (y_changed?wxPLOT_REDRAW_YAXIS:0)); if (!m_batch_count) AdjustScrollBars(); if (send_event && (x_changed || y_changed)) { wxPlotEvent event( wxEVT_PLOT_VIEW_CHANGED, GetId(), this); event.SetCurve(m_activeCurve, m_active_index); (void)DoSendEvent( event ); } return true; } void wxPlotCtrl::SetFixAspectRatio(bool fix, double ratio) { wxCHECK_RET(ratio > 0, wxT("Invalid aspect ratio")); m_fix_aspectratio = fix; m_aspectratio = ratio; } void wxPlotCtrl::FixAspectRatio( double *zoom_x, double *zoom_y, double *origin_x, double *origin_y ) { wxCHECK_RET(zoom_x && zoom_y && origin_x && origin_y, wxT("Invalid parameters")); //get the width and height of the view in plot coordinates double viewWidth = m_areaClientRect.width / (*zoom_x); double viewHeight = m_areaClientRect.height / (*zoom_y); //get the centre of the visible area in plot coordinates double xCentre = (*origin_x) + viewWidth / 2; double yCentre = (*origin_y) + viewHeight / 2; //if zoom in one direction is more than in the other, reduce both to the lower value if( (*zoom_x) * m_aspectratio > (*zoom_y) ) { (*zoom_x) = (*zoom_y) * m_aspectratio; (*zoom_y) = (*zoom_y); } else { (*zoom_x) = (*zoom_x); (*zoom_y) = (*zoom_x) / m_aspectratio; } //update the plot coordinate view width and height based on the new zooms viewWidth = m_areaClientRect.width / (*zoom_x); viewHeight = m_areaClientRect.height / (*zoom_y); //create the new bottom-left corner of the view in plot coordinates *origin_x = xCentre - (viewWidth / 2); *origin_y = yCentre - (viewHeight / 2); } void wxPlotCtrl::SetDefaultBoundingRect( const wxRect2DDouble &rect, bool send_event ) { wxCHECK_RET(wxFinite(rect.m_x)&&wxFinite(rect.m_y)&&wxFinite(rect.GetRight())&&wxFinite(rect.GetBottom()), wxT("bounding rect is NaN")); wxCHECK_RET((rect.m_width > 0) && (rect.m_height > 0), wxT("Plot Size < 0")); m_defaultPlotRect = rect; CalcBoundingPlotRect(); SetZoom( m_areaClientRect.width/rect.m_width, m_areaClientRect.height/rect.m_height, rect.m_x, rect.m_y, send_event); } void wxPlotCtrl::AddHistoryView() { if (!(wxFinite(m_viewRect.GetLeft())&&wxFinite(m_viewRect.GetRight())&&wxFinite(m_viewRect.GetTop())&&wxFinite(m_viewRect.GetBottom()))) return; if ((m_history_views_index >= 0) && (m_history_views_index < int(m_historyViews.GetCount())) && WXRECT2DDOUBLE_EQUAL(m_viewRect, m_historyViews[m_history_views_index])) return; if (int(m_historyViews.GetCount()) >= MAX_PLOT_ZOOMS) { if (m_history_views_index < int(m_historyViews.GetCount())-1) { m_historyViews[m_history_views_index] = m_viewRect; } else { m_historyViews.RemoveAt(0); m_historyViews.Add(m_viewRect); } } else { m_historyViews.Add(m_viewRect); m_history_views_index++; } } void wxPlotCtrl::NextHistoryView(bool foward, bool send_event) { int count = m_historyViews.GetCount(); // try to set it to the "current" history view if ((m_history_views_index > -1) && (m_history_views_index < count)) { if (!WXRECT2DDOUBLE_EQUAL(m_viewRect, m_historyViews[m_history_views_index])) SetViewRect(m_historyViews[m_history_views_index], send_event); } if (foward) { if ((count > 0) && (m_history_views_index < count - 1)) { m_history_views_index++; SetViewRect(m_historyViews[m_history_views_index], send_event); } } else { if (m_history_views_index > 0) { m_history_views_index--; SetViewRect(m_historyViews[m_history_views_index], send_event); } else SetZoom(-1, -1, 0, 0, send_event); } } void wxPlotCtrl::SetAreaMouseFunction( wxPlotMouse_Type func, bool send_event ) { if (func == m_area_mouse_func) return; if (send_event) { wxPlotEvent event1(wxEVT_PLOT_MOUSE_FUNC_CHANGING, GetId(), this); event1.SetMouseFunction(func); if (!DoSendEvent(event1)) return; } m_area_mouse_func = func; switch (func) { case wxPLOT_MOUSE_ZOOM : { SetAreaMouseCursor(wxCURSOR_MAGNIFIER); //wxCURSOR_CROSS); break; } case wxPLOT_MOUSE_SELECT : case wxPLOT_MOUSE_DESELECT : { SetAreaMouseCursor(wxCURSOR_ARROW); break; } case wxPLOT_MOUSE_PAN : { SetAreaMouseCursor(wxCURSOR_HAND); SetAreaMouseMarker(wxPLOT_MARKER_NONE); break; } case wxPLOT_MOUSE_NOTHING : default : { SetAreaMouseCursor(wxCURSOR_CROSS); SetAreaMouseMarker(wxPLOT_MARKER_NONE); break; } } if (send_event) { wxPlotEvent event2(wxEVT_PLOT_MOUSE_FUNC_CHANGED, GetId(), this); event2.SetMouseFunction(func); (void)DoSendEvent(event2); } } void wxPlotCtrl::SetAreaMouseMarker( wxPlotMarker_Type type ) { if (type == m_area_mouse_marker) return; wxClientDC dc(m_area); DrawMouseMarker( &dc, m_area_mouse_marker, m_area->m_mouseRect ); m_area_mouse_marker = type; DrawMouseMarker( &dc, m_area_mouse_marker, m_area->m_mouseRect ); } void wxPlotCtrl::SetAreaMouseCursor(int cursorid) { if (cursorid == m_area_mouse_cursorid) return; m_area_mouse_cursorid = cursorid; if (cursorid == wxCURSOR_HAND) m_area->SetCursor(s_handCursor); else if (cursorid == CURSOR_GRAB) m_area->SetCursor(s_grabCursor); else m_area->SetCursor(wxCursor(cursorid)); } void wxPlotCtrl::OnSize( wxSizeEvent& ) { DoSize(); } void wxPlotCtrl::DoSize(const wxRect &boundingRect) { if (!m_yAxisScrollbar) return; // we're not created yet m_redraw_type = wxPLOT_REDRAW_BLOCKER; // block OnPaints until done wxSize size; if(boundingRect == wxRect(0, 0, 0, 0)) { UpdateWindowSize(); size = GetClientSize(); } else { size.x = boundingRect.width; size.y = boundingRect.height; } int sb_width = m_yAxisScrollbar->GetSize().GetWidth(); m_clientRect = wxRect(0, 0, size.x-sb_width, size.y-sb_width); // scrollbar to right and bottom m_yAxisScrollbar->SetSize(m_clientRect.width, 0, sb_width, m_clientRect.height ); m_xAxisScrollbar->SetSize(0, m_clientRect.height, m_clientRect.width, sb_width ); // title and label positions, add padding here wxRect titleRect = m_show_title ? wxRect(m_titleRect).Inflate(m_border) : wxRect(0,0,1,1); wxRect xLabelRect = m_show_xlabel ? wxRect(m_xLabelRect).Inflate(m_border) : wxRect(0,0,1,1); wxRect yLabelRect = m_show_ylabel ? wxRect(m_yLabelRect).Inflate(m_border) : wxRect(0,0,1,1); // this is the border around the area, it lets you see about 1 digit extra on axis int area_border = m_axisFontSize.y/2; // use the area_border between top of y-axis and area as bottom border of title if (m_show_title) titleRect.height -= m_border; int yaxis_width = GetShowYAxis() ? m_y_axis_text_width : 1; int xaxis_height = GetShowXAxis() ? m_axisFontSize.y : 0; int area_width = m_clientRect.width - yLabelRect.GetRight() - yaxis_width - 2*area_border; int area_height = m_clientRect.height - titleRect.GetBottom() - xaxis_height - xLabelRect.height - area_border; m_yAxisRect = wxRect(yLabelRect.GetRight(), titleRect.GetBottom(), yaxis_width, area_height + 2*area_border); m_xAxisRect = wxRect(m_yAxisRect.GetRight(), m_yAxisRect.GetBottom() - area_border + 1, area_width + 2*area_border, xaxis_height); m_areaRect = wxRect(m_yAxisRect.GetRight() + area_border, m_yAxisRect.GetTop() + area_border, area_width, area_height); m_yAxis->SetSize(m_yAxisRect); m_xAxis->SetSize(m_xAxisRect); m_area->SetSize(m_areaRect); m_titleRect.x = m_areaRect.x + ( m_areaRect.width - m_titleRect.GetWidth() ) / 2; //m_titleRect.x = m_clientRect.width/2-m_titleRect.GetWidth()/2; center on whole plot m_titleRect.y = m_border; m_xLabelRect.x = m_areaRect.x + m_areaRect.width/2 - m_xLabelRect.width/2; m_xLabelRect.y = m_xAxisRect.GetBottom() + m_border; m_yLabelRect.x = m_border; m_yLabelRect.y = m_areaRect.y + m_areaRect.height/2 - m_yLabelRect.height/2; UpdateWindowSize(); double zoom_x = m_areaClientRect.width/m_viewRect.m_width; double zoom_y = m_areaClientRect.height/m_viewRect.m_height; if (!IsFinite(zoom_x, wxT("Plot zoom is NaN"))) return; if (!IsFinite(zoom_y, wxT("Plot zoom is NaN"))) return; if (m_fix_aspectratio) { double x = m_viewRect.m_x, y = m_viewRect.m_y; //FixAspectRatio( &zoom_x, &zoom_y, &m_viewRect.m_x, &m_viewRect.m_y ); FixAspectRatio(&zoom_x, &zoom_y, &x, &y); m_viewRect.m_x = x; m_viewRect.m_y = y; m_viewRect.m_width = m_areaClientRect.width/zoom_x; m_viewRect.m_height = m_areaClientRect.height/zoom_y; } m_zoom.m_x = zoom_x; m_zoom.m_y = zoom_y; wxPlotEvent event( wxEVT_PLOT_VIEW_CHANGED, GetId(), this); event.SetCurve(m_activeCurve, m_active_index); (void)DoSendEvent( event ); m_redraw_type = 0; Redraw(wxPLOT_REDRAW_WHOLEPLOT); } void wxPlotCtrl::CalcBoundingPlotRect() { int i, count = m_curves.GetCount(); if (count > 0) { bool valid_rect = false; wxRect2DDouble rect = m_curves[0].GetBoundingRect(); if ( IsFinite(rect.m_x, wxT("left curve boundary is NaN")) && IsFinite(rect.m_y, wxT("bottom curve boundary is NaN")) && IsFinite(rect.GetRight(), wxT("right curve boundary is NaN")) && IsFinite(rect.GetBottom(), wxT("top curve boundary is NaN")) && (rect.m_width >= 0) && (rect.m_height >= 0) ) { valid_rect = true; } else rect = wxRect2DDouble(0, 0, 0, 0); for (i=1; i= 0) && (newRect.m_height >= 0)) { if (!valid_rect) valid_rect = true; rect = newRect; } } // maybe just a single point, center it using default size bool zeroWidth = false, zeroHeight = false; if (rect.m_width == 0.0) { zeroWidth = true; rect.m_x = m_defaultPlotRect.m_x; rect.m_width = m_defaultPlotRect.m_width; } if (rect.m_height == 0.0) { zeroHeight = true; rect.m_y = m_defaultPlotRect.m_y; rect.m_height = m_defaultPlotRect.m_height; } m_curveBoundingRect = rect; // add some padding so the edge points can be seen double w = (!zeroWidth) ? rect.m_width/50.0 : 0.0; double h = (!zeroHeight) ? rect.m_height/50.0 : 0.0; m_curveBoundingRect.Inset(-w, -h, -w, -h); } else m_curveBoundingRect = m_defaultPlotRect; AdjustScrollBars(); } void wxPlotCtrl::Redraw(int type) { if (m_batch_count) return; if (type & wxPLOT_REDRAW_XAXIS) { m_redraw_type |= wxPLOT_REDRAW_XAXIS; AutoCalcXAxisTicks(); if (m_correct_ticks == true) CorrectXAxisTicks(); CalcXAxisTickPositions(); } if (type & wxPLOT_REDRAW_YAXIS) { m_redraw_type |= wxPLOT_REDRAW_YAXIS; AutoCalcYAxisTicks(); if (m_correct_ticks == true) CorrectYAxisTicks(); CalcYAxisTickPositions(); } if (type & wxPLOT_REDRAW_PLOT) { m_redraw_type |= wxPLOT_REDRAW_PLOT; m_area->Refresh(false); } if (type & wxPLOT_REDRAW_XAXIS) m_xAxis->Refresh(false); if (type & wxPLOT_REDRAW_YAXIS) m_yAxis->Refresh(false); if (type & wxPLOT_REDRAW_WINDOW) Refresh(); } void wxPlotCtrl::DrawAreaWindow( wxDC *dc, const wxRect &rect ) { wxCHECK_RET(dc, wxT("invalid dc")); // GTK doesn't like invalid parameters wxRect refreshRect = rect; wxRect clientRect(GetPlotAreaRect()); refreshRect.Intersect(clientRect); if ((refreshRect.width == 0) || (refreshRect.height == 0)) return; dc->SetClippingRegion(refreshRect); dc->SetBrush( wxBrush(GetBackgroundColour(), wxSOLID) ); dc->SetPen( wxPen(GetBorderColour(), m_area_border_width, wxSOLID) ); dc->DrawRectangle(clientRect); DrawTickMarks( dc, refreshRect ); DrawMarkers( dc, refreshRect ); dc->DestroyClippingRegion(); int i; wxPlotCurve *curve; wxPlotCurve *activeCurve = GetActiveCurve(); for(i=0; im_plotMarkers.GetCount(); mdc.SetPen( *wxRED_PEN ); for (i=0; iGetClientCoordFromPlotX( m_owner->m_plotMarkers.Item(i).m_x ); int y = m_owner->GetClientCoordFromPlotY( m_owner->m_plotMarkers.Item(i).m_y ); if (m_owner->GetPlotAreaRect().Inside(x, y)) { mdc.DrawLine( x-10, y, x+10, y ); mdc.DrawLine( x, y-10, x, y+10 ); } } */ // refresh border dc->SetBrush( *wxTRANSPARENT_BRUSH ); dc->SetPen( wxPen(GetBorderColour(), m_area_border_width, wxSOLID) ); dc->DrawRectangle(clientRect); dc->SetPen( wxNullPen ); dc->SetBrush( wxNullBrush ); } void wxPlotCtrl::DrawMouseMarker( wxDC *dc, int type, const wxRect &rect ) { wxCHECK_RET(dc, wxT("invalid window")); if ((rect.width == 0) || (rect.height == 0)) return; int logical_fn = dc->GetLogicalFunction(); dc->SetLogicalFunction( wxINVERT ); dc->SetBrush( *wxTRANSPARENT_BRUSH ); dc->SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1, wxDOT)); switch (type) { case wxPLOT_MARKER_NONE : break; case wxPLOT_MARKER_RECT : { // rects are drawn to width and height - 1, doesn't line up w/ cursor, who cares? dc->DrawRectangle( rect.x, rect.y, rect.width, rect.height ); break; } case wxPLOT_MARKER_VERT : { if (rect.width != 0) { int height = GetClientSize().y; dc->DrawLine(rect.x, 1, rect.x, height-2); dc->DrawLine(rect.GetRight()+1, 1, rect.GetRight()+1, height-2); } break; } case wxPLOT_MARKER_HORIZ : { if (rect.height != 0) { int width = GetClientSize().x; dc->DrawLine(1, rect.y, width-2, rect.y); dc->DrawLine(1, rect.GetBottom()+1, width-2, rect.GetBottom()+1); } break; } default : break; } dc->SetBrush( wxNullBrush ); dc->SetPen( wxNullPen ); dc->SetLogicalFunction( logical_fn ); } void wxPlotCtrl::DrawCrosshairCursor( wxDC *dc, const wxPoint &pos ) { wxCHECK_RET(dc, wxT("invalid window")); dc->SetPen(*wxBLACK_PEN); int logical_fn = dc->GetLogicalFunction(); dc->SetLogicalFunction( wxINVERT ); dc->CrossHair(pos.x, pos.y); dc->SetPen( wxNullPen ); dc->SetLogicalFunction( logical_fn ); } void wxPlotCtrl::DrawDataCurve( wxDC *dc, wxPlotData *curve, int curve_index, const wxRect &rect ) { wxCHECK_RET(dc && m_dataCurveDrawer && curve && curve->Ok(), wxT("invalid curve")); m_dataCurveDrawer->SetDCRect(rect); m_dataCurveDrawer->SetPlotViewRect(m_viewRect); m_dataCurveDrawer->Draw(dc, curve, curve_index); } void wxPlotCtrl::DrawCurve( wxDC *dc, wxPlotCurve *curve, int curve_index, const wxRect &rect ) { wxCHECK_RET(dc && m_curveDrawer && curve && curve->Ok(), wxT("invalid curve")); m_curveDrawer->SetDCRect(rect); m_curveDrawer->SetPlotViewRect(m_viewRect); m_curveDrawer->Draw(dc, curve, curve_index); } void wxPlotCtrl::RedrawDataCurve(int index, int min_index, int max_index) { if (m_batch_count) return; wxCHECK_RET((index>=0)&&(index<(int)m_curves.GetCount()), wxT("invalid curve index")); wxPlotData *plotData = GetDataCurve(index); wxCHECK_RET(plotData, wxT("not a data curve")); int count = plotData->GetCount(); wxCHECK_RET((min_index<=max_index)&&(min_index>=0)&&(max_index>=0)&&(min_indexGetIsXOrdered()) { double x = plotData->GetXValue(wxMax(min_index-1, 0)); if (x > m_viewRect.GetRight()) return; else if (x < m_viewRect.m_x) rect.x = 0; else rect.x = GetClientCoordFromPlotX(x) - cursor_size/2 - 1; x = plotData->GetXValue(wxMin(max_index+1, (int)plotData->GetCount()-1)); if (x < m_viewRect.m_x) return; else if (x > m_viewRect.GetRight()) rect.SetRight(m_areaClientRect.width); else rect.SetRight(GetClientCoordFromPlotX(x) + cursor_size/2 + 1); rect.Intersect(m_areaClientRect); } wxMemoryDC mdc; mdc.SelectObject( m_area->m_bitmap ); DrawDataCurve( &mdc, plotData, index, rect ); DrawCurveCursor(&mdc); wxClientDC dc(m_area); dc.Blit(rect.x, rect.y, rect.width, rect.height, &mdc, rect.x, rect.y); mdc.SelectObject( wxNullBitmap ); } void wxPlotCtrl::RedrawCurve(int index, double min_x, double max_x) { if (m_batch_count) return; wxCHECK_RET((min_x<=max_x)&&(index>=0)&&(index<(int)m_curves.GetCount()), wxT("invalid curve index")); wxCHECK_RET(!GetDataCurve(index), wxT("invalid curve")); wxRect rect(m_areaClientRect); if (min_x > m_viewRect.GetRight()) return; if (min_x < m_viewRect.m_x) min_x = m_viewRect.m_x; rect.x = GetClientCoordFromPlotX(min_x); if (max_x < m_viewRect.m_x) return; if (max_x > m_viewRect.GetRight()) max_x = m_viewRect.GetRight(); rect.width = GetClientCoordFromPlotX(max_x) - rect.x; if (rect.width < 1) return; wxMemoryDC mdc; mdc.SelectObject( m_area->m_bitmap ); DrawCurve(&mdc, GetCurve(index), index, rect); DrawCurveCursor(&mdc); wxClientDC dc(m_area); dc.Blit(rect.x, rect.y, rect.width, rect.height, &mdc, rect.x, rect.y); mdc.SelectObject( wxNullBitmap ); } void wxPlotCtrl::DrawKey( wxDC *dc ) { wxCHECK_RET(dc && m_keyDrawer, wxT("invalid window")); if (!GetShowKey() || m_keyString.IsEmpty()) return; wxRect dcRect(wxPoint(0, 0), GetPlotAreaRect().GetSize()); m_keyDrawer->SetDCRect(dcRect); m_keyDrawer->SetPlotViewRect(m_viewRect); m_keyDrawer->Draw(dc, m_keyString); } void wxPlotCtrl::DrawCurveCursor( wxDC *dc ) { wxCHECK_RET(dc, wxT("invalid window")); if (!IsCursorValid()) return; m_markerDrawer->SetPlotViewRect(m_viewRect); m_markerDrawer->SetDCRect(wxRect(wxPoint(0,0), m_area->GetClientSize())); m_markerDrawer->Draw(dc, m_cursorMarker); /* wxPoint2DDouble cursor = GetCursorPoint(); if ((GetCursorSize() > 0) && wxPlotRect2DDoubleContains(cursor.m_x, cursor.m_y, m_viewRect)) { dc->SetPen( wxPen(GetCursorColour(), 1, wxSOLID) ); int i = GetClientCoordFromPlotX(cursor.m_x); int j = GetClientCoordFromPlotY(cursor.m_y); dc->DrawCircle(i, j, m_cursor_size); if (m_cursor_size > 2) { dc->DrawLine(i - (m_cursor_size - 1), j, i + (m_cursor_size - 1), j); dc->DrawLine(i, j - (m_cursor_size - 1), i, j + (m_cursor_size - 1)); } } */ } void wxPlotCtrl::DrawTickMarks( wxDC *dc, const wxRect& rect ) { wxRect clientRect(GetPlotAreaRect()); dc->SetPen( wxPen(GetGridColour(), 1, wxSOLID) ); int xtick_length = GetDrawGrid() ? clientRect.height : 10; int ytick_length = GetDrawGrid() ? clientRect.width : 10; int tick_pos, i; // X-axis ticks int tick_count = m_xAxisTicks.GetCount(); for (i=0; i rect.GetRight()) break; dc->DrawLine(tick_pos, clientRect.height, tick_pos, clientRect.height - xtick_length); } // Y-axis ticks tick_count = m_yAxisTicks.GetCount(); for (i=0; i rect.GetBottom()) continue; dc->DrawLine(0, tick_pos, ytick_length, tick_pos); } } void wxPlotCtrl::DrawMarkers( wxDC *dc, const wxRect& rect ) { wxCHECK_RET(m_markerDrawer, wxT("Invalid marker drawer")); m_markerDrawer->SetPlotViewRect(m_viewRect); m_markerDrawer->SetDCRect(rect); m_markerDrawer->Draw(dc, m_plotMarkers); } void wxPlotCtrl::DrawXAxis( wxDC *dc, bool refresh ) { wxCHECK_RET(m_xAxisDrawer, wxT("Invalid x axis drawer")); m_xAxisDrawer->SetTickPositions( m_xAxisTicks ); m_xAxisDrawer->SetTickLabels( m_xAxisTickLabels ); m_xAxisDrawer->SetPlotViewRect(m_viewRect); wxSize clientSize = m_xAxisRect.GetSize(); m_xAxisDrawer->SetDCRect(wxRect(wxPoint(0,0),clientSize)); m_xAxisDrawer->Draw(dc, refresh); } void wxPlotCtrl::DrawYAxis( wxDC *dc, bool refresh ) { wxCHECK_RET(m_yAxisDrawer, wxT("Invalid y axis drawer")); m_yAxisDrawer->SetTickPositions( m_yAxisTicks ); m_yAxisDrawer->SetTickLabels( m_yAxisTickLabels ); m_yAxisDrawer->SetPlotViewRect(m_viewRect); wxSize clientSize = m_yAxisRect.GetSize(); m_yAxisDrawer->SetDCRect(wxRect(wxPoint(0,0),clientSize)); m_yAxisDrawer->Draw(dc, refresh); } wxRect ScaleRect(const wxRect& rect, double x_scale, double y_scale) { return wxRect( int(rect.x*x_scale+0.5), int(rect.y*y_scale+0.5), int(rect.width*x_scale+0.5), int(rect.height*y_scale+0.5) ); } void wxPlotCtrl::DrawWholePlot( wxDC *dc, const wxRect &boundingRect, int dpi ) { wxCHECK_RET(dc, wxT("invalid dc")); wxCHECK_RET(dpi > 0, wxT("Invalid dpi for plot drawing")); wxSize clientSize = GetClientSize(); int sb_width = m_yAxisScrollbar->GetSize().GetWidth(); clientSize.x -= sb_width; clientSize.y -= sb_width; //set font scale so 1pt = 1pixel at 72dpi double fontScale = (double)dpi / 72.0; //one pixel wide line equals (m_pen_print_width) millimeters wide double penScale = (m_pen_print_width / 25.4) * dpi; //save old values wxFont oldAxisLabelFont = GetAxisLabelFont(); wxFont oldPlotTitleFont = GetPlotTitleFont(); int old_area_border_width = m_area_border_width; int old_border = m_border; int old_cursor_size = m_cursorMarker.GetSize().x; wxPoint2DDouble old_zoom = m_zoom; wxRect2DDouble old_view = m_viewRect; //resize border and border pen m_area_border_width = RINT(m_area_border_width * penScale); m_border = RINT(m_border * penScale); //resize the curve cursor m_cursorMarker.SetSize(wxSize(int(old_cursor_size * penScale), int(old_cursor_size * penScale))); //resize the fonts wxFont axisLabelFont = GetAxisLabelFont(); axisLabelFont.SetPointSize( wxMax(2, RINT(axisLabelFont.GetPointSize() * fontScale)) ); SetAxisLabelFont( axisLabelFont ); wxFont plotTitleFont = GetPlotTitleFont(); plotTitleFont.SetPointSize( wxMax(2, RINT(plotTitleFont.GetPointSize() * fontScale)) ); SetPlotTitleFont( plotTitleFont ); //reload the original zoom and view rect in case it was changed by any of the font changes m_zoom = old_zoom; m_viewRect = old_view; //resize all window component rects to the bounding rect DoSize( boundingRect ); //AutoCalcTicks(); // don't reset ticks since it might not be WYSIWYG //draw all components to the provided dc dc->SetDeviceOrigin(long(boundingRect.x+m_xAxisRect.GetLeft()), long(boundingRect.y+m_xAxisRect.GetTop())); CalcXAxisTickPositions(); DrawXAxis(dc, false); dc->SetDeviceOrigin(long(boundingRect.x+m_yAxisRect.GetLeft()), long(boundingRect.y+m_yAxisRect.GetTop())); CalcYAxisTickPositions(); DrawYAxis(dc, false); dc->SetDeviceOrigin(long(boundingRect.x+m_areaRect.GetLeft()), long(boundingRect.y+m_areaRect.GetTop())); DrawAreaWindow(dc, m_areaClientRect); dc->SetDeviceOrigin(boundingRect.x, boundingRect.y); DrawPlotCtrl(dc); //restore old values m_area_border_width = old_area_border_width; m_border = old_border; m_cursorMarker.SetSize(wxSize(old_cursor_size, old_cursor_size)); SetAxisLabelFont( oldAxisLabelFont ); SetPlotTitleFont( oldPlotTitleFont ); m_zoom = old_zoom; m_viewRect = old_view; //update to window instead of printer UpdateWindowSize(); Redraw(wxPLOT_REDRAW_WHOLEPLOT); // recalc ticks for this window } // ---------------------------------------------------------------------------- // Axis tick calculations // ---------------------------------------------------------------------------- void wxPlotCtrl::DoAutoCalcTicks(bool x_axis) { double start = 0.0, end = 1.0; int i, n, window = 100; double *tick_step = NULL; int *tick_count = NULL; wxString *tickFormat = NULL; if (x_axis) { tick_step = &m_xAxisTick_step; tick_count = &m_xAxisTick_count; tickFormat = &m_xAxisTickFormat; window = GetPlotAreaRect().width; m_xAxisTicks.Clear(); // kill it in case something goes wrong start = m_viewRect.GetLeft(); end = m_viewRect.GetRight(); *tick_count = window/(m_axisFontSize.x*10); } else { tick_step = &m_yAxisTick_step; tick_count = &m_yAxisTick_count; tickFormat = &m_yAxisTickFormat; window = GetPlotAreaRect().height; m_yAxisTicks.Clear(); start = m_viewRect.GetTop(); end = m_viewRect.GetBottom(); double tick_count_scale = window/(m_axisFontSize.y*2.0) > 2.0 ? 2.0 : 1.5; *tick_count = int(window/(m_axisFontSize.y*tick_count_scale) + 0.5); } if (window < 5) return; // FIXME if (!IsFinite(start, wxT("axis range is not finite")) || !IsFinite(end, wxT("axis range is not finite")) ) { *tick_count = 0; return; } double range = end - start; double max = fabs(start) > fabs(end) ? fabs(start) : fabs(end); double min = fabs(start) < fabs(end) ? fabs(start) : fabs(end); bool exponential = (min >= m_min_exponential) || (max < 1.0/m_min_exponential) ? true : false; int places = exponential ? 1 : int(floor(fabs(log10(max)))); if (!IsFinite(range, wxT("axis range is not finite")) || !IsFinite(min, wxT("axis range is not finite")) || !IsFinite(max, wxT("axis range is not finite")) ) { *tick_count = 0; return; } *tick_step = 1.0; int int_log_range = int( log10(range) ); if (int_log_range > 0) { for (i=0; i < int_log_range; i++) (*tick_step) *= 10; } else if (int_log_range < 0) { for (i=0; i < -int_log_range; i++) (*tick_step) /= 10; } double stepsizes[TIC_STEPS] = { .1, .2, .5 }; double step10 = (*tick_step) / 10.0; int sigFigs = 0; int digits = 0; for (n=0; n<4; n++) { for (i=0; i= 1.0 ? 0 : int(ceil(-log10(*tick_step))); if (x_axis) { digits = 1 + places + (sigFigs > 0 ? 1+sigFigs : 0) + (exponential ? 4 : 0); *tick_count = int(double(window)/double((digits+3)*m_axisFontSize.x) + 0.5); } if ((range/(*tick_step)) <= (*tick_count)) break; } if ((range/(*tick_step)) <= (*tick_count)) break; step10 *= 10.0; } //if (!x_axis) wxPrintf(wxT("Ticks %d %lf, %d\n"), n, *tick_step, *tick_count); if (sigFigs > 9) sigFigs = 9; // FIXME if (exponential) tickFormat->Printf( wxT("%%.%dle"), sigFigs ); else tickFormat->Printf( wxT("%%.%dlf"), sigFigs ); *tick_count = int(ceil(range/(*tick_step))) + 1; // note : first_tick = ceil(start / tick_step) * tick_step; } void wxPlotCtrl::CorrectXAxisTicks() { double start = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step; wxString label; label.Printf( m_xAxisTickFormat.c_str(), start); if (label.ToDouble( &start )) { double x = GetClientCoordFromPlotX( start ); double zoom_x = (GetClientCoordFromPlotX(start+m_xAxisTick_step)-x)/m_xAxisTick_step; double origin_x = start - x/zoom_x; BeginBatch(); if (!SetZoom( zoom_x, m_zoom.m_y, origin_x, m_viewRect.GetTop(), true )) m_xAxisTick_count = 0; // oops EndBatch(false); // don't draw just block } } void wxPlotCtrl::CorrectYAxisTicks() { double start = ceil(m_viewRect.GetTop() / m_yAxisTick_step) * m_yAxisTick_step; wxString label; label.Printf( m_yAxisTickFormat.c_str(), start); if (label.ToDouble( &start )) { double y = GetClientCoordFromPlotY( start ); double zoom_y = (y-GetClientCoordFromPlotY(start+m_yAxisTick_step))/m_yAxisTick_step; double origin_y = start - (GetPlotAreaRect().height - y)/zoom_y; BeginBatch(); if (!SetZoom( m_zoom.m_x, zoom_y, m_viewRect.GetLeft(), origin_y, true )) m_yAxisTick_count = 0; // oops EndBatch(false); } } void wxPlotCtrl::CalcXAxisTickPositions() { double current = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step; m_xAxisTicks.Clear(); m_xAxisTickLabels.Clear(); int i, x, windowWidth = GetPlotAreaRect().width; for (i=0; i= -1) && (x < windowWidth+2)) { m_xAxisTicks.Add(x); m_xAxisTickLabels.Add(wxString::Format(m_xAxisTickFormat.c_str(), current)); } current += m_xAxisTick_step; } } void wxPlotCtrl::CalcYAxisTickPositions() { double current = ceil(m_viewRect.GetTop() / m_yAxisTick_step) * m_yAxisTick_step; m_yAxisTicks.Clear(); m_yAxisTickLabels.Clear(); int i, y, windowWidth = GetPlotAreaRect().height; for (i=0; i= -1) && (y < windowWidth+2)) { m_yAxisTicks.Add(y); m_yAxisTickLabels.Add(wxString::Format(m_yAxisTickFormat.c_str(), current)); } current += m_yAxisTick_step; } } // ---------------------------------------------------------------------------- // Event processing // ---------------------------------------------------------------------------- void wxPlotCtrl::ProcessAreaEVT_MOUSE_EVENTS( wxMouseEvent &event ) { wxPoint& m_mousePt = m_area->m_mousePt; wxRect& m_mouseRect = m_area->m_mouseRect; wxPoint lastMousePt = m_mousePt; m_mousePt = event.GetPosition(); if (event.ButtonDown() && IsTextCtrlShown()) { HideTextCtrl(true, true); return; } if (GetGreedyFocus() && (FindFocus() != m_area)) m_area->SetFocus(); double plotX = GetPlotCoordFromClientX(m_mousePt.x), plotY = GetPlotCoordFromClientY(m_mousePt.y); wxClientDC dc(m_area); // Mouse motion if (lastMousePt != m_area->m_mousePt) { wxPlotEvent evt_motion(wxEVT_PLOT_MOUSE_MOTION, GetId(), this); evt_motion.SetPosition( plotX, plotY ); (void)DoSendEvent( evt_motion ); // Draw the crosshair cursor if (GetCrossHairCursor()) { if (!event.Entering() || m_area->HasCapture()) DrawCrosshairCursor( &dc, lastMousePt ); if (!event.Leaving() || m_area->HasCapture()) DrawCrosshairCursor( &dc, m_mousePt ); } } // Wheel scrolling up and down if (event.GetWheelRotation() != 0) { double dir = event.GetWheelRotation() > 0 ? 0.25 : -0.25; SetOrigin( m_viewRect.GetLeft(), m_viewRect.GetTop() + dir*m_viewRect.m_height, true); } int active_index = GetActiveIndex(); // Initial Left down selection if (event.LeftDown() || event.LeftDClick()) { if (FindFocus() != m_area) // fixme MSW focus problems m_area->SetFocus(); if (m_area_mouse_cursorid == wxCURSOR_HAND) SetAreaMouseCursor(CURSOR_GRAB); // send a click or doubleclick event wxPlotEvent click_event( event.ButtonDClick() ? wxEVT_PLOT_DOUBLECLICKED : wxEVT_PLOT_CLICKED, GetId(), this ); click_event.SetPosition( plotX, plotY ); (void)DoSendEvent( click_event ); if (!event.ButtonDClick()) m_mouseRect = wxRect(m_mousePt, wxSize(0, 0)); int data_index = -1; int curve_index = -1; wxPoint2DDouble dpt(2.0/m_zoom.m_x, 2.0/m_zoom.m_y); wxPoint2DDouble curvePt; if (FindCurve(wxPoint2DDouble(plotX, plotY), dpt, curve_index, data_index, &curvePt)) { wxPlotCurve *plotCurve = GetCurve(curve_index); wxPlotData *plotData = wxDynamicCast(plotCurve, wxPlotData); if (plotCurve) { wxPlotEvent pt_click_event( event.ButtonDClick() ? wxEVT_PLOT_POINT_DOUBLECLICKED : wxEVT_PLOT_POINT_CLICKED, GetId(), this ); pt_click_event.SetPosition( curvePt.m_x, curvePt.m_y ); pt_click_event.SetCurve( plotCurve, curve_index ); pt_click_event.SetCurveDataIndex(data_index); (void)DoSendEvent( pt_click_event ); // send curve selection switched event if (curve_index != GetActiveIndex()) SetActiveIndex( curve_index, true ); if (!event.LeftDClick() && (m_area_mouse_func == wxPLOT_MOUSE_SELECT)) { if (plotData) SelectDataRange(curve_index, wxRangeInt(data_index,data_index), true); else SelectXRange(curve_index, wxRangeDouble(curvePt.m_x,curvePt.m_x), true); } else if (!event.LeftDClick() && (m_area_mouse_func == wxPLOT_MOUSE_DESELECT)) { if (plotData) DeselectDataRange(curve_index, wxRangeInt(data_index,data_index), true); else DeselectXRange(curve_index, wxRangeDouble(curvePt.m_x,curvePt.m_x), true); } else { if (plotData) SetCursorDataIndex(curve_index, data_index, true); else SetCursorXPoint(curve_index, curvePt.m_x, true); } return; } } } // Finished marking rectangle or scrolling, perhaps else if (event.LeftUp()) { SetCaptureWindow(NULL); if (m_area_mouse_cursorid == CURSOR_GRAB) SetAreaMouseCursor(wxCURSOR_HAND); StopMouseTimer(); if (m_mouseRect == wxRect(0,0,0,0)) return; wxRect rightedRect = m_mouseRect; // rightedRect always goes from upper-left to lower-right // don't fix m_mouseRect since redrawing will be off if (rightedRect.width < 0) { rightedRect.x += rightedRect.width; rightedRect.width = -rightedRect.width; } if (rightedRect.height < 0) { rightedRect.y += rightedRect.height; rightedRect.height = -rightedRect.height; } // Zoom into image if (m_area_mouse_func == wxPLOT_MOUSE_ZOOM) { if ((m_area_mouse_marker == wxPLOT_MARKER_RECT) && ((rightedRect.width > 10) && (rightedRect.height > 10))) SetZoom( rightedRect, true ); else if ((m_area_mouse_marker == wxPLOT_MARKER_VERT) && (rightedRect.width > 10) ) SetZoom( wxRect(rightedRect.x, 0, rightedRect.width, m_areaClientRect.height), true ); else if ((m_area_mouse_marker == wxPLOT_MARKER_HORIZ) && (rightedRect.height > 10) ) SetZoom( wxRect(0, rightedRect.y, m_areaClientRect.width, rightedRect.height ), true ); else DrawMouseMarker( &dc, m_area_mouse_marker, m_mouseRect ); } // Select a range of points else if ((m_area_mouse_func == wxPLOT_MOUSE_SELECT) && (active_index >= 0)) { BeginBatch(); // if you select nothing, you don't get a refresh wxRect2DDouble plotRect = GetPlotRectFromClientRect(rightedRect); if ((m_area_mouse_marker == wxPLOT_MARKER_VERT) && (plotRect.m_width > 0)) SelectXRange(active_index, wxRangeDouble(plotRect.m_x, plotRect.GetRight()), true ); else if ((m_area_mouse_marker == wxPLOT_MARKER_HORIZ) && (plotRect.m_height > 0)) SelectYRange(active_index, wxRangeDouble(plotRect.m_y, plotRect.GetBottom()), true ); else if ((plotRect.m_width > 0) || (plotRect.m_height > 0)) SelectRectangle(active_index, plotRect, true ); m_mouseRect = wxRect(0,0,0,0); EndBatch(); } // Deselect a range of points else if ((m_area_mouse_func == wxPLOT_MOUSE_DESELECT) && (active_index >= 0)) { BeginBatch(); wxRect2DDouble plotRect = GetPlotRectFromClientRect(rightedRect); if ((m_area_mouse_marker == wxPLOT_MARKER_VERT) && (plotRect.m_width > 0)) DeselectXRange(active_index, wxRangeDouble(plotRect.m_x, plotRect.GetRight()), true ); else if ((m_area_mouse_marker == wxPLOT_MARKER_HORIZ) && (plotRect.m_height > 0)) DeselectYRange(active_index, wxRangeDouble(plotRect.m_y, plotRect.GetBottom()), true ); else if ((plotRect.m_width > 0) || (plotRect.m_height > 0)) DeselectRectangle(active_index, plotRect, true ); m_mouseRect = wxRect(0,0,0,0); EndBatch(); } // Nothing to do - erase the rect else { DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); } m_mouseRect = wxRect(0,0,0,0); return; } // Marking the rectangle or panning around else if ( event.LeftIsDown() && event.Dragging() ) { SetCaptureWindow(m_area); if (m_area_mouse_cursorid == wxCURSOR_HAND) SetAreaMouseCursor(CURSOR_GRAB); // Move the origin if (m_area_mouse_func == wxPLOT_MOUSE_PAN) { #if wxCHECK_VERSION(2,7,0) if (!m_areaClientRect.Contains(event.GetPosition())) #else if (!m_areaClientRect.Inside(event.GetPosition())) #endif { StartMouseTimer(ID_AREA_TIMER); } m_mouseRect = wxRect(0,0,0,0); // no marker double dx = m_mousePt.x - lastMousePt.x; double dy = m_mousePt.y - lastMousePt.y; SetOrigin(m_viewRect.GetLeft() - dx/m_zoom.m_x, m_viewRect.GetTop() + dy/m_zoom.m_y, true ); return; } else { if (m_mouseRect != wxRect(0,0,0,0)) DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); else m_mouseRect = wxRect(m_mousePt, wxSize(1, 1)); m_mouseRect.width = m_mousePt.x - m_mouseRect.x; m_mouseRect.height = m_mousePt.y - m_mouseRect.y; DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); } return; } return; } void wxPlotCtrl::ProcessAxisEVT_MOUSE_EVENTS( wxMouseEvent &event ) { if (event.ButtonDown() && IsTextCtrlShown()) { HideTextCtrl(true, true); return; } wxPoint pos = event.GetPosition(); wxPlotAxis *axisWin = (wxPlotAxis*)event.GetEventObject(); wxCHECK_RET(axisWin, wxT("Unknown window")); wxPoint& m_mousePt = axisWin->m_mousePt; if (event.LeftIsDown() && (axisWin != GetCaptureWindow())) { SetCaptureWindow(axisWin); m_mousePt = pos; return; } else if (!event.LeftIsDown()) { SetCaptureWindow(NULL); StopMouseTimer(); } else if (event.LeftIsDown()) { wxSize winSize = axisWin->GetSize(); if (( axisWin->IsXAxis() && ((pos.x < 0) || (pos.x > winSize.x))) || (!axisWin->IsXAxis() && ((pos.y < 0) || (pos.y > winSize.y))) ) { m_mousePt = pos; StartMouseTimer(axisWin->IsXAxis() ? ID_XAXIS_TIMER : ID_YAXIS_TIMER); } else if (IsTimerRunning()) m_mousePt = pos; } int wheel = event.GetWheelRotation(); if (wheel != 0) { wheel = wheel > 0 ? 1 : wheel < 0 ? -1 : 0; double dx = 0, dy = 0; if (axisWin->IsXAxis()) dx = wheel*m_viewRect.m_width/4.0; else dy = wheel*m_viewRect.m_height/4.0; SetOrigin(m_viewRect.GetLeft() + dx, m_viewRect.GetTop() + dy, true); } if ((!GetScrollOnThumbRelease() && event.LeftIsDown() && event.Dragging()) || (GetScrollOnThumbRelease() && event.LeftUp())) { double x = m_viewRect.GetLeft(); double y = m_viewRect.GetTop(); if (axisWin->IsXAxis()) x += (pos.x - m_mousePt.x)/m_zoom.m_x; else y += (m_mousePt.y-pos.y)/m_zoom.m_y; SetOrigin(x, y, true); } if (!GetScrollOnThumbRelease()) m_mousePt = pos; } void wxPlotCtrl::ProcessAreaEVT_KEY_DOWN( wxKeyEvent &event ) { //wxPrintf(wxT("wxPlotCtrl::ProcessAreaEVT_KEY_DOWN %d `%c` S%dC%dA%d\n"), int(event.GetKeyCode()), (wxChar)event.GetKeyCode(), event.ShiftDown(), event.ControlDown(), event.AltDown()); event.Skip(true); int code = event.GetKeyCode(); bool alt = event.AltDown() || (code == WXK_ALT); bool ctrl = event.ControlDown() || (code == WXK_CONTROL); bool shift = event.ShiftDown() || (code == WXK_SHIFT); if (shift && !alt && !ctrl) SetAreaMouseFunction(wxPLOT_MOUSE_SELECT, true); else if (!shift && ctrl && !alt) SetAreaMouseFunction(wxPLOT_MOUSE_DESELECT, true); else if (ctrl && shift && alt) SetAreaMouseFunction(wxPLOT_MOUSE_PAN, true); else // if (!ctrl || !shift || !alt) SetAreaMouseFunction(wxPLOT_MOUSE_ZOOM, true); } void wxPlotCtrl::ProcessAreaEVT_KEY_UP( wxKeyEvent &event ) { //wxPrintf(wxT("wxPlotCtrl::ProcessAreaEVT_KEY_UP %d `%c` S%dC%dA%d\n"), int(event.GetKeyCode()), (wxChar)event.GetKeyCode(), event.ShiftDown(), event.ControlDown(), event.AltDown()); event.Skip(true); int code = event.GetKeyCode(); bool alt = event.AltDown() && (code != WXK_ALT); bool ctrl = event.ControlDown() && (code != WXK_CONTROL); bool shift = event.ShiftDown() && (code != WXK_SHIFT); if (shift && !ctrl && !alt) SetAreaMouseFunction(wxPLOT_MOUSE_SELECT, true); else if (!shift && ctrl && !alt) SetAreaMouseFunction(wxPLOT_MOUSE_DESELECT, true); else if (shift && ctrl && alt) SetAreaMouseFunction(wxPLOT_MOUSE_PAN, true); else // if (!shift && !ctrl && !alt) SetAreaMouseFunction(wxPLOT_MOUSE_ZOOM, true); } void wxPlotCtrl::OnChar(wxKeyEvent &event) { //wxPrintf(wxT("wxPlotCtrl::OnChar %d `%c` S%dC%dA%d\n"), int(event.GetKeyCode()), (wxChar)event.GetKeyCode(), event.ShiftDown(), event.ControlDown(), event.AltDown()); // select the next curve if possible, or cursor point like left mouse if (event.GetKeyCode() == WXK_SPACE) { if (event.ShiftDown() || event.ControlDown()) { if (IsCursorValid()) { if (GetDataCurve(m_cursor_curve)) DoSelectDataRange(m_cursor_curve, wxRangeInt(m_cursor_index,m_cursor_index), !event.ControlDown(), true); else { wxPoint2DDouble pt(m_cursorMarker.GetPlotPosition()); DoSelectRectangle(m_cursor_curve, wxRect2DDouble(pt.m_x,0,pt.m_x,0), !event.ControlDown(), true); } } } else { int count = GetCurveCount(); if ((count < 1) || ((count == 1) && (m_active_index == 0))) return; int index = (m_active_index + 1 > count - 1) ? 0 : m_active_index + 1; SetActiveIndex( index, true ); } return; } // These are reserved for the program if (event.ControlDown() || event.AltDown()) { event.Skip(true); return; } switch (event.GetKeyCode()) { // cursor keys moves the plot origin around case WXK_LEFT : SetOrigin(m_viewRect.GetLeft() - m_viewRect.m_width/10.0, m_viewRect.GetTop()); return; case WXK_RIGHT : SetOrigin(m_viewRect.GetLeft() + m_viewRect.m_width/10.0, m_viewRect.GetTop()); return; case WXK_UP : SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() + m_viewRect.m_height/10.0); return; case WXK_DOWN : SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() - m_viewRect.m_height/10.0); return; case WXK_PRIOR : SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() + m_viewRect.m_height/2.0); return; case WXK_NEXT : SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() - m_viewRect.m_height/2.0); return; // Center the plot on the cursor point, or 0,0 case WXK_HOME : { if (IsCursorValid()) MakeCursorVisible(true, true); else SetOrigin(-m_viewRect.m_width/2.0, -m_viewRect.m_height/2.0, true); return; } // try to make the current curve fully visible case WXK_END : { wxPlotData *plotData = GetActiveDataCurve(); if (plotData) { wxRect2DDouble bound = plotData->GetBoundingRect(); bound.Inset(-bound.m_width/80.0, -bound.m_height/80.0); SetViewRect(bound, true); } else if (GetActiveCurve()) { wxPlotCurve *curve = GetActiveCurve(); double y, min, max; y = max = min = curve->GetY(GetPlotCoordFromClientX(0)); for (int i=1; iGetY(GetPlotCoordFromClientX(i)); if (wxFinite(y) != 0) { if (y > max) max = y; if (y < min) min = y; } } if (max == min) { min -= 5; max += 5; } wxRect2DDouble bound(m_viewRect.m_x, min, m_viewRect.m_width, max-min); SetViewRect(bound, true); } return; } // zoom in and out case wxT('a'): SetZoom( wxPoint2DDouble(m_zoom.m_x/1.5, m_zoom.m_y ), true ); return; case wxT('d'): SetZoom( wxPoint2DDouble(m_zoom.m_x*1.5, m_zoom.m_y ), true ); return; case wxT('w'): SetZoom( wxPoint2DDouble(m_zoom.m_x, m_zoom.m_y*1.5), true ); return; case wxT('x'): SetZoom( wxPoint2DDouble(m_zoom.m_x, m_zoom.m_y/1.5), true ); return; case wxT('q'): SetZoom( wxPoint2DDouble(m_zoom.m_x/1.5, m_zoom.m_y*1.5), true ); return; case wxT('e'): SetZoom( wxPoint2DDouble(m_zoom.m_x*1.5, m_zoom.m_y*1.5), true ); return; case wxT('z'): SetZoom( wxPoint2DDouble(m_zoom.m_x/1.5, m_zoom.m_y/1.5), true ); return; case wxT('c'): SetZoom( wxPoint2DDouble(m_zoom.m_x*1.5, m_zoom.m_y/1.5), true ); return; case wxT('s'): MakeCurveVisible(GetActiveIndex(), true); break; // Select previous/next point in a curve case wxT('<'): case wxT(','): { double x = GetPlotCoordFromClientX(m_areaClientRect.width-1); wxPlotData *plotData = GetActiveDataCurve(); if (plotData) { if (!IsCursorValid()) SetCursorDataIndex(m_active_index, plotData->GetIndexFromX(x, wxPlotData::index_floor), true); else if (m_cursor_index > 0) SetCursorDataIndex(m_cursor_curve, m_cursor_index-1, true); } else if (m_active_index >= 0) { if (!IsCursorValid()) SetCursorXPoint(m_active_index, x, true); else { x = GetPlotCoordFromClientX((GetClientCoordFromPlotX(m_cursorMarker.GetPlotRect().m_x)-1)); SetCursorXPoint(m_cursor_curve, x, true); } } MakeCursorVisible(false, true); return; } case wxT('>'): case wxT('.'): { double x = GetPlotCoordFromClientX(0); wxPlotData *plotData = GetActiveDataCurve(); if (plotData) { int count = plotData->GetCount(); if (!IsCursorValid()) SetCursorDataIndex(m_active_index, plotData->GetIndexFromX(x, wxPlotData::index_ceil), true); else if (m_cursor_index < count - 1) SetCursorDataIndex(m_cursor_curve, m_cursor_index+1, true); } else if (m_active_index >= 0) { if (!IsCursorValid()) SetCursorXPoint(m_active_index, x, true); else { x = GetPlotCoordFromClientX((GetClientCoordFromPlotX(m_cursorMarker.GetPlotRect().m_x)+1)); SetCursorXPoint(m_cursor_curve, x, true); } } MakeCursorVisible(false, true); return; } // go to the last or next zoom case wxT('[') : NextHistoryView(false, true); return; case wxT(']') : NextHistoryView(true, true); return; // delete the selected curve case WXK_DELETE: { if (m_activeCurve) DeleteCurve(m_activeCurve, true); return; } // delete current selection or go to next curve and delete it's selection // finally invalidate cursor case WXK_ESCAPE : { BeginBatch(); if ((m_active_index >= 0) && (GetSelectedRangeCount(m_active_index) > 0)) { ClearSelectedRanges(m_active_index, true); } else { bool has_cleared = false; for (int i=0; i 0) { ClearSelectedRanges(i, true); has_cleared = true; break; } } if (!has_cleared) { if (IsCursorValid()) InvalidateCursor(true); else if (m_active_index > -1) SetActiveIndex( -1, true ); } } EndBatch(); // ESC is also a generic clean up routine too! break; } default: event.Skip(true); break; } } void wxPlotCtrl::UpdateWindowSize() { m_areaClientRect = wxRect(wxPoint(0,0), m_area->GetClientSize()); // If something happens to make these true, there's a problem if (m_areaClientRect.width < 10) m_areaClientRect.width = 10; if (m_areaClientRect.height < 10) m_areaClientRect.height = 10; } void wxPlotCtrl::AdjustScrollBars() { double range, thumbsize, position; double pagesize; range = (m_curveBoundingRect.m_width * m_zoom.m_x); if (!IsFinite(range, wxT("plot's x range is NaN"))) return; if (range > 32000) range = 32000; else if (range < 1) range = 1; thumbsize = (range * (m_viewRect.m_width/m_curveBoundingRect.m_width)); if (!IsFinite(thumbsize, wxT("plot's x range is NaN"))) return; if (thumbsize > range) thumbsize = range; else if (thumbsize < 1) thumbsize = 1; position = (range * ((m_viewRect.GetLeft() - m_curveBoundingRect.GetLeft())/m_curveBoundingRect.m_width)); if (!IsFinite(position, wxT("plot's x range is NaN"))) return; if (position > range - thumbsize) position = range - thumbsize; else if (position < 0) position = 0; pagesize = thumbsize; m_xAxisScrollbar->SetScrollbar( int(position), int(thumbsize), int(range), int(pagesize) ); range = (m_curveBoundingRect.m_height * m_zoom.m_y); if (!IsFinite(range, wxT("plot's y range is NaN"))) return; if (range > 32000) range = 32000; else if (range < 1) range = 1; thumbsize = (range * (m_viewRect.m_height/m_curveBoundingRect.m_height)); if (!IsFinite(thumbsize, wxT("plot's x range is NaN"))) return; if (thumbsize > range) thumbsize = range; else if (thumbsize < 1) thumbsize = 1; position = (range - range * ((m_viewRect.GetTop() - m_curveBoundingRect.GetTop())/m_curveBoundingRect.m_height) - thumbsize); if (!IsFinite(position, wxT("plot's x range is NaN"))) return; if (position > range - thumbsize) position = range - thumbsize; else if (position < 0) position = 0; pagesize = thumbsize; m_yAxisScrollbar->SetScrollbar( int(position), int(thumbsize), int(range), int(pagesize) ); } void wxPlotCtrl::OnScroll(wxScrollEvent& event) { if (m_scroll_on_thumb_release && (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)) return; if (event.GetId() == wxPlotCtrl::ID_PLOTCTRL_X_SCROLLBAR) { double range = m_xAxisScrollbar->GetRange(); if (range < 1) return; double position = m_xAxisScrollbar->GetThumbPosition(); double origin_x = m_curveBoundingRect.GetLeft() + m_curveBoundingRect.m_width*(position/range); if (!IsFinite(origin_x, wxT("plot's x-origin is NaN"))) return; m_viewRect.m_x = origin_x; Redraw(wxPLOT_REDRAW_PLOT|wxPLOT_REDRAW_XAXIS); } else if (event.GetId() == wxPlotCtrl::ID_PLOTCTRL_Y_SCROLLBAR) { double range = m_yAxisScrollbar->GetRange(); if (range < 1) return; double position = m_yAxisScrollbar->GetThumbPosition(); double thumbsize = m_yAxisScrollbar->GetThumbSize(); double origin_y = m_curveBoundingRect.GetTop() + m_curveBoundingRect.m_height*((range-position-thumbsize)/range); if (!IsFinite(origin_y, wxT("plot's y-origin is NaN"))) return; m_viewRect.m_y = origin_y; Redraw(wxPLOT_REDRAW_PLOT|wxPLOT_REDRAW_YAXIS); } } bool wxPlotCtrl::IsFinite(double n, const wxString &msg) const { if (!wxFinite(n)) { if (!msg.IsEmpty()) { wxPlotEvent event(wxEVT_PLOT_ERROR, GetId(), (wxPlotCtrl*)this); event.SetString(msg); (void)DoSendEvent( event ); } return false; } return true; } bool wxPlotCtrl::FindCurve(const wxPoint2DDouble &pt, const wxPoint2DDouble &dpt, int &curve_index, int &data_index, wxPoint2DDouble *curvePt) const { curve_index = data_index = -1; if (!IsFinite(pt.m_x, wxT("point is not finite"))) return false; if (!IsFinite(pt.m_y, wxT("point is not finite"))) return false; if (!IsFinite(dpt.m_x, wxT("point is not finite"))) return false; if (!IsFinite(dpt.m_y, wxT("point is not finite"))) return false; int curve_count = GetCurveCount(); if (curve_count < 1) return false; for (int n=-1; n= 0) n = m_active_index; else n = 0; } else if (n == m_active_index) continue; wxPlotCurve *plotCurve = GetCurve(n); wxPlotData *plotData = wxDynamicCast(plotCurve, wxPlotData); // find the index of the closest point in a wxPlotData curve if (plotData) { // check if curve has BoundingRect wxRect2DDouble rect = plotData->GetBoundingRect(); if ( ((rect.m_width > 0) && ((pt.m_x+dpt.m_x < rect.GetLeft()) || (pt.m_x-dpt.m_x > rect.GetRight()))) || ((rect.m_height > 0) && ((pt.m_y+dpt.m_y < rect.GetTop()) || (pt.m_y-dpt.m_y > rect.GetBottom()))) ) { if ((n == m_active_index) && (n > 0)) n = -1; // start back at 0 continue; } int index = plotData->GetIndexFromXY(pt.m_x, pt.m_y, dpt.m_x); double x = plotData->GetXValue(index); double y = plotData->GetYValue(index); if ((fabs(x-pt.m_x) <= dpt.m_x) && (fabs(y-pt.m_y) <= dpt.m_y)) { curve_index = n; data_index = index; if (curvePt) *curvePt = wxPoint2DDouble(x, y); return true; } } else // not a data curve, just find y at this x pos { wxRect2DDouble rect = plotCurve->GetBoundingRect(); if ((rect.m_width <= 0) || ((pt.m_x+dpt.m_x >= rect.GetLeft()) && (pt.m_x-dpt.m_x <= rect.GetRight()))) { if ((rect.m_height <= 0) || ((pt.m_y >= rect.GetTop()) && (pt.m_y-dpt.m_y <= rect.GetBottom()))) { double y = plotCurve->GetY(pt.m_x); if (fabs(y - pt.m_y) <= dpt.m_y) { curve_index = n; if (curvePt) *curvePt = wxPoint2DDouble(pt.m_x, y); return true; } } } } // continue searching through curves // if on the current then start back at the beginning if not already at 0 if ((n == m_active_index) && (n > 0)) n = -1; } return false; } bool wxPlotCtrl::DoSendEvent(wxPlotEvent &event) const { /* if (event.GetEventType() != wxEVT_PLOT_MOUSE_MOTION) { wxLogDebug(wxT("wxPlotEvent '%s' CurveIndex: %d, DataIndex: %d, Pos: %lf %lf, MouseFn %d"), GetEventName(event).c_str(), event.GetCurveIndex(), event.GetCurveDataIndex(), event.GetX(), event.GetY(), event.GetMouseFunction()); } */ return !GetEventHandler()->ProcessEvent(event) || event.IsAllowed(); } void wxPlotCtrl::StartMouseTimer(wxWindowID win_id) { #if wxCHECK_VERSION(2,5,0) if (m_timer && (m_timer->GetId() != win_id)) StopMouseTimer(); #else StopMouseTimer(); // always stop it I guess #endif // wxCHECK_VERSION(2,5,0) if (!m_timer) m_timer = new wxTimer(this, win_id); if (!m_timer->IsRunning()) m_timer->Start(200, true); // one shot timer } void wxPlotCtrl::StopMouseTimer() { if (m_timer) { if (m_timer->IsRunning()) m_timer->Stop(); delete m_timer; m_timer = NULL; } } bool wxPlotCtrl::IsTimerRunning() { return (m_timer && m_timer->IsRunning()); } void wxPlotCtrl::OnTimer( wxTimerEvent &event ) { wxPoint mousePt; switch (event.GetId()) { case ID_AREA_TIMER : mousePt = m_area->m_mousePt; break; case ID_XAXIS_TIMER : mousePt = m_xAxis->m_mousePt; break; case ID_YAXIS_TIMER : mousePt = m_yAxis->m_mousePt; break; default : { event.Skip(); // someone else's timer? return; } } double dx = (mousePt.x<0) ? -20 : (mousePt.x>GetPlotAreaRect().width ) ? 20 : 0; double dy = (mousePt.y<0) ? 20 : (mousePt.y>GetPlotAreaRect().height) ? -20 : 0; dx /= m_zoom.m_x; dy /= m_zoom.m_y; if (((dx == 0) && (dy == 0)) || !SetOrigin(GetViewRect().GetLeft() + dx, GetViewRect().GetTop() + dy, true) ) { StopMouseTimer(); } else StartMouseTimer(event.GetId()); // restart timer for another round } void wxPlotCtrl::SetCaptureWindow(wxWindow *win) { if (m_winCapture && (m_winCapture != win) && m_winCapture->HasCapture()) m_winCapture->ReleaseMouse(); m_winCapture = win; if (m_winCapture && (!m_winCapture->HasCapture())) m_winCapture->CaptureMouse(); } gambit-0.2010.09.01/src/labenski/src/plotcurv.cpp0000644000076500007650000002237111350032206016165 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotcurv.cpp // Purpose: wxPlotCurve for wxPlotCtrl // Author: John Labenski // Modified by: // Created: 12/01/2000 // Copyright: (c) John Labenski // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "plotcurv.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/bitmap.h" #include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/plotctrl/plotcurv.h" const wxRect2DDouble wxNullPlotBounds(0, 0, 0, 0); #ifdef USE_BITMAPS_FOR_DRAWING /* XPM */ static const char *normal_symbol_xpm_data[] = { /* columns rows colors chars-per-pixel */ "5 5 2 1", " c None", "b c #000000", /* pixels */ " bbb ", "b b", "b b", "b b", " bbb " }; static const char *active_symbol_xpm_data[] = { /* columns rows colors chars-per-pixel */ "5 5 2 1", " c None", "b c #0000FF", /* pixels */ " bbb ", "b b", "b b", "b b", " bbb " }; static const char *selected_symbol_xpm_data[] = { /* columns rows colors chars-per-pixel */ "5 5 2 1", " c None", "b c #FF0000", /* pixels */ " bbb ", "b b", "b b", "b b", " bbb " }; #endif // USE_BITMAPS_FOR DRAWING // Can't load these now since wxWindows must initialize first wxBitmap wxPlotSymbolNormal; wxBitmap wxPlotSymbolActive; wxBitmap wxPlotSymbolSelected; //---------------------------------------------------------------------------- // Interpolate //---------------------------------------------------------------------------- double LinearInterpolateX(double x0, double y0, double x1, double y1, double y) { //wxCHECK_MSG( (y1 - y0) != 0.0, 0.0, wxT("Divide by zero, LinearInterpolateX()") ); return ( (y - y0)*(x1 - x0)/(y1 - y0) + x0 ); } double LinearInterpolateY(double x0, double y0, double x1, double y1, double x) { //wxCHECK_MSG( (x1 - x0) != 0.0, 0.0, wxT("Divide by zero, LinearInterpolateY()") ); double m = (y1 - y0) / (x1 - x0); return (m*x + (y0 - m*x0)); } //---------------------------------------------------------------------------- // wxPlotCurveRefData //---------------------------------------------------------------------------- wxArrayGenericPen wxPlotCurveRefData::sm_defaultPens; void InitPlotCurveDefaultPens() { static bool s_init_default_pens = false; if (!s_init_default_pens) { s_init_default_pens = true; wxPlotCurveRefData::sm_defaultPens.Add(wxGenericPen( wxGenericColour( 0, 0, 0), 1, wxSOLID )); wxPlotCurveRefData::sm_defaultPens.Add(wxGenericPen( wxGenericColour( 0, 0, 255), 1, wxSOLID )); wxPlotCurveRefData::sm_defaultPens.Add(wxGenericPen( wxGenericColour(255, 0, 0), 1, wxSOLID )); } } wxPlotCurveRefData::wxPlotCurveRefData() : wxObjectRefData() { InitPlotCurveDefaultPens(); m_pens = sm_defaultPens; } wxPlotCurveRefData::wxPlotCurveRefData(const wxPlotCurveRefData& data) :wxObjectRefData() { Copy(data); } void wxPlotCurveRefData::Copy(const wxPlotCurveRefData &source) { m_boundingRect = source.m_boundingRect; m_pens = source.m_pens; m_optionNames = source.m_optionNames; m_optionValues = source.m_optionValues; } #define M_PLOTCURVEDATA ((wxPlotCurveRefData*)m_refData) //----------------------------------------------------------------------------- // wxPlotCurve //----------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxPlotCurve, wxObject); wxObjectRefData *wxPlotCurve::CreateRefData() const { return new wxPlotCurveRefData; } wxObjectRefData *wxPlotCurve::CloneRefData(const wxObjectRefData *data) const { return new wxPlotCurveRefData(*(const wxPlotCurveRefData *)data); } wxPlotCurve::wxPlotCurve() : wxObject() { // Note: You must do this in your constructor in order to use the the curve // m_refData = new wxPlotCurveRefData (or wxMySubclassedPlotCurveRefData) } bool wxPlotCurve::Ok() const { return (M_PLOTCURVEDATA != NULL); } wxRect2DDouble wxPlotCurve::GetBoundingRect() const { wxCHECK_MSG(Ok(), wxRect2DDouble(0,0,0,0), wxT("invalid plotcurve")); return M_PLOTCURVEDATA->m_boundingRect; } void wxPlotCurve::SetBoundingRect( const wxRect2DDouble &rect ) { wxCHECK_RET(Ok(), wxT("invalid plotcurve")); M_PLOTCURVEDATA->m_boundingRect = rect; } //---------------------------------------------------------------------------- // Get/Set Pen //---------------------------------------------------------------------------- wxGenericPen wxPlotCurve::GetPen(wxPlotPen_Type colour_type) const { wxCHECK_MSG(Ok(), wxGenericPen(), wxT("invalid plotcurve")); wxCHECK_MSG((colour_type >= 0) && (colour_type < (int)M_PLOTCURVEDATA->m_pens.GetCount()), wxGenericPen(), wxT("invalid plot colour")); return M_PLOTCURVEDATA->m_pens[colour_type]; } void wxPlotCurve::SetPen(wxPlotPen_Type colour_type, const wxGenericPen &pen ) { wxCHECK_RET(Ok(), wxT("invalid plotcurve")); wxCHECK_RET((colour_type >= 0) && (colour_type < (int)M_PLOTCURVEDATA->m_pens.GetCount()), wxT("invalid plot colour")); M_PLOTCURVEDATA->m_pens[colour_type] = pen; } wxGenericPen wxPlotCurve::GetDefaultPen(wxPlotPen_Type colour_type) { InitPlotCurveDefaultPens(); wxCHECK_MSG((colour_type >= 0) && (colour_type < int(wxPlotCurveRefData::sm_defaultPens.GetCount())), wxGenericPen(), wxT("invalid plot colour")); return wxPlotCurveRefData::sm_defaultPens[colour_type]; } void wxPlotCurve::SetDefaultPen(wxPlotPen_Type colour_type, const wxGenericPen &pen ) { InitPlotCurveDefaultPens(); wxCHECK_RET((colour_type >= 0) && (colour_type < int(wxPlotCurveRefData::sm_defaultPens.GetCount())), wxT("invalid plot colour")); wxPlotCurveRefData::sm_defaultPens[colour_type] = pen; } // ---------------------------------------------------------------------------- // Get/Set Option names/values // ---------------------------------------------------------------------------- size_t wxPlotCurve::GetOptionCount() const { wxCHECK_MSG(M_PLOTCURVEDATA, 0, wxT("invalid plotcurve")); return M_PLOTCURVEDATA->m_optionNames.GetCount(); } int wxPlotCurve::HasOption(const wxString& name) const { wxCHECK_MSG(M_PLOTCURVEDATA, wxNOT_FOUND, wxT("invalid plotcurve")); return M_PLOTCURVEDATA->m_optionNames.Index(name); } wxString wxPlotCurve::GetOptionName( size_t i ) const { wxCHECK_MSG(M_PLOTCURVEDATA&&(im_optionNames[i]; } wxString wxPlotCurve::GetOptionValue( size_t i ) const { wxCHECK_MSG(M_PLOTCURVEDATA&&(im_optionValues[i]; } int wxPlotCurve::SetOption(const wxString& name, const wxString& value, bool update) { wxCHECK_MSG(M_PLOTCURVEDATA, -1, wxT("invalid plotcurve")); int n = M_PLOTCURVEDATA->m_optionNames.Index(name); if (n == wxNOT_FOUND) { n = M_PLOTCURVEDATA->m_optionNames.Add(name); M_PLOTCURVEDATA->m_optionValues.Insert(value, n); } else if (update) { M_PLOTCURVEDATA->m_optionNames[n] = name; M_PLOTCURVEDATA->m_optionValues[n] = value; } return n; } int wxPlotCurve::SetOption(const wxString &name, int option, bool update) { return SetOption(name, wxString::Format(wxT("%d"), option), update); } wxString wxPlotCurve::GetOption(const wxString& name) const { wxCHECK_MSG(M_PLOTCURVEDATA, wxEmptyString, wxT("invalid plotcurve")); int n = M_PLOTCURVEDATA->m_optionNames.Index(name); if (n == wxNOT_FOUND) return wxEmptyString; return M_PLOTCURVEDATA->m_optionValues[n]; } int wxPlotCurve::GetOption(const wxString& name, wxString &value ) const { wxCHECK_MSG(M_PLOTCURVEDATA, wxNOT_FOUND, wxT("invalid plotcurve")); int n = M_PLOTCURVEDATA->m_optionNames.Index(name); if (n == wxNOT_FOUND) return wxNOT_FOUND; value = M_PLOTCURVEDATA->m_optionValues[n]; return n; } int wxPlotCurve::GetOptionInt(const wxString& name) const { wxCHECK_MSG(M_PLOTCURVEDATA, 0, wxT("invalid plotcurve")); return wxAtoi(GetOption(name)); } wxArrayString wxPlotCurve::GetOptionNames() const { wxCHECK_MSG(M_PLOTCURVEDATA, wxArrayString(), wxT("invalid plotcurve")); return M_PLOTCURVEDATA->m_optionNames; } wxArrayString wxPlotCurve::GetOptionValues() const { wxCHECK_MSG(M_PLOTCURVEDATA, wxArrayString(), wxT("invalid plotcurve")); return M_PLOTCURVEDATA->m_optionValues; } //------------------------------------------------------------------------- void wxPlotCurve::SetClientObject( wxClientData *data ) { wxCHECK_RET(M_PLOTCURVEDATA, wxT("invalid plotcurve")); M_PLOTCURVEDATA->SetClientObject(data); } wxClientData *wxPlotCurve::GetClientObject() const { wxCHECK_MSG(M_PLOTCURVEDATA, NULL, wxT("invalid plotcurve")); return M_PLOTCURVEDATA->GetClientObject(); } void wxPlotCurve::SetClientData( void *data ) { wxCHECK_RET(M_PLOTCURVEDATA, wxT("invalid plotcurve")); M_PLOTCURVEDATA->SetClientData(data); } void *wxPlotCurve::GetClientData() const { wxCHECK_MSG(M_PLOTCURVEDATA, NULL, wxT("invalid plotcurve")); return M_PLOTCURVEDATA->GetClientData(); } gambit-0.2010.09.01/src/labenski/src/plotdata.cpp0000644000076500007650000026032611350032206016123 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotdata.cpp // Purpose: wxPlotData container class for wxPlotCtrl // Author: John Labenski // Modified by: // Created: 12/01/2000 // Copyright: (c) John Labenski // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "plotdata.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/bitmap.h" #include "wx/textdlg.h" #include "wx/msgdlg.h" #include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/file.h" #include "wx/wfstream.h" #include "wx/textfile.h" #include "wx/math.h" #include "wx/plotctrl/plotdata.h" #include "wx/plotctrl/fourier.h" #include "wx/wxthings/medsort.h" #include "wx/wxthings/range.h" #include #define wxPLOT_MAX_DATA_COLUMNS 64 #define CHECK_INDEX_COUNT_MSG(index, count, max_count, ret) \ wxCHECK_MSG((int(index) >= 0) && (int(index)+int(count) <= int(max_count)), ret, wxT("invalid index or count")) #define CHECK_INDEX_COUNT_RET(index, count, max_count) \ wxCHECK_RET((int(index) >= 0) && (int(index)+int(count) <= int(max_count)), wxT("invalid index or count")) #define CHECK_START_END_INDEX_MSG(start_index, end_index, max_count, ret) \ wxCHECK_MSG((int(start_index)>=0)&&(int(start_index)int(start_index))&&(int(end_index)=0)&&(int(start_index)int(start_index))&&(int(end_index)m_count > 0); } void wxPlotData::Destroy() { UnRef(); } int wxPlotData::GetCount() const { wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); return M_PLOTDATA->m_count; } bool wxPlotData::Create( const wxPlotData& plotData ) { wxCHECK_MSG(plotData.Ok(), false, wxT("Invalid wxPlotData")); Ref(plotData); CalcBoundingRect(); // just to be sure we're ok return true; } bool wxPlotData::Create( const wxPlotFunction &plotFunc, double x_start, double dx, int points ) { wxCHECK_MSG(plotFunc.Ok(), false, wxT("Invalid wxPlotFunction")); wxCHECK_MSG(wxFinite(x_start) && wxFinite(dx), false, wxT("values are NaN")); if (!Create(points, false)) return false; // this checks points double x = x_start, y = 0; double *x_data = M_PLOTDATA->m_Xdata; double *y_data = M_PLOTDATA->m_Ydata; wxPlotFunction pf = plotFunc; // since it's passed as const for (int i = 0; i < points; i++, x += dx, x_data++, y_data++) { if (wxFinite(x)) { y = pf.GetY(x); *x_data = x; *y_data = wxFinite(y) ? y : 0; } else { *x_data = 0; *y_data = 0; } } CalcBoundingRect(); return true; } bool wxPlotData::Create( int points, bool zero ) { wxCHECK_MSG( points > 0, false, wxT("Can't create wxPlotData with < 1 points") ); UnRef(); m_refData = new wxPlotDataRefData(); if ( !M_PLOTDATA ) { wxFAIL_MSG(wxT("memory allocation error creating plot")); return false; } M_PLOTDATA->m_count = points; M_PLOTDATA->m_Xdata = (double*)malloc( points*sizeof(double) ); M_PLOTDATA->m_Ydata = (double*)malloc( points*sizeof(double) ); if (!M_PLOTDATA->m_Xdata || !M_PLOTDATA->m_Ydata) { UnRef(); wxFAIL_MSG(wxT("memory allocation error creating plot")); return false; } if (zero) { memset(M_PLOTDATA->m_Xdata, 0, points*sizeof(double)); memset(M_PLOTDATA->m_Ydata, 0, points*sizeof(double)); } return true; } bool wxPlotData::Create( double *x_data, double *y_data, int points, bool static_data ) { wxCHECK_MSG((points > 0) && x_data && y_data, false, wxT("Can't create wxPlotData with < 1 points or invalid data") ); UnRef(); m_refData = new wxPlotDataRefData(); if ( !M_PLOTDATA ) { wxFAIL_MSG(wxT("memory allocation error creating plot")); return false; } M_PLOTDATA->m_Xdata = x_data; M_PLOTDATA->m_Ydata = y_data; M_PLOTDATA->m_count = points; M_PLOTDATA->m_static = static_data; CalcBoundingRect(); return true; } bool wxPlotData::Copy( const wxPlotData &source, bool copy_all ) { wxCHECK_MSG( source.Ok(), false, wxT("Invalid wxPlotData") ); int count = source.GetCount(); if (!Create(count, false)) return false; memcpy( M_PLOTDATA->m_Xdata, source.GetXData(), count*sizeof(double) ); memcpy( M_PLOTDATA->m_Ydata, source.GetYData(), count*sizeof(double) ); if (source.GetYiData()) { M_PLOTDATA->m_Yidata = (double*)malloc(count*sizeof(double)); if (!M_PLOTDATA->m_Yidata) { UnRef(); return false; } memcpy( M_PLOTDATA->m_Yidata, source.GetYiData(), count*sizeof(double) ); } if (copy_all) CopyExtra(source); CalcBoundingRect(); return true; } bool wxPlotData::CopyExtra( const wxPlotData &source ) { wxCHECK_MSG( Ok() && source.Ok(), false, wxT("Invalid wxPlotData") ); M_PLOTDATA->Copy(*((wxPlotDataRefData*)source.GetRefData())); return true; } bool wxPlotData::Resize( int new_size, bool zero ) { wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); wxCHECK_MSG(new_size > 0, false, wxT("Can't create wxPlotData with < 1 points")); if (M_PLOTDATA->m_count == new_size) return true; M_PLOTDATA->m_Xdata = (double*)realloc( M_PLOTDATA->m_Xdata, new_size*sizeof(double) ); M_PLOTDATA->m_Ydata = (double*)realloc( M_PLOTDATA->m_Ydata, new_size*sizeof(double) ); bool has_yi = false; if (M_PLOTDATA->m_Yidata) { has_yi = true; M_PLOTDATA->m_Yidata = (double*)realloc( M_PLOTDATA->m_Yidata, new_size*sizeof(double) ); } // realloc failed if (!M_PLOTDATA->m_Xdata || !M_PLOTDATA->m_Ydata || (has_yi && (!M_PLOTDATA->m_Yidata))) { UnRef(); return false; } if (zero && (M_PLOTDATA->m_count < new_size )) { int old_count = M_PLOTDATA->m_count; int points = new_size - M_PLOTDATA->m_count; memset(M_PLOTDATA->m_Xdata + old_count, 0, points*sizeof(double)); memset(M_PLOTDATA->m_Ydata + old_count, 0, points*sizeof(double)); if (M_PLOTDATA->m_Yidata) memset(M_PLOTDATA->m_Yidata + old_count, 0, points*sizeof(double)); } M_PLOTDATA->m_count = new_size; CalcBoundingRect(); return true; } bool wxPlotData::Resize( int new_size, double dx, double y ) { wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); int orig_count = GetCount(); if (!Resize(new_size, false)) return false; SetYValues(orig_count, -1, y); SetXStepValues(orig_count, -1, M_PLOTDATA->m_Xdata[orig_count - 1], dx); return true; } wxPlotData wxPlotData::Append( const wxPlotData &source ) const { wxCHECK_MSG( Ok() && source.Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); int count = M_PLOTDATA->m_count; int src_count = source.GetCount(); wxPlotData newCurve(count + src_count, false); if (!newCurve.Ok()) return newCurve; bool has_yi = false; if (M_PLOTDATA->m_Yidata && source.GetYiData()) { has_yi = true; double *yi = (double*)malloc((count+src_count)*sizeof(double)); if (!yi) { newCurve.Destroy(); return newCurve; } newCurve.SetYiData(yi); } memcpy(newCurve.GetXData(), M_PLOTDATA->m_Xdata, count*sizeof(double)); memcpy(newCurve.GetYData(), M_PLOTDATA->m_Ydata, count*sizeof(double)); if (has_yi) memcpy(newCurve.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); memcpy(newCurve.GetXData()+count, source.GetXData(), src_count*sizeof(double)); memcpy(newCurve.GetYData()+count, source.GetYData(), src_count*sizeof(double)); if (has_yi) memcpy(newCurve.GetYiData(), source.GetYiData(), src_count*sizeof(double)); newCurve.CalcBoundingRect(); newCurve.CopyExtra( *this ); return newCurve; } wxPlotData wxPlotData::Insert( const wxPlotData &source, int index ) const { wxCHECK_MSG( Ok() && source.Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); wxPCHECK_MINMAX_MSG(index, 0, M_PLOTDATA->m_count, wxPlotData(), wxT("invalid index")); int count = M_PLOTDATA->m_count; int src_count = source.GetCount(); wxPlotData newCurve(count + src_count, false); if (!newCurve.Ok()) return newCurve; double *src_x_data = source.GetXData(); double *src_y_data = source.GetYData(); double *src_yi_data = source.GetYiData(); double *x_data = M_PLOTDATA->m_Xdata; double *y_data = M_PLOTDATA->m_Ydata; double *yi_data = M_PLOTDATA->m_Yidata; bool has_yi = false; if (yi_data && src_yi_data) { has_yi = true; double *yi = (double*)malloc((count+src_count)*sizeof(double)); if (!yi) { newCurve.Destroy(); return newCurve; } newCurve.SetYiData(yi); } double *new_Xdata = newCurve.GetXData(); double *new_Ydata = newCurve.GetYData(); double *new_Yidata = newCurve.GetYiData(); if (index > 0) { memcpy(new_Xdata, x_data, index*sizeof(double)); memcpy(new_Ydata, y_data, index*sizeof(double)); if (has_yi) memcpy(new_Yidata, yi_data, index*sizeof(double)); } memcpy(new_Xdata+index, src_x_data, src_count*sizeof(double)); memcpy(new_Ydata+index, src_y_data, src_count*sizeof(double)); if (has_yi) memcpy(new_Yidata+index, src_yi_data, src_count*sizeof(double)); memcpy(new_Xdata+index+src_count, x_data+index, (count-index)*sizeof(double)); memcpy(new_Ydata+index+src_count, y_data+index, (count-index)*sizeof(double)); if (has_yi) memcpy(new_Yidata+index+src_count, yi_data+index, (count-index)*sizeof(double)); newCurve.CalcBoundingRect(); newCurve.CopyExtra( *this ); return newCurve; } wxPlotData wxPlotData::Remove(int index, int count) const { wxPlotData newCurve; wxCHECK_MSG( Ok(), newCurve, wxT("Invalid wxPlotData") ); if (count <= 0) count = M_PLOTDATA->m_count - index; wxCHECK_MSG((index >= 0) && (index+count <= M_PLOTDATA->m_count), newCurve, wxT("invalid index")); // should probably give an error here? if ((index == 0) && (count < 0)) return newCurve; if (count < 0) // return first part { newCurve = GetSubPlotData(0, index); } else if (index == 0) // return last part { newCurve = GetSubPlotData(index+count, -1); } else // return first and last, removing middle { newCurve = GetSubPlotData(0, index); if (index+count < M_PLOTDATA->m_count - 1) newCurve = newCurve.Append(GetSubPlotData(index+count, -1)); } newCurve.CopyExtra( *this ); return newCurve; } wxPlotData wxPlotData::GetSubPlotData(int index, int count) const { wxCHECK_MSG( Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); if (count <= 0) count = M_PLOTDATA->m_count - index; wxCHECK_MSG((index >= 0) && (index+count <= M_PLOTDATA->m_count), wxPlotData(), wxT("invalid index")); wxPlotData newCurve(count, false); if (!newCurve.Ok()) return newCurve; bool has_yi = false; if (M_PLOTDATA->m_Yidata) { has_yi = true; double *yi = (double*)malloc(count*sizeof(double)); newCurve.SetYiData(yi); } memcpy(newCurve.GetXData(), M_PLOTDATA->m_Xdata+index, count*sizeof(double)); memcpy(newCurve.GetYData(), M_PLOTDATA->m_Ydata+index, count*sizeof(double)); if (has_yi) memcpy(newCurve.GetYiData(), M_PLOTDATA->m_Yidata+index, count*sizeof(double)); newCurve.CalcBoundingRect(); newCurve.CopyExtra( *this ); return newCurve; } void wxPlotData::CalcBoundingRect() { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); M_PLOTDATA->m_boundingRect = wxRect2DDouble(0, 0, 0, 0); double *x_data = M_PLOTDATA->m_Xdata, *y_data = M_PLOTDATA->m_Ydata; double x = *x_data, y = *y_data, xmin = x, xmax = x, ymin = y, ymax = y, xlast = x; bool xordered = true, valid = false; register int i, count = M_PLOTDATA->m_count; for (i=0; i xmax ) xmax = x; if ( y < ymin ) ymin = y; else if ( y > ymax ) ymax = y; if ( xlast > x ) xordered = false; else xlast = x; } if (valid) M_PLOTDATA->m_boundingRect = wxRect2DDouble(xmin, ymin, xmax-xmin, ymax-ymin); else M_PLOTDATA->m_boundingRect = wxRect2DDouble(0, 0, 0, 0); M_PLOTDATA->m_Xordered = xordered; } bool wxPlotData::GetIsXOrdered() const { wxCHECK_MSG( Ok(), false, wxT("Invalid wxPlotData") ); return M_PLOTDATA->m_Xordered; } //---------------------------------------------------------------------------- // Load/Save Get/Set Filename, Header //---------------------------------------------------------------------------- int NumberParse (double *nums, const wxString &string) { const wxChar d1 = wxT(','); // 44; // comma const wxChar d2 = wxT('\t'); // 9; // tab const wxChar d3 = wxT(' '); // 32; // space const wxChar d4 = wxT('\n'); // 13; // carrage return const wxChar d5 = wxT('\r'); // 10; // line feed // char *D = "D"; // for Quick Basic, uses 1D3 not 1E3 // char *E = "E"; const wxChar *s = string.GetData(); int i, count = string.Length(); double number; int n = 0; int start_word = -1; for (i=0; i<=count; i++) { if ((*s == d1 || *s == d2 || *s == d2 || *s == d3 || *s == d4 || *s == d5) || (i >= count)) { if (start_word != -1) { if ( string.Mid(start_word, i - start_word).ToDouble(&number) ) { nums[n] = number; n++; if (n >= wxPLOT_MAX_DATA_COLUMNS) return n; start_word = -1; } else return n; } } else if (start_word == -1) start_word = i; if (*s == d4 || *s == d5) return n; s++; } return n; } static char GetNextFileStreamChar( wxFileInputStream &fs ) { return fs.Eof() ? '\0' : fs.GetC(); /* if (fs.Eof()) return wxT('\0'); // see txtstream.cpp, ReadLine() #if wxUSE_UNICODE // FIXME: this is only works for single byte encodings // How-to read a single char in an unkown encoding??? char buf[10] = {0}; memset(buf, 0, 10*sizeof(char)); buf[0] = fs.GetC(); wxChar wbuf[10] = {0}; memset(wbuf, 0, 10*sizeof(wxChar)); wxConvUTF8.MB2WC( wbuf, buf, 2 ); wxChar c = wbuf[0]; #else wxChar c = fs.GetC(); #endif return c; */ } bool wxPlotData::LoadFile( const wxString &filename, int x_col, int y_col, int options ) { if (filename.IsEmpty()) return false; wxFile loadfile; loadfile.Open( filename, wxFile::read ); if (!loadfile.IsOpened()) return false; wxFileInputStream fileStream( loadfile ); if (!fileStream.Ok()) { loadfile.Close(); return false; } wxEOL eol = wxEOL_NATIVE; if (1) { while ((eol == wxEOL_NATIVE) && !fileStream.Eof()) { const char c = GetNextFileStreamChar(fileStream); if (c == '\n') { eol = wxEOL_UNIX; } else if (c == '\r') { const char cc = GetNextFileStreamChar(fileStream); if (cc == '\n') eol = wxEOL_DOS; else eol = wxEOL_MAC; } } } // Rewind file fileStream.SeekI(off_t(0)); wxTextInputStream textstream( fileStream ); int allocated_data = 400; double *x_data = (double*)malloc(allocated_data*sizeof(double)); double *y_data = (double*)malloc(allocated_data*sizeof(double)); if (!x_data || !y_data) { if (x_data) free(x_data); if (y_data) free(y_data); return false; } int points = 0, line_number = 0; wxString wxstr; wxString header; wxString separator; bool stop_load = false; double nums[wxPLOT_MAX_DATA_COLUMNS]; int n; bool select_cols = (x_col < 0) || (y_col < 0); while ( !fileStream.Eof() && !stop_load ) { wxstr = textstream.ReadLine().Strip(wxString::both); line_number++; if (wxstr.IsEmpty()) { if ((points > 0) && (options & wxPLOTDATA_LOAD_BREAKONBLANKLINE)) stop_load = true; } else if (wxstr.Left(1) == wxT("#")) { if ((points == 0) && (options & wxPLOTDATA_LOAD_HEADER)) header += (wxstr + wxT("\n")); } else { n = NumberParse( nums, wxstr ); if (select_cols) { if (n == 0) // FAIL { x_col = y_col = 1; select_cols = false; } else if (n == 1) { x_col = y_col = 0; select_cols = false; } else if (n == 2) { x_col = 0; y_col = 1; select_cols = false; } while (select_cols && !stop_load ) { wxString colStr = wxGetTextFromUser( wxString::Format(wxT("%d columns found.\n" "Enter x and y cols separated by a space starting from 1.\n" "If x = y then x values are 0,1,2... and y is that col."), n), wxT("Enter columns of data file to use")); if (colStr.IsEmpty()) { stop_load = true; } else { colStr.Trim(true).Trim(false); wxString leftStr = colStr.BeforeFirst(wxT(' ')); wxString rightStr = colStr.AfterFirst(wxT(' ')); if (rightStr.IsEmpty()) rightStr = leftStr; long xcol=0, ycol=0; if ((!leftStr.IsEmpty()) && leftStr.ToLong(&xcol) && rightStr.ToLong(&ycol)) { xcol--; ycol--; if ((xcol>=0) && (ycol>=0) && (xcol= n) || (y_col >= n)) && (!stop_load || select_cols)) { // FIXME - wxEOL_MAC - and end of file filestream.Eof() == 1, last line is a '@' if (fileStream.Eof() && (eol==wxEOL_MAC) && (wxstr == wxT("@"))) { printf("MAC EOF @"); fflush(stdout); break; } wxMessageBox( wxString::Format(wxT("Loading cols (%d,%d) aborted after %d points\n\n" "First 100 characters of offending line number: %d\n" "\"%s\"\n\n" "# for comments, blank lines Ok, comma, tab, space for separators\n" "7 4\n33 2.5e-2\n...\n"), x_col, y_col, points, line_number, wxstr.Left(100).c_str()), wxT("Error loading ")+filename, wxOK|wxICON_ERROR); stop_load = true; break; } else if (!stop_load) { // figure out what the separator is for the first line only if (points == 0) { if (wxstr.Find(wxT(',')) != wxNOT_FOUND) separator = wxPLOTCURVE_DATASEPARATOR_COMMA; else if (wxstr.Find(wxT('\t')) != wxNOT_FOUND) separator = wxPLOTCURVE_DATASEPARATOR_TAB; } // reallocate data if necessary if ( points >= allocated_data - 1) { allocated_data += 400; x_data = (double*)realloc( x_data, allocated_data*sizeof(double) ); y_data = (double*)realloc( y_data, allocated_data*sizeof(double) ); if (!x_data || !y_data) { if (x_data) free(x_data); if (y_data) free(y_data); loadfile.Close(); return false; } } if (x_col == y_col) x_data[points] = points; else x_data[points] = nums[x_col]; y_data[points] = nums[y_col]; points++; } } } loadfile.Close(); if (points > 0) { x_data = (double*)realloc( x_data, points*sizeof(double) ); y_data = (double*)realloc( y_data, points*sizeof(double) ); bool ok = Create( x_data, y_data, points, false ); if (ok) { SetFilename( filename ); SetEOLMode( eol ); if (!separator.IsEmpty()) SetDataColumnSeparator(separator); if (header.Len() > 0u) SetHeader(header); } return ok; } if (x_data) free(x_data); if (y_data) free(y_data); return false; } bool wxPlotData::SaveFile( const wxString &filename, bool save_header, const wxString &format ) { wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData") ); wxCHECK_MSG((!format.IsEmpty()) && (format.Find(wxT('%')) != wxNOT_FOUND), false, wxT("invalid format")); if (filename.IsEmpty()) return false; wxFile savefile; savefile.Open( filename, wxFile::write ); if (!savefile.IsOpened()) return false; wxFileOutputStream filestream( savefile ); wxTextOutputStream textstream( filestream ); textstream.SetMode( GetEOLMode() ); int i; wxString header = GetOption(wxPLOTCURVE_OPTION_HEADER); if (save_header && (header.Len() > 0u)) { textstream.WriteString(header); const wxChar lastChar = header[header.Len()-1]; if ((lastChar != wxT('\r')) || (lastChar != wxT('\n'))) textstream.WriteString(wxT("\n")); } wxString s; wxString sep = GetDataColumnSeparator(); wxString f(wxT("%g")); if (!format.IsEmpty()) f = format; double x, y; for (i=0; im_count; i++) { x = M_PLOTDATA->m_Xdata[i]; y = M_PLOTDATA->m_Ydata[i]; if (wxFinite(x)) s = wxString::Format(f.c_str(), x); else s = wxT("nan"); s += sep; if (wxFinite(y)) s += wxString::Format(f.c_str(), y); else s += wxT("nan"); s += wxT("\n"); textstream.WriteString( s ); } savefile.Close(); SetFilename(filename); return true; } wxString wxPlotData::GetFilename() const { wxCHECK_MSG( Ok(), wxEmptyString, wxT("Invalid wxPlotData") ); return GetOption(wxPLOTCURVE_OPTION_FILENAME); } void wxPlotData::SetFilename( const wxString &filename ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); SetOption(wxPLOTCURVE_OPTION_FILENAME, filename, true); } wxString wxPlotData::GetHeader() const { wxCHECK_MSG( Ok(), wxEmptyString, wxT("Invalid wxPlotData") ); return GetOption(wxPLOTCURVE_OPTION_HEADER); } void wxPlotData::SetHeader( const wxString &header ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); SetOption(wxPLOTCURVE_OPTION_HEADER, header); } wxEOL wxPlotData::GetEOLMode() const { wxCHECK_MSG( Ok(), wxEOL_NATIVE, wxT("Invalid wxPlotData") ); int eol = HasOption(wxPLOTCURVE_OPTION_EOLMODE) ? GetOptionInt(wxPLOTCURVE_OPTION_EOLMODE) : wxEOL_NATIVE; switch (eol) { case wxEOL_NATIVE : return wxEOL_NATIVE; case wxEOL_UNIX : return wxEOL_UNIX; case wxEOL_MAC : return wxEOL_MAC; case wxEOL_DOS : return wxEOL_DOS; default : break; } return wxEOL_NATIVE; } void wxPlotData::SetEOLMode( wxEOL eol ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); SetOption(wxPLOTCURVE_OPTION_EOLMODE, (int)eol); } wxString wxPlotData::GetDataColumnSeparator() const { wxCHECK_MSG( Ok(), wxPLOTCURVE_DATASEPARATOR_SPACE, wxT("Invalid wxPlotData") ); wxString s = wxPLOTCURVE_DATASEPARATOR_SPACE; GetOption(wxPLOTCURVE_OPTION_DATASEPARATOR, s); return s; } void wxPlotData::SetDataColumnSeparator( const wxString &separator ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); SetOption(wxPLOTCURVE_OPTION_DATASEPARATOR, separator, true); } //---------------------------------------------------------------------------- // Get(X/Y)Data //---------------------------------------------------------------------------- double *wxPlotData::GetXData() const { wxCHECK_MSG( Ok(), (double*)NULL, wxT("Invalid wxPlotData") ); return M_PLOTDATA->m_Xdata; } double *wxPlotData::GetYData() const { wxCHECK_MSG( Ok(), (double*)NULL, wxT("Invalid wxPlotData") ); return M_PLOTDATA->m_Ydata; } double *wxPlotData::GetYiData() const { wxCHECK_MSG( Ok(), (double*)NULL, wxT("Invalid wxPlotData") ); return M_PLOTDATA->m_Yidata; } void wxPlotData::SetYiData( double *yi_data ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); if (M_PLOTDATA->m_Yidata) free(M_PLOTDATA->m_Yidata); M_PLOTDATA->m_Yidata = yi_data; } double wxPlotData::GetXValue( int index ) const { wxCHECK_MSG( Ok() && (index < M_PLOTDATA->m_count), 0.0, wxT("Invalid wxPlotData") ); return M_PLOTDATA->m_Xdata[index]; } double wxPlotData::GetYValue( int index ) const { wxCHECK_MSG( Ok() && (index < M_PLOTDATA->m_count), 0.0, wxT("Invalid wxPlotData") ); return M_PLOTDATA->m_Ydata[index]; } wxPoint2DDouble wxPlotData::GetPoint( int index ) const { wxCHECK_MSG( Ok() && (index < M_PLOTDATA->m_count), wxPoint2DDouble(0,0), wxT("Invalid wxPlotData") ); return wxPoint2DDouble(M_PLOTDATA->m_Xdata[index], M_PLOTDATA->m_Ydata[index]); } double wxPlotData::GetY( double x ) { wxCHECK_MSG(Ok(), 0, wxT("invalid wxPlotData")); int i = GetIndexFromX( x, index_floor ); if (M_PLOTDATA->m_Xdata[i] == x) return M_PLOTDATA->m_Ydata[i]; if (i >= M_PLOTDATA->m_count - 1) return M_PLOTDATA->m_Ydata[i]; int i1 = GetIndexFromX( x, index_ceil ); double y0 = M_PLOTDATA->m_Ydata[i]; double y1 = M_PLOTDATA->m_Ydata[i1]; if ( y0 == y1 ) return y0; return LinearInterpolateY( M_PLOTDATA->m_Xdata[i], y0, M_PLOTDATA->m_Xdata[i1], y1, x ); } void wxPlotData::SetXValue( int index, double x ) { wxCHECK_RET( Ok() && (index < M_PLOTDATA->m_count), wxT("Invalid wxPlotData") ); if (M_PLOTDATA->m_count == 1) M_PLOTDATA->m_boundingRect.m_x = x; else { if (x < M_PLOTDATA->m_boundingRect.m_x) M_PLOTDATA->m_boundingRect.SetLeft(x); else if (x > M_PLOTDATA->m_boundingRect.GetRight()) M_PLOTDATA->m_boundingRect.SetRight(x); else CalcBoundingRect(); // don't know recalc it all } M_PLOTDATA->m_Xdata[index] = x; } void wxPlotData::SetYValue( int index, double y ) { wxCHECK_RET( Ok() && (index < M_PLOTDATA->m_count), wxT("Invalid wxPlotData") ); if (M_PLOTDATA->m_count == 1) M_PLOTDATA->m_boundingRect.m_y = y; else { if (y < M_PLOTDATA->m_boundingRect.m_y) M_PLOTDATA->m_boundingRect.SetTop(y); else if (y > M_PLOTDATA->m_boundingRect.GetBottom()) M_PLOTDATA->m_boundingRect.SetBottom(y); else CalcBoundingRect(); // don't know recalc it all } M_PLOTDATA->m_Ydata[index] = y; } void wxPlotData::SetValue(int index, double x, double y) { wxCHECK_RET( Ok() && (index < M_PLOTDATA->m_count), wxT("Invalid wxPlotData") ); double x_old = M_PLOTDATA->m_Xdata[index]; double y_old = M_PLOTDATA->m_Ydata[index]; M_PLOTDATA->m_Xdata[index] = x; M_PLOTDATA->m_Ydata[index] = y; if (M_PLOTDATA->m_count == 1) { M_PLOTDATA->m_boundingRect.m_x = x; M_PLOTDATA->m_boundingRect.m_y = y; } else { if ( (x_old <= M_PLOTDATA->m_boundingRect.m_x) || (x_old >= M_PLOTDATA->m_boundingRect.GetRight()) || (y_old >= M_PLOTDATA->m_boundingRect.m_y) || (y_old <= M_PLOTDATA->m_boundingRect.GetBottom()) ) CalcBoundingRect(); // don't know recalc it all else { if (x < M_PLOTDATA->m_boundingRect.m_x) M_PLOTDATA->m_boundingRect.m_x = x; if (x > M_PLOTDATA->m_boundingRect.GetRight()) M_PLOTDATA->m_boundingRect.SetRight(x); if (y > M_PLOTDATA->m_boundingRect.m_y) M_PLOTDATA->m_boundingRect.m_y = y; if (y < M_PLOTDATA->m_boundingRect.GetBottom()) M_PLOTDATA->m_boundingRect.SetBottom(y); } } } void wxPlotData::SetXValues( int start_index, int count, double x ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); if (count == 0) return; if (count < 0) count = M_PLOTDATA->m_count-start_index; int end_index = start_index + count - 1; wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid starting index")); wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid ending index")); double *x_data = M_PLOTDATA->m_Xdata; for (int n = start_index; n <= end_index; n++) *x_data++ = x; } void wxPlotData::SetYValues( int start_index, int count, double y ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); if (count == 0) return; if (count < 0) count = M_PLOTDATA->m_count-start_index; int end_index = start_index + count - 1; wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid starting index")); wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid ending index")); double *y_data = M_PLOTDATA->m_Ydata; for (int n = start_index; n <= end_index; n++) *y_data++ = y; } void wxPlotData::SetXStepValues( int start_index, int count, double x_start, double dx ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); if (count == 0) return; if (count < 0) count = M_PLOTDATA->m_count-start_index; int end_index = start_index + count - 1; wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid starting index")); wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid ending index")); double *x_data = M_PLOTDATA->m_Xdata + start_index; for (int i = 0; i < count; i++, x_data++) *x_data = x_start + (i * dx); } void wxPlotData::SetYStepValues( int start_index, int count, double y_start, double dy ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); if (count == 0) return; if (count < 0) count = M_PLOTDATA->m_count-start_index; int end_index = start_index + count - 1; wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid starting index")); wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid ending index")); double *y_data = M_PLOTDATA->m_Ydata + start_index; for (int i = 0; i < count; i++, y_data++) *y_data = y_start + (i * dy); } int wxPlotData::GetIndexFromX( double x, wxPlotData::Index_Type type ) const { wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); int count = M_PLOTDATA->m_count; double *x_data = M_PLOTDATA->m_Xdata; if ( !M_PLOTDATA->m_Xordered ) { register int i; int index = 0, index_lower = 0, index_higher = 0; double closest = fabs( x - *x_data++ ); for (i=1; i *x_data) index_lower = i; else index_higher = i; } x_data++; } // out of bounds so just return the closest if ((x < M_PLOTDATA->m_boundingRect.GetLeft()) || (x > M_PLOTDATA->m_boundingRect.GetRight()) ) return index; if (type == index_floor) return index_lower; if (type == index_ceil) return index_higher; return index; } // if the data is ordered use a faster search if (x < M_PLOTDATA->m_boundingRect.GetLeft()) return 0; if (x > M_PLOTDATA->m_boundingRect.GetRight()) return M_PLOTDATA->m_count - 1; if (x <= x_data[0]) return 0; if (x >= x_data[count-1]) return count-1; int i, lo = 0, hi = count; double res; while ( lo < hi ) { i = (lo + hi)/2; res = x - x_data[i]; if ( res < 0 ) hi = i; else if ( res > 0 ) lo = i + 1; else { lo = i; break; } } if (type == index_floor) { if ((lo > 0) && (x < x_data[lo])) lo--; return lo; } if (type == index_ceil) { if ((lo < count - 1) && (x > x_data[lo])) lo++; return lo; } if ((lo > 0) && (fabs(x - x_data[lo-1]) < fabs(x - x_data[lo]))) lo--; if ((lo < count-1) && (fabs(x - x_data[lo+1]) < fabs(x - x_data[lo]))) lo++; return lo; } int wxPlotData::GetIndexFromY( double y, wxPlotData::Index_Type type ) const { wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); register int i; int index = 0, index_lower = 0, index_higher = 0; int count = M_PLOTDATA->m_count; double *y_data = M_PLOTDATA->m_Ydata; double closest = fabs( y - *y_data++ ); for (i=1; i *y_data) index_lower = i; else index_higher = i; } y_data++; } // out of bounds so just return the closest if ((y < M_PLOTDATA->m_boundingRect.GetLeft()) || (y > M_PLOTDATA->m_boundingRect.GetRight()) ) return index; if (type == index_floor) return index_lower; if (type == index_ceil) return index_higher; return index; } int wxPlotData::GetIndexFromXY( double x, double y, double x_range ) const { wxCHECK_MSG( Ok() && (x_range >= 0), 0, wxT("Invalid wxPlotData") ); int start = 1, end = M_PLOTDATA->m_count - 1; // find bounding indexes for range if (M_PLOTDATA->m_Xordered && (x_range != 0)) { start = GetIndexFromX(x - x_range, wxPlotData::index_floor) + 1; end = GetIndexFromX(x + x_range, wxPlotData::index_ceil); } int i, index = start - 1; double *x_data = &M_PLOTDATA->m_Xdata[index]; double *y_data = &M_PLOTDATA->m_Ydata[index]; double xdiff = (*x_data++) - x; double ydiff = (*y_data++) - y; double diff = xdiff*xdiff + ydiff*ydiff; double min_diff = diff; double x_lower = x - x_range, x_higher = x + x_range; for (i=start; i<=end; i++) { if ((x_range != 0) && ((*x_data < x_lower) || (*x_data > x_higher))) { x_data++; y_data++; continue; } xdiff = (*x_data++) - x; ydiff = (*y_data++) - y; diff = xdiff*xdiff + ydiff*ydiff; if (diff < min_diff) { min_diff = diff; index = i; } } return index; } double wxPlotData::GetAverage( int start_index, int count ) const { wxCHECK_MSG( Ok(), 0.0, wxT("Invalid wxPlotData") ); if (count < 0) count = M_PLOTDATA->m_count-start_index; int end_index = start_index + count - 1; wxCHECK_MSG((start_indexm_count) && (end_indexm_count), 0.0, wxT("invalid input")); double ave = 0.0; double *y_data = M_PLOTDATA->m_Ydata + start_index; for (int i=start_index; i<=end_index; i++) ave += *y_data++; ave /= double(count); return ave; } int wxPlotData::GetMinMaxAve( const wxRangeIntSelection& rangeSel, wxPoint2DDouble* minXY_, wxPoint2DDouble* maxXY_, wxPoint2DDouble* ave_, int *x_min_index_, int *x_max_index_, int *y_min_index_, int *y_max_index_ ) const { wxCHECK_MSG(Ok(), 0, wxT("Invalid data curve")); wxCHECK_MSG(rangeSel.GetCount() != 0, 0, wxT("Invalid range selection")); int min_index = rangeSel.GetRange(0).m_min; //int max_index = rangeSel.GetRange(sel_count-1).m_max; wxCHECK_MSG((min_index >= 0) && (min_index < (int)M_PLOTDATA->m_count), 0, wxT("Invalid range selection index in data curve")); double *x_data = M_PLOTDATA->m_Xdata; double *y_data = M_PLOTDATA->m_Ydata; double x = x_data[min_index]; double y = y_data[min_index]; // Find the X and Y min/max/ave values of the selection int x_min_index = min_index, x_max_index = min_index; int y_min_index = min_index, y_max_index = min_index; double x_min_x = x, x_max_x = x; double y_min_y = y, y_max_y = y; double ave_x = 0, ave_y = 0; int i, j, sel_count = rangeSel.GetCount(), sel_point_count = 0; for (i=0; i= 0) && (r.m_min < (int)M_PLOTDATA->m_count) && (r.m_max >= 0) && (r.m_max < (int)M_PLOTDATA->m_count), 0, wxT("Invalid range selection index in data curve")); for (j=r.m_min; j<=r.m_max; j++) // yes we duplicate first point { sel_point_count++; x = x_data[j]; y = y_data[j]; if (x < x_min_x) { x_min_x = x; x_min_index = j; } if (x > x_max_x) { x_max_x = x; x_max_index = j; } if (y < y_min_y) { y_min_y = y; y_min_index = j; } if (y > y_max_y) { y_max_y = y; y_max_index = j; } ave_x += x; ave_y += y; } } ave_x /= double(sel_point_count); ave_y /= double(sel_point_count); if (ave_) *ave_ = wxPoint2DDouble(ave_x, ave_y); if (minXY_) *minXY_ = wxPoint2DDouble(x_min_x, y_min_y); if (maxXY_) *maxXY_ = wxPoint2DDouble(x_max_x, y_max_y); if (x_min_index_) *x_min_index_ = x_min_index; if (x_max_index_) *x_max_index_ = x_max_index; if (y_min_index_) *y_min_index_ = y_min_index; if (y_max_index_) *y_max_index_ = y_max_index; return sel_point_count; } wxArrayInt wxPlotData::GetCrossing( double y_value ) const { wxArrayInt points; wxCHECK_MSG( Ok(), points, wxT("Invalid wxPlotData") ); int i; double *y_data = M_PLOTDATA->m_Ydata; double y, last_y = M_PLOTDATA->m_Ydata[0]; for (i=1; im_count; i++) { y = y_data[i]; if (((last_y >= y_value) && (y <= y_value)) || ((last_y <= y_value) && (y >= y_value))) { if (fabs(last_y - y_value) < fabs(y - y_value)) points.Add(i-1); else points.Add(i); } last_y = y; } return points; } int wxPlotData::GetMinYIndex(int start_index, int end_index) const { wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_MSG(start_index, end_index, count, 0); double *y_data = &M_PLOTDATA->m_Ydata[start_index]; double min_y = *y_data; int min_y_index = start_index; for (int i=start_index+1; im_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_MSG(start_index, end_index, count, 0); double *y_data = &M_PLOTDATA->m_Ydata[start_index]; double max_y = *y_data; int max_y_index = start_index; for (int i=start_index+1; i max_y) { max_y = *y_data; max_y_index = i; } y_data++; } return max_y_index; } //---------------------------------------------------------------------------- // Data processing functions //---------------------------------------------------------------------------- void wxPlotData::OffsetX( double offset, int start_index, int end_index ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_RET(start_index, end_index, count); register int i; double *x = M_PLOTDATA->m_Xdata + start_index; for (i = start_index; i <= end_index; i++) *x++ += offset; CalcBoundingRect(); } void wxPlotData::OffsetY( double offset, int start_index, int end_index ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_RET(start_index, end_index, count); register int i; double *y = M_PLOTDATA->m_Ydata + start_index; for (i = start_index; i <= end_index; i++) *y++ += offset; CalcBoundingRect(); } void wxPlotData::OffsetXY( double offsetX, double offsetY, int start_index, int end_index ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_RET(start_index, end_index, count); register int i; double *x = M_PLOTDATA->m_Xdata + start_index; double *y = M_PLOTDATA->m_Ydata + start_index; for (i = start_index; i <= end_index; i++) { *x++ += offsetX; *y++ += offsetY; } CalcBoundingRect(); } void wxPlotData::ScaleX( double scale, double offset, int start_index, int end_index ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_RET(start_index, end_index, count); register int i; double *x = M_PLOTDATA->m_Xdata + start_index; for (i = start_index; i <= end_index; i++) { *x = ((*x) - offset)*scale + offset; x++; } CalcBoundingRect(); } void wxPlotData::ScaleY( double scale, double offset, int start_index, int end_index ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_RET(start_index, end_index, count); register int i; double *y = M_PLOTDATA->m_Ydata + start_index; for (i = start_index; i <= end_index; i++) { *y = ((*y) - offset)*scale + offset; y++; } CalcBoundingRect(); } void wxPlotData::ScaleXY(double scaleX, double scaleY, double offsetX, double offsetY, int start_index, int end_index ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_RET(start_index, end_index, count); double *x = M_PLOTDATA->m_Xdata + start_index; double *y = M_PLOTDATA->m_Ydata + start_index; for (int i = start_index; i < end_index; i++) { *x = ((*x) - offsetX)*scaleX + offsetX; x++; *y = ((*y) - offsetY)*scaleY + offsetY; y++; } CalcBoundingRect(); } void wxPlotData::PowerX( double power, int start_index, int end_index ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_RET(start_index, end_index, count); register int i; double *x = M_PLOTDATA->m_Xdata + start_index; for (i = start_index; i <= end_index; i++, x++) *x = pow(*x, power); CalcBoundingRect(); } void wxPlotData::PowerY( double power, int start_index, int end_index ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_RET(start_index, end_index, count); register int i; double *y = M_PLOTDATA->m_Ydata + start_index; for (i = start_index; i <= end_index; i++, y++) *y = pow(*y, power); CalcBoundingRect(); } void wxPlotData::PowerXY( double powerX, double powerY, int start_index, int end_index ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); const int count = M_PLOTDATA->m_count; if (end_index < 0) end_index = count - 1; CHECK_START_END_INDEX_RET(start_index, end_index, count); register int i; double *x = M_PLOTDATA->m_Xdata + start_index; double *y = M_PLOTDATA->m_Ydata + start_index; for (i = start_index; i <= end_index; i++, x++, y++) { *x = pow(*x, powerX); *y = pow(*y, powerY); } CalcBoundingRect(); } wxPlotData wxPlotData::Resample( double start_x, double dx, int points ) const { wxPlotData dst; wxCHECK_MSG(Ok(), dst, wxT("Invalid wxPlotData")); wxCHECK_MSG(points > 0, dst, wxT("invalid number of points")); if (!dst.Create(points, false)) return dst; double x = start_x; wxPlotData thisData = *this; for (int i=0; i< points; i++, x += dx) { dst.SetPoint(i, wxPoint2DDouble(x, thisData.GetY(x))); } dst.CalcBoundingRect(); return dst; } wxPlotData wxPlotData::Resample( const wxPlotData &source ) const { wxPlotData dst; wxCHECK_MSG( Ok(), dst, wxT("Invalid wxPlotData") ); int src_index_min = source.GetIndexFromX(wxMax(GetBoundingRect().m_x, source.GetBoundingRect().m_x)); int src_index_max = source.GetIndexFromX(wxMin(GetBoundingRect().GetRight(), source.GetBoundingRect().GetRight())); int index_min = GetIndexFromX(wxMax(GetBoundingRect().m_x, source.GetBoundingRect().m_x)); //int index_max = GetIndexFromX(wxMin(GetBoundingRect().GetRight(), source.GetBoundingRect().GetRight())); int count = src_index_max - src_index_min; if (count <= 0) return dst; if (!dst.Create(src_index_max - src_index_min, false)) return dst; double *dst_x_data = dst.GetXData(); double *dst_y_data = dst.GetYData(); double x, s_x, y; for (int i=0; i s_x) { if (i+index_min > 0) index1--; } else { if (i+index_min > 0) index2++; } y = LinearInterpolateY( GetXValue(index1), GetYValue(index1), GetXValue(index2), GetYValue(index2), x ); } *dst_x_data++ = x; *dst_y_data++ = y; } dst.CalcBoundingRect(); return dst; } //---------------------------------------------------------------------------- // Data manipulation //---------------------------------------------------------------------------- wxPlotData wxPlotData::Modify( const wxPlotFunction &func_, FuncModify_Type type ) const { wxPlotData dst; wxCHECK_MSG( Ok() && func_.Ok(), dst, wxT("Invalid wxPlotData") ); int i, count = M_PLOTDATA->m_count; if (!dst.Create(count)) return dst; double *x_data = M_PLOTDATA->m_Xdata; double *y_data = M_PLOTDATA->m_Ydata; double *dst_x_data = dst.GetXData(); double *dst_y_data = dst.GetYData(); if (M_PLOTDATA->m_Yidata) { double *yi = (double*)malloc(count*sizeof(double)); if (!yi) { dst.Destroy(); return dst; } dst.SetYiData(yi); } wxPlotFunction func(func_); switch (type) { case add_x : { memcpy(dst_y_data, y_data, count*sizeof(double)); if (M_PLOTDATA->m_Yidata) memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); for (i=0; im_Yidata) memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); for (i=0; im_Yidata) memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); for (i=0; im_Yidata) memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); for (i=0; im_Yidata; double *dst_yi_data = dst.GetYiData(); for (i=0; im_Yidata; double *dst_yi_data = dst.GetYiData(); for (i=0; im_count; double *x_data = M_PLOTDATA->m_Xdata; double *y_data = M_PLOTDATA->m_Ydata; if (!dst.Create(count)) return dst; double *dst_x_data = dst.GetXData(); double *dst_y_data = dst.GetYData(); int i, index1, index2; for (i=0; i curve2_x_min) && (*x_data < curve2_x_max)) { index1 = curve2.GetIndexFromX(*x_data); if ( curve2.GetXValue(index1) == *x_data ) { *dst_y_data = factor1*(*y_data) + factor2*curve2.GetYValue(index1); } else // need to interpolate to find data's y value at this x { if (*x_data < curve2.GetXValue(index1)) { index2 = index1; index1--; } else //if (*x_data < data.GetX(index1)) { index2 = index1 + 1; } if ((index1 >= 0) && (index1 < curve2_count) && (index2 >= 0) && (index2 < curve2_count) ) { *dst_y_data = factor1*(*y_data) + factor2*LinearInterpolateY( curve2.GetXValue(index1), curve2.GetYValue(index1), curve2.GetXValue(index2), curve2.GetYValue(index2), *x_data ); } else { *dst_y_data = *x_data; } } } x_data++; y_data++; dst_x_data++; dst_y_data++; } dst.CalcBoundingRect(); return dst; } //---------------------------------------------------------------------------- // RunAverage //---------------------------------------------------------------------------- wxPlotData wxPlotData::RunAverage( int points, int start_index, int count ) const { wxPlotData dst; wxCHECK_MSG( Ok(), dst, wxT("Invalid wxPlotData") ); int data_count = M_PLOTDATA->m_count; wxCHECK_MSG((start_index < data_count), dst, wxT("Invalid runaverage range") ); int i; int half_width = points/2; int width = half_width * 2 + 1; double dpoints = width; int end_index = count <= 0 ? data_count : start_index + count; int run_start = wxMax(start_index, half_width); int run_end = wxMin(end_index, data_count - half_width); //wxCHECK_MSG((points > 2) && (start_index+count= run_end) return dst; //double *src = M_PLOTDATA->m_Ydata; //double *dest = dst.GetYData(); double run_sum = 0.0; for (i=run_start-half_width; i<=run_start+half_width; i++) run_sum += GetYValue(i); //src[i]; dst.SetYValue(run_start, run_sum/dpoints); //dest[half_width] = runsum / dpoints; // fake the initial runaverage (ideally this should be thrown away) double run_sum_init = run_sum; for (i=run_start-1; i>=start_index; i--) { run_sum_init += GetYValue(i) - GetYValue(i+half_width); dst.SetYValue(i, run_sum_init/dpoints); } for (i=run_start+1; i=0; i--) { init_runsum += src[i]; dest[i] = init_runsum / double(half_width - i + 1); } // middle "good" runaveraged points dest[half_width] = runsum / dpoints; for (i=half_width+1; im_count; i++) { runsum += src[i]; dest[i] = runsum / double(half_width - (M_PLOTDATA->m_count - i) + 2); } memcpy(dst.GetXData(), M_PLOTDATA->m_Xdata, M_PLOTDATA->m_count*sizeof(double)); */ dst.CalcBoundingRect(); return dst; } //---------------------------------------------------------------------------- // Abs //---------------------------------------------------------------------------- wxPlotData wxPlotData::Abs() const { wxPlotData dst; wxCHECK_MSG(Ok(), dst, wxT("invalid plotdata")); int points = M_PLOTDATA->m_count; if (!dst.Create(points, false)) return dst; double *y_data = M_PLOTDATA->m_Ydata; double *dst_y_data = dst.GetYData(); memcpy(dst.GetXData(), GetXData(), points*sizeof(double)); for (int i=0; im_count; if (count <= 0) count = points - start_index; wxCHECK_MSG((start_index + count <= points), dst, wxT("invalid index")); double x0 = M_PLOTDATA->m_Xdata[start_index]; double y0 = M_PLOTDATA->m_Ydata[start_index]; double x1 = M_PLOTDATA->m_Xdata[start_index+count-1]; double y1 = M_PLOTDATA->m_Ydata[start_index+count-1]; wxCHECK_MSG(wxFinite(x0)&&wxFinite(y0)&&wxFinite(x1)&&wxFinite(y1), dst, wxT("values are NaN")); if (!dst.Copy(*this, true)) return dst; double x, y, m = (y1-y0)/count; // equally spaced y values if (x1 == x0) { y = y0; for (int i=start_index+1; im_Xdata[i]; if (wxFinite(x)) { y = (m*x + (y0 - m*x0)); if (wxFinite(y)) dst.SetYValue(i, y); } } dst.CalcBoundingRect(); return dst; } // FIXME - this is not strictly correct should be xnew_n = (x_(n+1)+x_n)/2, do I care? wxPlotData wxPlotData::Derivitive() const { wxCHECK_MSG( Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); int count = M_PLOTDATA->m_count; wxPlotData dst(count, false); double *y_data = M_PLOTDATA->m_Ydata; double *dst_y_data = dst.GetYData(); memcpy(dst.GetXData(), GetXData(), count*sizeof(double)); *dst_y_data++ = 0; for (int i=1; i)^2))/N double wxPlotData::Variance(int start_index, int count) const { wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); int points = M_PLOTDATA->m_count; if (count <= 0) count = points - start_index; wxCHECK_MSG((start_index >= 0) && (start_index + count <= points), 0, wxT("invalid index")); double *y_data = GetYData() + start_index; double sum = 0; double ave = GetAverage(start_index, count); for (register int i=0; im_count; int i; int half_width = points/2; int width = half_width * 2 + 1; int end_index = data_count; //count <= 0 ? data_count : start_index + count; int run_start = wxMax(0, half_width); int run_end = wxMin(end_index, data_count - half_width); wxCHECK_MSG((data_count > half_width), dst, wxT("invalid data indexes")); if (!dst.Create(data_count, false)) return dst; memcpy(dst.GetXData(), GetXData(), data_count*sizeof(double)); memset(dst.GetYData(), 0, half_width*sizeof(double)); memset(dst.GetYData()+data_count-half_width, 0, half_width*sizeof(double)); if (run_start >= run_end) return dst; for (i=run_start; i= 0)&&(min min, 0.0, wxT("invalid index range")); double data_x_min = data.GetBoundingRect().GetLeft(); double data_x_max = data.GetBoundingRect().GetRight(); const int data_count = data.GetCount(); double *x_data = M_PLOTDATA->m_Xdata + min; double *y_data = M_PLOTDATA->m_Ydata + min; double x, y, dev = 0.0; int index1=0, index2=0; int points = 0; register int i; for (i=min; i= data_x_min) && (x <= data_x_max) ) { index1 = data.GetIndexFromX(x); if ( data.GetXValue(index1) == x ) { double yd = (y - data.GetYValue(index1)); dev += yd*yd; points++; } else // need to interpolate to find data's y value at this x { if (x < data.GetXValue(index1)) { index2 = index1; index1--; } else //if (*x_data < data.GetX(index1)) { index2 = index1 + 1; } if ((index1 >= 0) && (index2 < data_count) ) { double yd = y - LinearInterpolateY( data.GetXValue(index1), data.GetYValue(index1), data.GetXValue(index2), data.GetYValue(index2), x ); dev += yd*yd; points++; } } } x_data++; y_data++; } dev = sqrt(dev); if (points > 0) return dev/double(points); return -1; } double wxPlotData::CrossCorrelation( const wxPlotData &other, int runave, int min, int max ) const { //http://astronomy.swin.edu.au/~pbourke/analysis/correlate/ for discussion of crosscorrelation wxCHECK_MSG( Ok() && other.Ok(), 0.0, wxT("Invalid wxPlotData") ); const int count = GetCount(); wxCHECK_MSG((min >= 0)&&(min min, 0.0, wxT("invalid index range")); double cc = 0.0; wxPlotData smooth(RunAverage(runave)); wxPlotData other_smooth(other.RunAverage(runave)); smooth.CalcBoundingRect(); other_smooth.CalcBoundingRect(); double other_x_min = other.GetBoundingRect().GetLeft(); double other_x_max = other.GetBoundingRect().GetRight(); int other_count = other.GetCount(); register int i; double *x_data = M_PLOTDATA->m_Xdata; double *y_data = M_PLOTDATA->m_Ydata; double *smooth_y_data = smooth.GetYData(); double x; int index1, index2; for (i=min; i= other_x_min) && (x <= other_x_max) ) { index1 = other.GetIndexFromX(x); if ( other.GetXValue(index1) == x ) { //*y_data -= data.GetY(index1); //cc += (*y_data - data.GetY(index1))*(*y_data - data.GetY(index1)); cc += (GetYValue(i) - smooth.GetYValue(i))*(other.GetYValue(index1)-other_smooth.GetYValue(index1)); } else // need to interpolate to find data's y value at this x { if (x < other.GetXValue(index1)) { index2 = index1; index1--; } else //if (*x_data < data.GetX(index1)) { index2 = index1 + 1; } if ((index1 >= 0) && (index1 < other_count) && (index2 >= 0) && (index2 < other_count) ) { double y = LinearInterpolateY( other.GetXValue(index1), other.GetYValue(index1), other.GetXValue(index2), other.GetYValue(index2), x ); double ys = LinearInterpolateY( other_smooth.GetXValue(index1), other_smooth.GetYValue(index1), other_smooth.GetXValue(index2), other_smooth.GetYValue(index2), x ); cc += (GetYValue(i) - smooth.GetYValue(i))*(y-ys); } } } x_data++; y_data++; smooth_y_data++; } //cc = sqrt(cc); return cc; } double wxPlotData::MinShiftX( const wxPlotData &other ) const { wxCHECK_MSG(Ok() && other.Ok(), 0.0, wxT("invalid plotcurve")); wxRect2DDouble boundRect = GetBoundingRect(); wxRect2DDouble other_boundRect = other.GetBoundingRect(); double start_shift = (boundRect.m_x - other_boundRect.m_x) - other_boundRect.m_width/2.0; double end_shift = (boundRect.GetRight() - other_boundRect.m_x) - other_boundRect.m_width/2.0; double min_dev = 0, min_shift = start_shift; double step = fabs(M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0]); wxPlotData shifted; shifted.Copy(other); shifted.OffsetX(min_shift); for (double x=start_shift; x= 0) { if (x == start_shift) min_dev = dev; else if (dev < min_dev) { min_dev = dev; min_shift = x; } } shifted.OffsetX(step); } return min_shift; } //---------------------------------------------------------------------------- // Fast Fourier Transform //---------------------------------------------------------------------------- wxPlotData wxPlotData::FFT( bool forward ) { wxCHECK_MSG( Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); wxCHECK_MSG( GetCount() < 2, wxPlotData(), wxT("Invalid wxPlotData size") ); // Find the next highest 2^n power int samples = 1; int orig_count = M_PLOTDATA->m_count; while (samples < orig_count) samples *= 2; wxPlotData source; source.Copy(*this); // resize the curve to the 2^n sample size required by fft_double if (samples > orig_count) { double dx = M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0]; source.Resize(samples, dx, M_PLOTDATA->m_Ydata[orig_count - 1]); } wxPlotData trans(samples); trans.SetYiData( (double*)malloc(samples*sizeof(double)) ); if (fft_double( samples, (forward ? 0 : 1), source.GetYData(), source.GetYiData(), trans.GetYData(), trans.GetYiData() ) == 0) return wxPlotData(); if (forward) { double *trans_xData = trans.GetXData(); trans_xData[0] = 0.0; double timestep = (M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0])*samples; for (int i=0; im_Xdata[1] - M_PLOTDATA->m_Xdata[0])*double(samples)); for (int i=0; i%lg"), hi); case FilterButterworth : return wxString::Format(wxT("1 - 1/(1+(x/%lg)^(2*%lg))"), hi, n); case FilterGaussian : return wxString::Format(wxT("exp(-(%lg^2)/(2*x*x))"), hi); case FilterFermi : return wxString::Format(wxT("1/(1+exp((%lg-x)/%lg))"), hi, n); default : break; } return wxEmptyString; } wxString wxPlotData::FFTLoPassFilterFormat( double lo, wxPlotData::FFTFilter_Type filter, double n ) { switch (filter) { case FilterStep : return wxString::Format(wxT("x<%lg"), lo); case FilterButterworth : return wxString::Format(wxT("1/(1+(x/%lg)^(2*%lg))"), lo, n); case FilterGaussian : return wxString::Format(wxT("1 - exp(-(%lg^2)/(2*x*x))"), lo); case FilterFermi : return wxString::Format(wxT("1/(1+exp((%lg-x)/(-%lg)))"), lo, n); default : break; } return wxEmptyString; } wxString wxPlotData::FFTNotchFilterFormat( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n ) { switch (filter) { case FilterStep : return wxString::Format(wxT("(x<%lg)|(x>%lg)"), lo, hi); case FilterButterworth : return wxString::Format(wxT("1/(1+(x/%lg)^(2*%lg)) + (1-1/(1+(x/%lg)^(2*%lg)))"), lo, n, hi, n); case FilterGaussian : return wxString::Format(wxT("2-(exp(-(%lg^2)/(2*x*x))+(1-exp(-(%lg^2)/(2*x*x))))"), lo, hi); case FilterFermi : return wxString::Format(wxT("1/(1+exp((%lg-x)/(-%lg))) + 1/(1+exp((%lg-x)/(%lg)))"), lo, n, hi, n); default : break; } return wxEmptyString; } wxString wxPlotData::FFTBandPassFilterFormat( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n ) { switch (filter) { case FilterStep : return wxString::Format(wxT("(x>%lg)&(x<%lg)"), lo, hi); case FilterButterworth : return wxString::Format(wxT("1 - (1/(1+(x/%lg)^(2*%lg))+(1-1/(1+(x/%lg)^(2*%lg))))"), lo, n, hi, n); case FilterGaussian : return wxString::Format(wxT("exp(-(%lg^2)/(2*x*x)) - exp(-(%lg^2)/(2*x*x))"), lo, hi); case FilterFermi : return wxString::Format(wxT("1 - 1/(1+exp((%lg-x)/(-%lg))) - 1/(1+exp((%lg-x)/(%lg)))"), lo, n, hi, n); default : break; } return wxEmptyString; } // butterworth lo=1./(1.+ (x/fc)**(2*n)), hi=1-1./(1.+ (x/fc)**(2*n)) // gaussian lo = 1.0-exp(-fc**2/(2.*x**2)), hi = exp(-fc**2/(2.*x**2)) // fermi lo= 1/(1+exp[(fc-x)/n]) , hi = 1/(1+exp((x-fc)/(-n))) wxPlotData wxPlotData::FFTHiPassFilter( double fc, wxPlotData::FFTFilter_Type filter, double n ) { wxCHECK_MSG( Ok() && (n>0), wxPlotData(), wxT("Invalid wxPlotData") ); wxPlotData xform( FFT(true) ); int i, count = xform.GetCount(); double f, x; double *ydata = xform.GetYData(), *yidata = xform.GetYiData(); for (i=0; im_Xdata[0]); dest.CalcBoundingRect(); return dest; } wxPlotData wxPlotData::FFTLoPassFilter( double fc, wxPlotData::FFTFilter_Type filter, double n ) { wxCHECK_MSG( Ok() && (n>0), wxPlotData(), wxT("Invalid wxPlotData") ); wxPlotData xform( FFT(true) ); int i, count = xform.GetCount(); double f, x; double *ydata = xform.GetYData(), *yidata = xform.GetYiData(); for (i=0; i fc)) { *ydata = 0; *yidata = 0; } else { if (filter == FilterButterworth) f = 1.0/(1.0 + pow(x/fc, 2.0*n)); else if (filter == FilterGaussian) f = 1.0 - exp(-fc*fc/(2.0*x*x)); else // (filter == FilterFermi) f = 1.0/(1.0+exp((fc-x)/(-n))); *ydata *= f; *yidata *= f; } ydata++; yidata++; } wxPlotData dest( xform.FFT(false) ); dest.OffsetX(M_PLOTDATA->m_Xdata[0]); dest.CalcBoundingRect(); return dest; } wxPlotData wxPlotData::FFTNotchFilter( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n ) { wxCHECK_MSG( Ok() && (lo <= hi) && (n>0), wxPlotData(), wxT("Invalid wxPlotData") ); wxPlotData xform( FFT(true) ); int i, count = xform.GetCount(); double x, f; double *ydata = xform.GetYData(), *yidata = xform.GetYiData(); for (i=0; i= lo) && (x <= hi))) { *ydata = 0; *yidata = 0; } else { if (filter == FilterButterworth) f = 1.0/(1.0 + pow(x/lo, 2.0*n)) + (1.0-1.0/(1.0 + pow(x/hi, 2.0*n))); else if (filter == FilterGaussian) f = 2.0 - (exp(-lo*lo/(2.0*x*x)) + (1.0 - exp(-hi*hi/(2.0*x*x)))); else // (filter == FilterFermi) f = 1.0/(1.0+exp((lo-x)/(-n))) + 1.0/(1.0+exp((hi-x)/(n))); *ydata *= f; *yidata *= f; } ydata++; yidata++; } wxPlotData dest( xform.FFT(false) ); dest.OffsetX(M_PLOTDATA->m_Xdata[0]); dest.CalcBoundingRect(); return dest; } wxPlotData wxPlotData::FFTBandPassFilter( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n ) { wxPlotData xform; wxCHECK_MSG( Ok() && (lo <= hi) && (n>0), xform, wxT("Invalid wxPlotData") ); xform = FFT(true); if (!xform.Ok()) return xform; int i, count = xform.GetCount(); double x, f; double *xform_xdata = xform.GetXData(), *xform_ydata = xform.GetYData(), *xform_yidata = xform.GetYiData(); for (i=0; i= hi))) { *xform_ydata = 0; *xform_yidata = 0; } else { if (filter == FilterButterworth) f = 1.0-(1.0/(1.0 + pow(x/lo, 2.0*n)) + (1.0-1.0/(1.0 + pow(x/hi, 2.0*n)))); else if (filter == FilterGaussian) f = exp(-lo*lo/(2.0*x*x)) - exp(-hi*hi/(2.0*x*x)); else // (filter == FilterFermi) f = 1.0 - 1.0/(1.0+exp((lo-x)/(-n))) - 1.0/(1.0+exp((hi-x)/(n))); *xform_ydata *= f; *xform_yidata *= f; } xform_ydata++; xform_yidata++; } wxPlotData dst( xform.FFT(false) ); if (!dst.Ok()) return dst; dst.OffsetX(M_PLOTDATA->m_Xdata[0]); dst.CalcBoundingRect(); return dst; } wxPlotData wxPlotData::FFTCustomFilter( const wxPlotFunction &func ) { wxCHECK_MSG(Ok() && func.Ok(), wxPlotData(), wxT("invalid curve")); wxPlotData xform = FFT(true); if (!xform.Ok()) return xform; xform = xform.Modify(func, mult_y); if (!xform.Ok()) return xform; xform = xform.Modify(func, mult_yi); if (!xform.Ok()) return xform; wxPlotData dst( xform.FFT(false) ); if (!dst.Ok()) return dst; dst.OffsetX(M_PLOTDATA->m_Xdata[0]); dst.CalcBoundingRect(); return dst; } bool wxPlotData::SortByX() { wxCHECK_MSG( Ok(), false, wxT("Invalid wxPlotData") ); IMPLEMENT_PIXEL_QSORT2(double, M_PLOTDATA->m_Xdata, M_PLOTDATA->m_Ydata, M_PLOTDATA->m_count); return true; } bool wxPlotData::SortByY() { wxCHECK_MSG( Ok(), false, wxT("Invalid wxPlotData") ); IMPLEMENT_PIXEL_QSORT2(double, M_PLOTDATA->m_Ydata, M_PLOTDATA->m_Xdata, M_PLOTDATA->m_count); return true; } //------------------------------------------------------------------------- // Curve fitting //------------------------------------------------------------------------- /* #include "amoeba.h" static wxPlotFunction s_amoebaPlotFunc; static wxPlotData s_amoebaPlotData; double amoema_func( double *vars ) { double diff = 0; int i, count = s_amoebaPlotData.GetCount(); double *x_data = s_amoebaPlotData.GetXData(); double *y_data = s_amoebaPlotData.GetYData(); \ int ndim = s_amoebaPlotFunc.GetNumberVariables(); for (i=0; im_normalSymbol, wxT("Invalid wxPlotData") ); switch (colour_type) { case wxPLOTPEN_ACTIVE : return M_PLOTDATA->m_activeSymbol; case wxPLOTPEN_SELECTED : return M_PLOTDATA->m_selectedSymbol; default : break; //case wxPLOTPEN_NORMAL : } return M_PLOTDATA->m_normalSymbol; } void wxPlotData::SetSymbol( const wxBitmap &bitmap, wxPlotPen_Type colour_type ) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); wxCHECK_RET( bitmap.Ok(), wxT("Invalid bitmap") ); switch (colour_type) { case wxPLOTPEN_ACTIVE : M_PLOTDATA->m_activeSymbol = bitmap; break; case wxPLOTPEN_SELECTED : M_PLOTDATA->m_selectedSymbol = bitmap; break; default : //case wxPLOTPEN_NORMAL : M_PLOTDATA->m_normalSymbol = bitmap; break; } } void wxPlotData::SetSymbol( wxPlotSymbol_Type type, wxPlotPen_Type colour_type, int width , int height, const wxPen *pen, const wxBrush *brush) { wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); switch (colour_type) { case wxPLOTPEN_ACTIVE : M_PLOTDATA->m_activeSymbol = CreateSymbol(type, colour_type, width, height, pen, brush); break; case wxPLOTPEN_SELECTED : M_PLOTDATA->m_selectedSymbol = CreateSymbol(type, colour_type, width, height, pen, brush); break; default : //case wxPLOTPEN_NORMAL : M_PLOTDATA->m_normalSymbol = CreateSymbol(type, colour_type, width, height, pen, brush); break; } } wxBitmap wxPlotData::CreateSymbol( wxPlotSymbol_Type type, wxPlotPen_Type colour_type, int width, int height, const wxPen *pen, const wxBrush *brush) { wxBitmap b(width, height); wxMemoryDC mdc; mdc.SelectObject(b); mdc.SetPen(*wxWHITE_PEN); mdc.SetBrush(*wxWHITE_BRUSH); mdc.DrawRectangle(0, 0, width, height); /* if (pen) mdc.SetPen(*pen); else mdc.SetPen(GetNormalPen()); */ switch (type) { case wxPLOTSYMBOL_ELLIPSE : { mdc.DrawEllipse(width/2, height/2, width/2, height/2); break; } case wxPLOTSYMBOL_RECTANGLE : { mdc.DrawRectangle(0, 0, width, height); break; } case wxPLOTSYMBOL_CROSS : { mdc.DrawLine(0, 0, width , height); mdc.DrawLine(0, height, width, 0); break; } case wxPLOTSYMBOL_PLUS : { mdc.DrawLine(0, height/2, width, height/2); mdc.DrawLine(width/2, 0, width/2, height); break; } default : break; } b.SetMask(new wxMask(b, *wxWHITE)); return b; } // ---------------------------------------------------------------------------- // Functions for the wxClipboard // ---------------------------------------------------------------------------- #include "wx/clipbrd.h" #if wxUSE_DATAOBJ && wxUSE_CLIPBOARD const wxChar* wxDF_wxPlotData = wxT("wxDF_wxPlotData"); static wxPlotData s_clipboardwxPlotData; // temp storage of clipboard data static wxString s_clipboardwxPlotData_data; // holds wxNow() to match clipboard data // For some strange reason you get a segfault destroying s_clipboardwxPlotData // using gcc 3.4 at least. Using a wxModule to destroy it fixes this. //#0 0x40aefee1 in posix_memalign () from /lib/tls/libc.so.6 //#1 0x40aedd4c in mallopt () from /lib/tls/libc.so.6 //#2 0x40aeb8ba in free () from /lib/tls/libc.so.6 //#3 0x4060e885 in ~wxPlotDataRefData (this=0x82bc4b0) at plotcurve.cpp:203 //#4 0x40518d1a in wxObject::UnRef() (this=0x40630ef4) at src/common/object.cpp:309 //#5 0x0809d0e4 in ~wxObject (this=0x40630ef4) at object.h:431 //#6 0x4061cd42 in ~wxPlotCurve (this=0x40630ef4) at plotcurve.h:110 //#7 0x4061c43c in ~wxPlotData (this=0x40630ef4) at plotcurve.h:297 //#8 0x4061c247 in __tcf_7 () at plotcurve.cpp:3044 #include "wx/module.h" class wxPlotDataModule: public wxModule { DECLARE_DYNAMIC_CLASS(wxPlotDataModule) public: wxPlotDataModule() : wxModule() {} bool OnInit() { return true; } void OnExit() { s_clipboardwxPlotData.Destroy(); } }; IMPLEMENT_DYNAMIC_CLASS(wxPlotDataModule, wxModule) wxPlotData wxClipboardGetPlotData() { bool is_opened = wxTheClipboard->IsOpened(); wxPlotData plotData; if (is_opened || wxTheClipboard->Open()) { wxPlotDataObject plotDataObject; if (wxTheClipboard->IsSupported(wxDataFormat(wxDF_wxPlotData)) && wxTheClipboard->GetData(plotDataObject) && (plotDataObject.GetText() == s_clipboardwxPlotData_data)) { plotData.Copy(plotDataObject.GetPlotData(), true); } if (!is_opened) wxTheClipboard->Close(); } return plotData; } bool wxClipboardSetPlotData(const wxPlotData& plotData) { wxCHECK_MSG(plotData.Ok(), false, wxT("Invalid wxPlotData to copy to clipboard")); bool is_opened = wxTheClipboard->IsOpened(); if (is_opened || wxTheClipboard->Open()) { wxPlotDataObject *plotDataObject = new wxPlotDataObject(plotData); bool ret = wxTheClipboard->SetData( plotDataObject ); if (!is_opened) wxTheClipboard->Close(); return ret; } return false; } // ---------------------------------------------------------------------------- // wxPlotDataObject Clipboard object // ---------------------------------------------------------------------------- wxPlotDataObject::wxPlotDataObject() : wxTextDataObject() { SetFormat(wxDataFormat(wxDF_wxPlotData)); } wxPlotDataObject::wxPlotDataObject(const wxPlotData& plotData) : wxTextDataObject() { SetFormat(wxDataFormat(wxDF_wxPlotData)); SetPlotData(plotData); } wxPlotData wxPlotDataObject::GetPlotData() const { return s_clipboardwxPlotData; } void wxPlotDataObject::SetPlotData(const wxPlotData& plotData) { s_clipboardwxPlotData_data = wxNow(); SetText(s_clipboardwxPlotData_data); if (plotData.Ok()) s_clipboardwxPlotData.Copy(plotData, true); else s_clipboardwxPlotData.Destroy(); } #endif // wxUSE_DATAOBJ && wxUSE_CLIPBOARD gambit-0.2010.09.01/src/labenski/src/plotdraw.cpp0000644000076500007650000011616511441453421016157 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotdraw.cpp // Purpose: wxPlotDrawer and friends // Author: John Labenski // Modified by: // Created: 8/27/2002 // Copyright: (c) John Labenski // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "plotdraw.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/math.h" #include "wx/plotctrl/plotctrl.h" #include "wx/plotctrl/plotdraw.h" #include "wx/plotctrl/plotmark.h" #include #include #include // MSVC hogs global namespace with these min/max macros - remove them #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef GetYValue // Visual Studio 7 defines this #undef GetYValue #endif #define LONG_TO_WXCOLOUR(c) wxColour((unsigned char)((c>>16)&0xFF), (unsigned char)((c>>8 )&0xFF), (unsigned char)((c)&0xFF)) #define WXCOLOUR_TO_LONG(c) ((c.Red()<<16)|(c.Green()<<8)|(c.Blue())) #define RINT(x) int((x) >= 0 ? ((x) + 0.5) : ((x) - 0.5)) #if !wxCHECK_VERSION(2,5,0) bool WXRECT2DDOUBLE_EQUAL(const wxRect2DDouble& r1, const wxRect2DDouble& r2) { return (r1.m_x == r1.m_x) && (r1.m_y == r1.m_y) && (r1.m_width == r1.m_width) && (r1.m_height == r1.m_height); } #else #define WXRECT2DDOUBLE_EQUAL(r1, r2) ((r1) == (r2)) #endif // wxCHECK_VERSION(2,5,0) //----------------------------------------------------------------------------- // Consts //----------------------------------------------------------------------------- // Skip the wxWidgets drawing routines since they calc an unnecessary bounding rect // You may turn this off by defining wxPLOT_FAST_GRAPHICS=0 to the compilier #ifndef wxPLOT_FAST_GRAPHICS #define wxPLOT_FAST_GRAPHICS 0 #endif // wxPLOT_FAST_GRAPHICS #if defined(__WXGTK__) && wxPLOT_FAST_GRAPHICS extern "C" { #include } #define INITIALIZE_FAST_GRAPHICS \ double dc_scale_x = 1, dc_scale_y = 1; \ dc->GetUserScale( &dc_scale_x, &dc_scale_y ); \ wxPoint dc_origin = dc->GetDeviceOrigin(); \ wxWindowDC *winDC = wxDynamicCast(dc, wxWindowDC); \ GdkWindow *window = NULL; \ GdkGC *pen = NULL; \ if (winDC && (dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0,0))) \ { \ window = winDC->m_window; \ pen = winDC->m_penGC; \ } // inline void wxPLOT_DRAW_LINE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0, int x1, int y1) #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ if (win && pen) \ gdk_draw_line( win, pen, x0, y0, x1, y1 ); \ else \ dc->DrawLine( x0, y0, x1, y1 ); // note : need to draw outline since the filled part isn't really a circle // gdk_draw_arc( win, pen, false, x0-2, y0-2, 4, 4, 0, 360*64 ); // false for outline, true for inside //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0) #define wxPLOT_DRAW_ELLIPSE(dc, win, pen, x0, y0, w, h) \ if (win && pen) \ gdk_draw_arc( win, pen, false, (x0)-(w), (y0)-(h), (w)*2, (h)*2, 0, 360*64 ); \ else \ dc->DrawEllipse(x0, y0, w, h); #elif defined(__WXMSW__) && wxPLOT_FAST_GRAPHICS #define INITIALIZE_FAST_GRAPHICS \ double dc_scale_x = 1, dc_scale_y = 1; \ dc->GetUserScale( &dc_scale_x, &dc_scale_y ); \ wxPoint dc_origin = dc->GetDeviceOrigin(); \ HDC window = 0; \ if ((dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0,0))) \ window = (HDC)dc->GetHDC(); \ int pen = 0; pen = 0; // no unused var warning //inline void wxPLOT_DRAW_LINE(wxDC *dc, HDC win, int pen, int x0, int y0, int x1, int y1) #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ if (win) \ { \ (void)MoveToEx(win, x0, y0, NULL); \ (void)LineTo(win, x1, y1); \ } \ else \ dc->DrawLine( x0, y0, x1, y1 ); //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, HDC win, int pen, int x0, int y0) #define wxPLOT_DRAW_ELLIPSE(dc, win, pen, x0, y0, w, h) \ if (win) \ (void)Ellipse(win, (x0)-(w), (y0)-(w), (x0)+(w)*2, (y0)+(h)*2); \ else \ dc->DrawEllipse(x0, y0, w, h); #else // !wxPLOT_FAST_GRAPHICS or not gtk/msw #define INITIALIZE_FAST_GRAPHICS \ int window = 0; window = 0; \ int pen = 0; pen = 0; //inline void wxPLOT_DRAW_LINE(wxDC *dc, int win, int pen, int x0, int y0, int x1, int y1) #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ dc->DrawLine( x0, y0, x1, y1 ); //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, int win, int pen, int x0, int y0) #define wxPLOT_DRAW_ELLIPSE(dc, win, pen, x0, y0, w, h) \ dc->DrawEllipse(x0, y0, w, h); #endif // wxPLOT_FAST_GRAPHICS // differs from wxRect2DDouble::Intersects by allowing for 0 width or height inline bool wxPlotRect2DDoubleIntersects(const wxRect2DDouble &a, const wxRect2DDouble &b) { return (wxMax(a.m_x, b.m_x) <= wxMin(a.GetRight(), b.GetRight())) && (wxMax(a.m_y, b.m_y) <= wxMin(a.GetBottom(), b.GetBottom())); } // same as wxPlotRect2DDouble::Contains, but doesn't convert to wxPoint2DDouble inline bool wxPlotRect2DDoubleContains(double x, double y, const wxRect2DDouble &rect) { return ((x>=rect.m_x) && (y>=rect.m_y) && (x<=rect.GetRight()) && (y<=rect.GetBottom())); } // differs from wxRect2DDouble::GetOutCode by swaping top and bottom for plot origin //inline wxOutCode wxPlotRect2DDoubleOutCode( double x, double y, const wxRect2DDouble &rect ) //{ // return wxOutCode((x < rect.m_x ? wxOutLeft : // (x > rect.GetRight() ? wxOutRight : wxInside )) + // (y < rect.m_y ? wxOutTop : // (y > rect.GetBottom() ? wxOutBottom : wxInside )) ); //} #define wxPlotRect2DDoubleOutCode( x, y, rect ) \ wxOutCode(((x) < rect.m_x ? wxOutLeft : \ ((x) > rect.GetRight() ? wxOutRight : wxInside )) + \ ((y) < rect.m_y ? wxOutTop : \ ((y) > rect.GetBottom() ? wxOutBottom : wxInside )) ) // modified Cohen-Sutherland Algorithm for line clipping in at most two passes // the the original endless loop is too unstable // http://www.cc.gatech.edu/grads/h/Hao-wei.Hsieh/Haowei.Hsieh/code1.html for psuedo code // The line connecting (x0,y0)-(x1,y1) is clipped to rect and which // points were clipped is returned. enum ClipLine_Type { ClippedNeither = 0x0000, ClippedFirstX = 0x0001, ClippedFirstY = 0x0002, ClippedFirst = ClippedFirstX | ClippedFirstY, ClippedSecondX = 0x0010, ClippedSecondY = 0x0020, ClippedSecond = ClippedSecondX | ClippedSecondY, ClippedBoth = ClippedFirst | ClippedSecond, ClippedOut = 0x0100 // no intersection, so can't clip }; int ClipLineToRect( double &x0, double &y0, double &x1, double &y1, const wxRect2DDouble &rect ) { if (!wxFinite(x0) || !wxFinite(y0) || !wxFinite(x1) || !wxFinite(y1)) return ClippedOut; wxOutCode out0 = wxPlotRect2DDoubleOutCode( x0, y0, rect ); wxOutCode out1 = wxPlotRect2DDoubleOutCode( x1, y1, rect ); if ((out0 & out1) != wxInside) return ClippedOut; // both outside on same side if ((out0 | out1) == wxInside) return ClippedNeither; // both inside int ret = ClippedNeither; if (x0 == x1) // vertical line { if (out0 & wxOutTop) {y0 = rect.GetTop(); ret |= ClippedFirstY;} else if (out0 & wxOutBottom) {y0 = rect.GetBottom(); ret |= ClippedFirstY;} if (out1 & wxOutTop) {y1 = rect.GetTop(); ret |= ClippedSecondY;} else if (out1 & wxOutBottom) {y1 = rect.GetBottom(); ret |= ClippedSecondY;} return ret; } if (y0 == y1) // horiz line { if (out0 & wxOutLeft) {x0 = rect.GetLeft(); ret |= ClippedFirstX;} else if (out0 & wxOutRight) {x0 = rect.GetRight(); ret |= ClippedFirstX;} if (out1 & wxOutLeft) {x1 = rect.GetLeft(); ret |= ClippedSecondX;} else if (out1 & wxOutRight) {x1 = rect.GetRight(); ret |= ClippedSecondX;} return ret; } double x = x0, y = y0; wxOutCode out = out0; int points_out = 2; bool out0_outside = true; if (out0 == wxInside) { out0_outside = false; points_out = 1; out = out1; } else if (out1 == wxInside) points_out = 1; for (int i=0; ix1 = x1_; stack_top->y1 = y1_; \ stack_top->x2 = x2_; stack_top->y2 = y2_; \ stack_top->x3 = x3_; stack_top->y3 = y3_; \ stack_top->x4 = x4_; stack_top->y4 = y4_; \ stack_top++; \ m_stack_count++; #define SPLINE_POP(x1_, y1_, x2_, y2_, x3_, y3_, x4_, y4_) \ stack_top--; \ m_stack_count--; \ x1_ = stack_top->x1; y1_ = stack_top->y1; \ x2_ = stack_top->x2; y2_ = stack_top->y2; \ x3_ = stack_top->x3; y3_ = stack_top->y3; \ x4_ = stack_top->x4; y4_ = stack_top->y4; class SplineDrawer { public: SplineDrawer() : m_dc(NULL) { } // the wxRect2DDouble rect is the allowed dc area in pixel coords // wxRangeDoubleSelection is the ranges to use selPen, also in pixel coords // x1_, y1_, x2_, y2_ are the first 2 points to draw void Create(wxDC *dc, const wxPen &curPen, const wxPen &selPen, const wxRect2DDouble &rect, wxRangeDoubleSelection *rangeSel, double x1_, double y1_, double x2_, double y2_) { m_dc = dc; wxCHECK_RET( dc, wxT("invalid window dc") ); m_selPen = selPen; m_curPen = curPen; m_rangeSel = rangeSel; m_rect = rect; m_stack_count = 0; m_x1 = x1_; m_y1 = y1_; m_x2 = x2_; m_y2 = y2_; m_cx1 = (m_x1 + m_x2) / 2.0; m_cy1 = (m_y1 + m_y2) / 2.0; m_cx2 = (m_cx1 + m_x2) / 2.0; m_cy2 = (m_cy1 + m_y2) / 2.0; m_last_x = m_x1; m_last_y = m_y1; } // actually do the drawing here void DrawSpline(double x, double y); // After the last point call this to finish the drawing void EndSpline() { wxCHECK_RET( m_dc, wxT("invalid window dc") ); if (ClipLineToRect(m_cx1, m_cy1, m_x2, m_y2, m_rect) != ClippedOut) m_dc->DrawLine((int)m_cx1, (int)m_cy1, (int)m_x2, (int)m_y2); } private: typedef struct SplineStack { double x1, y1, x2, y2, x3, y3, x4, y4; } SplineStack; wxDC *m_dc; wxRect2DDouble m_rect; SplineStack m_splineStack[SPLINE_STACK_DEPTH]; int m_stack_count; double m_cx1, m_cy1, m_cx2, m_cy2, m_cx3, m_cy3, m_cx4, m_cy4; double m_x1, m_y1, m_x2, m_y2; double m_last_x, m_last_y; wxPen m_selPen, m_curPen; wxRangeDoubleSelection *m_rangeSel; }; void SplineDrawer::DrawSpline( double x, double y ) { wxCHECK_RET( m_dc, wxT("invalid window dc") ); wxPen oldPen = m_dc->GetPen(); bool is_selected = (oldPen == m_selPen); m_x1 = m_x2; m_y1 = m_y2; m_x2 = x; m_y2 = y; m_cx4 = (m_x1 + m_x2) / 2.0; m_cy4 = (m_y1 + m_y2) / 2.0; m_cx3 = (m_x1 + m_cx4) / 2.0; m_cy3 = (m_y1 + m_cy4) / 2.0; double xmid, ymid; double xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4; SplineStack *stack_top = m_splineStack; m_stack_count = 0; SPLINE_PUSH(m_cx1, m_cy1, m_cx2, m_cy2, m_cx3, m_cy3, m_cx4, m_cy4); while (m_stack_count > 0) { SPLINE_POP(xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4); xmid = (xx2 + xx3)/2.0; ymid = (yy2 + yy3)/2.0; if ((fabs(xx1 - xmid) < THRESHOLD) && (fabs(yy1 - ymid) < THRESHOLD) && (fabs(xmid - xx4) < THRESHOLD) && (fabs(ymid - yy4) < THRESHOLD)) { // FIXME - is this really necessary, better safe than sorry? double t1_last_x = m_last_x; double t1_last_y = m_last_y; double t1_xx1 = xx1; double t1_yy1 = yy1; if (ClipLineToRect(t1_last_x, t1_last_y, t1_xx1, t1_yy1, m_rect) != ClippedOut) { if (m_rangeSel && (m_rangeSel->Contains((m_last_x + xx1)/2) != is_selected)) { is_selected = is_selected ? false : true; if (is_selected) m_dc->SetPen(m_selPen); else m_dc->SetPen(m_curPen); } m_dc->DrawLine((int)t1_last_x, (int)t1_last_y, (int)t1_xx1, (int)t1_yy1); } double t2_xx1 = xx1; double t2_yy1 = yy1; double t2_xmid = xmid; double t2_ymid = ymid; if (ClipLineToRect(t2_xx1, t2_yy1, t2_xmid, t2_ymid, m_rect) != ClippedOut) { if (m_rangeSel && (m_rangeSel->Contains((xx1+xmid)/2) != is_selected)) { is_selected = is_selected ? false : true; if (is_selected) m_dc->SetPen(m_selPen); else m_dc->SetPen(m_curPen); } m_dc->DrawLine((int)t2_xx1, (int)t2_yy1, (int)t2_xmid, (int)t2_ymid); } m_last_x = xmid; m_last_y = ymid; } else { wxCHECK_RET(m_stack_count < SPLINE_STACK_DEPTH - 2, wxT("Spline stack overflow")); SPLINE_PUSH(xmid, ymid, (xmid + xx3)/2.0, (ymid + yy3)/2.0, (xx3 + xx4)/2.0, (yy3 + yy4)/2.0, xx4, yy4); SPLINE_PUSH(xx1, yy1, (xx1 + xx2)/2.0, (yy1 + yy2)/2.0, (xx2 + xmid)/2.0, (yy2 + ymid)/2.0, xmid, ymid); } } m_cx1 = m_cx4; m_cy1 = m_cy4; m_cx2 = (m_cx1 + m_x2) / 2.0; m_cy2 = (m_cy1 + m_y2) / 2.0; m_dc->SetPen(oldPen); } //*************************************************************************** //----------------------------------------------------------------------------- // wxPlotDrawerAxisBase //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerBase, wxObject) wxPlotDrawerAxisBase::wxPlotDrawerAxisBase(wxPlotCtrl* owner) :wxPlotDrawerBase(owner) { m_tickFont = *wxNORMAL_FONT; m_labelFont = *wxSWISS_FONT; m_tickColour = wxGenericColour(0,0,0); m_labelColour = wxGenericColour(0,0,0); m_tickPen = wxGenericPen(m_tickColour, wxSOLID); m_backgroundBrush = wxGenericBrush(wxGenericColour(255,255,255), wxSOLID); } //----------------------------------------------------------------------------- // wxPlotDrawerArea //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerArea, wxPlotDrawerBase) void wxPlotDrawerArea::Draw(wxDC *dc, bool refresh) { } //----------------------------------------------------------------------------- // wxPlotDrawerAxisBase //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerAxisBase, wxPlotDrawerBase) //----------------------------------------------------------------------------- // wxPlotDrawerXAxis //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerXAxis, wxPlotDrawerAxisBase) void wxPlotDrawerXAxis::Draw(wxDC *dc, bool refresh) { wxCHECK_RET(dc, wxT("Invalid dc")); wxRect dcRect(GetDCRect()); // Draw background if (refresh) { dc->SetBrush(m_backgroundBrush.GetBrush()); dc->SetPen(*wxTRANSPARENT_PEN); dc->DrawRectangle(dcRect); } wxFont tickFont = m_tickFont; if (m_font_scale != 1) tickFont.SetPointSize( wxMax(2, RINT(tickFont.GetPointSize() * m_font_scale)) ); wxPoint dcOrigin(dc->GetDeviceOrigin()); dc->SetDeviceOrigin(dcRect.x, dcRect.y); dc->SetTextForeground( m_tickColour.GetColour() ); dc->SetFont( tickFont ); wxString label; // center the text in the window int x, y; dc->GetTextExtent(wxT("5"), &x, &y); int y_pos = (GetDCRect().height - y)/2 + 2; // FIXME I want to center this // double current = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step; int i, count = m_tickPositions.GetCount(); for (i=0; iDrawText(m_tickLabels[i], m_tickPositions[i], y_pos); // if (!IsFinite(current, wxT("axis label is not finite"))) // break; // label.Printf( m_xAxisTickFormat.c_str(), current ); // dc->DrawText(label, m_xAxisTicks[i], y_pos); // current += m_xAxisTick_step; } #ifdef DRAW_BORDERS // Test code for sizing to show the extent of the axes dc->SetBrush( *wxTRANSPARENT_BRUSH ); dc->SetPen( wxPen(GetBorderColour(), 1, wxSOLID) ); dc->DrawRectangle(wxRect(wxPoint(0,0), clientSize)); #endif // DRAW_BORDERS dc->SetDeviceOrigin(dcOrigin.x, dcOrigin.y); } //----------------------------------------------------------------------------- // wxPlotDrawerYAxis //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerYAxis, wxPlotDrawerAxisBase) void wxPlotDrawerYAxis::Draw(wxDC *dc, bool refresh) { wxCHECK_RET(dc, wxT("Invalid dc")); wxRect dcRect(GetDCRect()); // Draw background if (refresh) { dc->SetBrush(m_backgroundBrush.GetBrush()); dc->SetPen(*wxTRANSPARENT_PEN); dc->DrawRectangle(dcRect); } wxFont tickFont = m_tickFont; if (m_font_scale != 1) tickFont.SetPointSize( wxMax(2, RINT(tickFont.GetPointSize() * m_font_scale)) ); wxPoint dcOrigin(dc->GetDeviceOrigin()); dc->SetDeviceOrigin(dcRect.x, dcRect.y); dc->SetTextForeground( m_tickColour.GetColour() ); dc->SetFont( tickFont ); wxString label; // double current = ceil(m_viewRect.GetTop() / m_yAxisTick_step) * m_yAxisTick_step; int i, count = m_tickLabels.GetCount(); for (i=0; iDrawText( m_tickLabels[i], 2, m_tickPositions[i] ); // if (!IsFinite(current, wxT("axis label is not finite"))) // break; // label.Printf( m_yAxisTickFormat.c_str(), current); // dc->DrawText( label, 2, m_yAxisTicks[i] ); // current += m_yAxisTick_step; } #ifdef DRAW_BORDERS // Test code for sizing to show the extent of the axes dc->SetBrush( *wxTRANSPARENT_BRUSH ); dc->SetPen( wxPen(GetBorderColour(), 1, wxSOLID) ); dc->DrawRectangle(wxRect(wxPoint(0,0), clientSize)); #endif // DRAW_BORDERS dc->SetDeviceOrigin(dcOrigin.x, dcOrigin.y); } //----------------------------------------------------------------------------- // wxPlotDrawerKey //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerKey, wxPlotDrawerBase) wxPlotDrawerKey::wxPlotDrawerKey(wxPlotCtrl* owner) :wxPlotDrawerBase(owner) { m_font = *wxNORMAL_FONT; m_fontColour = wxGenericColour(0, 0, 0); m_keyPosition = wxPoint(100, 100); m_border = 5; m_key_inside = true; m_key_line_width = 20; m_key_line_margin = 5; } void wxPlotDrawerKey::Draw(wxDC *dc, const wxString& keyString_) { wxCHECK_RET(dc && m_owner, wxT("Invalid dc")); if (keyString_.IsEmpty()) return; wxString keyString = keyString_; /* // GTK - kills X if font size is too small double x_scale = 1, y_scale = 1; dc->GetUserScale( &x_scale, &y_scale ); wxFont font = m_owner->GetKeyFont(); if (0 && x_scale != 1) { font.SetPointSize(wxMax(int(font.GetPointSize()/x_scale), 4)); if (!font.Ok()) font = GetKeyFont(); } */ wxFont keyFont = m_font; if (m_font_scale != 1) keyFont.SetPointSize( wxMax(2, RINT(keyFont.GetPointSize() * m_font_scale)) ); int key_line_width = RINT(m_key_line_width * m_pen_scale); int key_line_margin = RINT(m_key_line_margin * m_pen_scale); dc->SetFont(keyFont); dc->SetTextForeground(m_fontColour.GetColour()); wxRect keyRect; int heightLine = 0; dc->GetMultiLineTextExtent(keyString, &keyRect.width, &keyRect.height, &heightLine); wxRect dcRect(GetDCRect()); wxSize areaSize = dcRect.GetSize(); keyRect.x = 30 + int((m_keyPosition.x*.01)*areaSize.x); keyRect.y = areaSize.y - int((m_keyPosition.y*.01)*areaSize.y); if (m_key_inside) { keyRect.x = wxMax(30, keyRect.x); keyRect.x = wxMin(areaSize.x - keyRect.width - m_border, keyRect.GetRight()); keyRect.y = wxMax(m_border, keyRect.y); keyRect.y = wxMin(areaSize.y - keyRect.height - m_border, keyRect.y); } int h = keyRect.y; int i = 0; while (!keyString.IsEmpty()) { wxString subkey = keyString.BeforeFirst(wxT('\n')).Strip(wxString::both); keyString = keyString.AfterFirst(wxT('\n')); if (subkey.IsEmpty()) break; if (m_owner && m_owner->GetCurve(i)) { wxPen keyPen = m_owner->GetCurve(i)->GetPen(wxPLOTPEN_NORMAL).GetPen(); if (m_pen_scale != 1) keyPen.SetWidth(int(keyPen.GetWidth() * m_pen_scale)); if(keyPen.GetWidth() < 3) keyPen.SetWidth(3); dc->SetPen(keyPen); dc->DrawLine(keyRect.x - (key_line_width + key_line_margin), h + heightLine/2, keyRect.x - key_line_margin, h + heightLine/2); } dc->DrawText(subkey, keyRect.x, h); h += heightLine; i++; } dc->SetPen(wxNullPen); dc->SetFont(wxNullFont); } //----------------------------------------------------------------------------- // wxPlotDrawerCurve //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerCurve, wxPlotDrawerBase) void wxPlotDrawerCurve::Draw(wxDC *dc, wxPlotCurve *curve, int curve_index) { wxCHECK_RET(dc && m_owner && curve && curve->Ok(), wxT("invalid curve")); INITIALIZE_FAST_GRAPHICS wxRect dcRect(GetDCRect()); int i, j0, j1; double x0, y0, x1, y1, yy0, yy1; x0 = m_owner->GetPlotCoordFromClientX(0); y0 = yy0 = curve->GetY(x0); //wxRect2DDouble viewRect = m_viewRect; wxRect2DDouble subViewRect = m_owner->GetPlotRectFromClientRect( dcRect ); //printf("curve rect %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height); fflush(stdout); //printf("curve subviewrect %lf %lf %lf %lf\n", subViewRect.m_x, subViewRect.m_y, subViewRect.m_width, subViewRect.m_height); fflush(stdout); int right = dcRect.GetRight(); wxPen currentPen = (curve_index == m_owner->GetActiveIndex()) ? curve->GetPen(wxPLOTPEN_ACTIVE).GetPen() : curve->GetPen(wxPLOTPEN_NORMAL).GetPen(); wxPen selectedPen = curve->GetPen(wxPLOTPEN_SELECTED).GetPen(); if (m_pen_scale != 1) { currentPen.SetWidth(int(currentPen.GetWidth() * m_pen_scale)); selectedPen.SetWidth(int(selectedPen.GetWidth() * m_pen_scale)); } dc->SetPen(currentPen); const wxRangeDoubleSelection *ranges = m_owner->GetCurveSelection(curve_index); bool selected = false; int clipped = ClippedNeither; for (i=dcRect.x; iGetPlotCoordFromClientX(i); y1 = yy1 = curve->GetY(x1); clipped = ClipLineToRect(x0, yy0, x1, yy1, subViewRect); if (selected != ranges->Contains(x1)) { if (selected) dc->SetPen(currentPen); else dc->SetPen(selectedPen); selected = !selected; } if (clipped != ClippedOut) { j0 = m_owner->GetClientCoordFromPlotY(yy0); j1 = m_owner->GetClientCoordFromPlotY(yy1); wxPLOT_DRAW_LINE(dc, window, pen, i-1, j0, i, j1); if (selected && !((clipped & ClippedSecond) != 0)) { wxPLOT_DRAW_ELLIPSE(dc, window, pen, i, j1, 2, 2); } } x0 = x1; y0 = yy0 = y1; } dc->SetPen(wxNullPen); } //----------------------------------------------------------------------------- // wxPlotDrawerDataCurve //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerDataCurve, wxPlotDrawerBase) void wxPlotDrawerDataCurve::Draw(wxDC *dc, wxPlotData* curve, int curve_index) { wxCHECK_RET(dc && m_owner && curve && curve->Ok(), wxT("invalid curve")); INITIALIZE_FAST_GRAPHICS wxRect dcRect(GetDCRect()); wxRect2DDouble viewRect( GetPlotViewRect() ); //m_viewRect ); wxRect2DDouble subViewRect( m_owner->GetPlotRectFromClientRect(dcRect) ); wxRect2DDouble curveRect( curve->GetBoundingRect() ); if (!wxPlotRect2DDoubleIntersects(curveRect, subViewRect)) return; /* // FIXME - drawing symbol bitmaps in MSW is very slow wxBitmap bitmap; if (curve == GetActiveCurve()) bitmap = curve->GetSymbol(wxPLOTPEN_ACTIVE); else bitmap = curve->GetSymbol(wxPLOTPEN_NORMAL); if (!bitmap.Ok()) { if (curve == GetActiveCurve()) bitmap = wxPlotSymbolCurrent; else bitmap = wxPlotSymbolNormal; } int bitmapHalfWidth = bitmap.GetWidth()/2; int bitmapHalfHeight = bitmap.GetHeight()/2; */ // find the starting and ending indexes into the data curve int n, n_start, n_end; bool x_ordered = curve->GetIsXOrdered(); if (x_ordered) { n_start = curve->GetIndexFromX(subViewRect.GetLeft(), wxPlotData::index_floor); n_end = curve->GetIndexFromX(subViewRect.GetRight(), wxPlotData::index_ceil); n_end++; // for statement comparison is < } else { n_start = 0; n_end = curve->GetCount(); } // set the pens to draw with wxPen currentPen = (curve_index == m_owner->GetActiveIndex()) ? curve->GetPen(wxPLOTPEN_ACTIVE).GetPen() : curve->GetPen(wxPLOTPEN_NORMAL).GetPen(); wxPen selectedPen = curve->GetPen(wxPLOTPEN_SELECTED).GetPen(); if (m_pen_scale != 1) { currentPen.SetWidth(int(currentPen.GetWidth() * m_pen_scale)); selectedPen.SetWidth(int(selectedPen.GetWidth() * m_pen_scale)); } dc->SetPen(currentPen); // handle the selected ranges and initialize the starting range const wxArrayRangeInt &ranges = m_owner->GetDataCurveSelection(curve_index)->GetRangeArray(); int n_range = 0, range_count = ranges.GetCount(); int min_sel = -1, max_sel = -1; for (n_range=0; n_range= n_start) || (range.m_min >= n_start)) { min_sel = range.m_min; max_sel = range.m_max; if (range.Contains(n_start)) dc->SetPen( selectedPen ); break; } } // data variables const double *x_data = &curve->GetXData()[n_start]; const double *y_data = &curve->GetYData()[n_start]; int i0, j0, i1, j1; // curve coords in pixels double x0, y0, x1, y1; // original curve coords double xx0, yy0, xx1, yy1; // clipped curve coords x0 = *x_data; y0 = *y_data; int clipped = ClippedNeither; bool draw_lines = m_owner->GetDrawLines(); bool draw_symbols = m_owner->GetDrawSymbols(); bool draw_spline = m_owner->GetDrawSpline(); SplineDrawer sd; wxRangeDoubleSelection dblRangeSel; if (draw_spline) { wxRangeDouble viewRange(viewRect.m_x, viewRect.GetRight()); wxRangeDouble dcRange(dcRect.x, dcRect.GetRight()); for (int r = n_range; r < range_count; r++) { wxRangeDouble plotRange(curve->GetXValue(ranges[r].m_min), curve->GetXValue(ranges[r].m_max)); if (viewRange.Intersects(plotRange)) { double min_x = m_owner->GetClientCoordFromPlotX(plotRange.m_min); double max_x = m_owner->GetClientCoordFromPlotX(plotRange.m_max); dblRangeSel.SelectRange(wxRangeDouble(min_x, max_x)); } else break; } // spline starts 2 points back for smoothness int s_start = n_start > 1 ? -2 : n_start > 0 ? -1 : 0; sd.Create(dc, currentPen, selectedPen, wxRect2DDouble(dcRect.x, dcRect.y, dcRect.width, dcRect.height), &dblRangeSel, m_owner->GetClientCoordFromPlotX(x_data[s_start]), m_owner->GetClientCoordFromPlotY(y_data[s_start]), m_owner->GetClientCoordFromPlotX(x_data[s_start+1]), m_owner->GetClientCoordFromPlotY(y_data[s_start+1])); } for (n = n_start; n < n_end; n++) { x1 = *x_data++; y1 = *y_data++; if (draw_spline) sd.DrawSpline(m_owner->GetClientCoordFromPlotX(x1), m_owner->GetClientCoordFromPlotY(y1)); xx0 = x0; yy0 = y0; xx1 = x1; yy1 = y1; clipped = ClipLineToRect(xx0, yy0, xx1, yy1, viewRect); if (clipped != ClippedOut) { i0 = m_owner->GetClientCoordFromPlotX(xx0); j0 = m_owner->GetClientCoordFromPlotY(yy0); i1 = m_owner->GetClientCoordFromPlotX(xx1); j1 = m_owner->GetClientCoordFromPlotY(yy1); if (draw_lines && ((i0 != i1) || (j0 != j1))) { wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i1, j1); } if (n == min_sel) dc->SetPen( selectedPen ); if (draw_symbols && !((clipped & ClippedSecond) != 0) && ((i0 != i1) || (j0 != j1) || (n == min_sel) || (n == n_start))) { //dc->DrawBitmap( bitmap, i1 - bitmapHalfWidth, j1 - bitmapHalfHeight, true ); wxPLOT_DRAW_ELLIPSE(dc, window, pen, i1, j1, 2, 2); } } else if (n == min_sel) { dc->SetPen( selectedPen ); } if (n == max_sel) { dc->SetPen( currentPen ); if (n_range < range_count - 1) { n_range++; min_sel = ranges[n_range].m_min; max_sel = ranges[n_range].m_max; } } x0 = x1; y0 = y1; } if (draw_spline) { // want an extra point at the end to smooth it out if (n_end < (int)curve->GetCount() - 1) sd.DrawSpline(m_owner->GetClientCoordFromPlotX(*x_data), m_owner->GetClientCoordFromPlotY(*y_data)); sd.EndSpline(); } dc->SetPen(wxNullPen); } //----------------------------------------------------------------------------- // wxPlotDrawerMarkers //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerMarker, wxPlotDrawerBase) void wxPlotDrawerMarker::Draw(wxDC *dc, const wxPlotMarker& marker) { // drawing multiple markers is faster, so just drawing a single one takes a hit wxArrayPlotMarker markers; markers.Add(marker); Draw(dc, markers); } void wxPlotDrawerMarker::Draw(wxDC *dc, const wxArrayPlotMarker& markers) { wxCHECK_RET(dc && m_owner, wxT("dc or owner")); INITIALIZE_FAST_GRAPHICS wxRect dcRect(GetDCRect()); wxRect2DDouble subViewRect = m_owner->GetPlotRectFromClientRect( dcRect ); double x0 = 0, y0 = 0, x1 = 0, y1 = 0; int n, count = markers.GetCount(); for (n = 0; n < count; n++) { const wxPlotMarker &marker = markers[n]; wxCHECK_RET(marker.Ok(), wxT("Invalid marker")); wxRect2DDouble r = marker.GetPlotRect(); x0 = r.m_x; y0 = r.m_y; x1 = r.GetRight(); y1 = r.GetBottom(); if (marker.GetPen().Ok()) dc->SetPen(marker.GetPen().GetPen()); if (marker.GetBrush().Ok()) dc->SetBrush(marker.GetBrush().GetBrush()); // determine what to draw int marker_type = marker.GetMarkerType(); wxSize size = marker.GetSize(); if (marker_type == wxPLOTMARKER_BITMAP) { wxBitmap bmp(marker.GetBitmap()); int w = bmp.GetWidth(), h = bmp.GetHeight(); // FIXME - add scaling and shifting later - maybe int i0 = m_owner->GetClientCoordFromPlotX(x0); int j0 = m_owner->GetClientCoordFromPlotY(y0); dc->DrawBitmap(bmp, RINT(i0 - w/2.0), RINT(j0 - h/2.0), true); } else if (marker_type == wxPLOTMARKER_LINE) { if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { int i0 = m_owner->GetClientCoordFromPlotX(x0); int j0 = m_owner->GetClientCoordFromPlotY(y0); int i1 = m_owner->GetClientCoordFromPlotX(x1); int j1 = m_owner->GetClientCoordFromPlotY(y1); wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i1, j1); } } else if (marker_type == wxPLOTMARKER_ELLIPSE) { // fixed pixel size if ((size.x > 0) && (size.y > 0)) { if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { int i0 = m_owner->GetClientCoordFromPlotX(x0); int j0 = m_owner->GetClientCoordFromPlotY(y0); wxPLOT_DRAW_ELLIPSE(dc, window, pen, i0, j0, size.x, size.y); } } /* else if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { int i0 = m_owner->GetClientCoordFromPlotX(x0); int j0 = m_owner->GetClientCoordFromPlotY(y0); int i1 = m_owner->GetClientCoordFromPlotX(x1); int j1 = m_owner->GetClientCoordFromPlotY(y1); wxPLOT_DRAW_ELLIPSE(dc, window, pen, i0, j0, i1, j1); } */ } else // figure out the rest { // we may ignore type if rect is in certain states bool is_horiz = r.m_width < 0; bool is_vert = r.m_height < 0; bool cross = is_horiz && is_vert; if (is_horiz) { x0 = subViewRect.m_x - subViewRect.m_width; // push outside win x1 = subViewRect.GetRight() + subViewRect.m_width; } if (is_vert) { y0 = subViewRect.m_y - subViewRect.m_height; y1 = subViewRect.GetBottom() + subViewRect.m_height; } if ((marker_type == wxPLOTMARKER_POINT) || ((x0 == x1) && (y0 == y1))) { if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { int i0 = m_owner->GetClientCoordFromPlotX(x0); int j0 = m_owner->GetClientCoordFromPlotY(y0); dc->DrawPoint(i0, j0); } } else if ((marker_type == wxPLOTMARKER_VERT_LINE) || ((x0 == x1) && (y0 != y1))) { if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { int i0 = m_owner->GetClientCoordFromPlotX(x0); int j0 = m_owner->GetClientCoordFromPlotY(y0); int j1 = m_owner->GetClientCoordFromPlotY(y1); wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i0, j1); } } else if ((marker_type == wxPLOTMARKER_HORIZ_LINE) || ((y0 == y1) && (x0 != x1))) { if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { int i0 = m_owner->GetClientCoordFromPlotX(x0); int i1 = m_owner->GetClientCoordFromPlotX(x1); int j0 = m_owner->GetClientCoordFromPlotY(y0); wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i1, j0); } } else if ((marker_type == wxPLOTMARKER_CROSS) || cross) { } else // rectangle { wxRect2DDouble clippedRect(x0, y0, x1 - x0, y1 - y0); clippedRect.Intersect(subViewRect); int pen_width = dc->GetPen().GetWidth() + 2; int i0 = m_owner->GetClientCoordFromPlotX(clippedRect.m_x); int i1 = m_owner->GetClientCoordFromPlotX(clippedRect.GetRight()); int j0 = m_owner->GetClientCoordFromPlotY(clippedRect.m_y); int j1 = m_owner->GetClientCoordFromPlotY(clippedRect.GetBottom()); if (r.m_x < subViewRect.m_x) i0 -= pen_width; if (r.m_y < subViewRect.m_y) j0 -= pen_width; if (r.GetRight() > subViewRect.GetRight()) i1 += pen_width; if (r.GetBottom() > subViewRect.GetBottom()) j1 += pen_width; dc->SetClippingRegion(dcRect); dc->DrawRectangle(i0, j0, i1 - i0 + 1, j1 - j0 + 1); dc->DestroyClippingRegion(); } } } } gambit-0.2010.09.01/src/labenski/src/plotfunc.cpp0000644000076500007650000001370711350032206016144 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotfunc.cpp // Purpose: wxPlotFunction curve for wxPlotCtrl // Author: John Labenski // Modified by: // Created: 12/01/2000 // Copyright: (c) John Labenski // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "plotfunc.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/bitmap.h" #include "wx/textdlg.h" #include "wx/msgdlg.h" #include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/plotctrl/plotfunc.h" #include "wx/plotctrl/fparser.h" #include //---------------------------------------------------------------------------- // wxPlotFuncRefData //---------------------------------------------------------------------------- class wxPlotFuncRefData: public wxPlotCurveRefData { public: wxPlotFuncRefData() : wxPlotCurveRefData() {} wxPlotFuncRefData(const wxPlotFuncRefData& data); wxFunctionParser m_parser; }; wxPlotFuncRefData::wxPlotFuncRefData(const wxPlotFuncRefData& data) :wxPlotCurveRefData() { wxPlotCurveRefData::Copy(data); m_parser = data.m_parser; } #define M_PLOTFUNCDATA ((wxPlotFuncRefData*)m_refData) //----------------------------------------------------------------------------- // wxPlotFunction //----------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxPlotFunction, wxPlotCurve); wxObjectRefData *wxPlotFunction::CreateRefData() const { return new wxPlotFuncRefData; } wxObjectRefData *wxPlotFunction::CloneRefData(const wxObjectRefData *data) const { return new wxPlotFuncRefData(*(const wxPlotFuncRefData *)data); } bool wxPlotFunction::Create( const wxPlotFunction& curve ) { wxCHECK_MSG(curve.Ok(), false, wxT("invalid plot function")); UnRef(); Ref(curve); return true; } void wxPlotFunction::Destroy() { UnRef(); } bool wxPlotFunction::Ok() const { return m_refData && M_PLOTFUNCDATA->m_parser.Ok(); } int wxPlotFunction::Create(const wxString &function, const wxString &vars, bool useDegrees) { UnRef(); m_refData = new wxPlotFuncRefData(); wxCHECK_MSG(m_refData, 0, wxT("can't allocate memory")); int i = M_PLOTFUNCDATA->m_parser.Parse(function, vars, useDegrees); if (!M_PLOTFUNCDATA->m_parser.ErrorMsg().IsEmpty()) return i; return -1; } int wxPlotFunction::Parse(const wxString &function, const wxString &vars, bool useDegrees) { wxCHECK_MSG(m_refData, 0, wxT("Invalid plotfunction")); int i = M_PLOTFUNCDATA->m_parser.Parse(function, vars, useDegrees); if (!M_PLOTFUNCDATA->m_parser.ErrorMsg().IsEmpty()) return i; return -1; } wxString wxPlotFunction::GetFunctionString() const { wxCHECK_MSG(Ok(), wxEmptyString, wxT("invalid plotfunction")); return M_PLOTFUNCDATA->m_parser.GetFunctionString(); } wxString wxPlotFunction::GetVariableString() const { wxCHECK_MSG(Ok(), wxEmptyString, wxT("invalid plotfunction")); return M_PLOTFUNCDATA->m_parser.GetVariableString(); } wxString wxPlotFunction::GetVariableName(size_t n) const { wxCHECK_MSG(Ok(), wxEmptyString, wxT("invalid plotfunction")); wxCHECK_MSG((int(n) < GetNumberVariables()), wxEmptyString, wxT("invalid variable index")); return M_PLOTFUNCDATA->m_parser.GetVariableName(n); } int wxPlotFunction::GetNumberVariables() const { wxCHECK_MSG(Ok(), 0, wxT("Invalid plotfunction")); return M_PLOTFUNCDATA->m_parser.GetNumberVariables(); } bool wxPlotFunction::GetUseDegrees() const { wxCHECK_MSG(m_refData, false, wxT("Invalid plotfunction")); return M_PLOTFUNCDATA->m_parser.GetUseDegrees(); } wxString wxPlotFunction::GetErrorMsg() const { wxCHECK_MSG(m_refData, wxEmptyString, wxT("Invalid plotfunction")); return M_PLOTFUNCDATA->m_parser.ErrorMsg(); } double wxPlotFunction::GetY( double x ) { wxCHECK_MSG(Ok(), 0.0, wxT("invalid plotfunction")); return M_PLOTFUNCDATA->m_parser.Eval( &x ); } double wxPlotFunction::GetValue( double *x ) { wxCHECK_MSG(Ok(), 0.0, wxT("invalid plotfunction")); return M_PLOTFUNCDATA->m_parser.Eval( x ); } bool wxPlotFunction::AddConstant(const wxString& name, double value) { wxCHECK_MSG(Ok(), false, wxT("invalid plotfunction")); return M_PLOTFUNCDATA->m_parser.AddConstant(name, value); } //----------------------------------------------------------------------------- // wxClipboardGet/SetPlotFunction //----------------------------------------------------------------------------- #include "wx/clipbrd.h" #include "wx/dataobj.h" #if wxUSE_DATAOBJ && wxUSE_CLIPBOARD wxPlotFunction wxClipboardGetPlotFunction() { bool is_opened = wxTheClipboard->IsOpened(); wxPlotFunction plotFunc; if (is_opened || wxTheClipboard->Open()) { wxTextDataObject textDataObject; if (wxTheClipboard->IsSupported(wxDataFormat(wxDF_TEXT)) && wxTheClipboard->GetData(textDataObject)) { wxString str = textDataObject.GetText(); plotFunc.Create(str.BeforeLast(wxT(';')), str.AfterLast(wxT(';'))); } if (!is_opened) wxTheClipboard->Close(); } return plotFunc; } bool wxClipboardSetPlotFunction(const wxPlotFunction& plotFunc) { wxCHECK_MSG(plotFunc.Ok(), false, wxT("Invalid wxPlotFunction to copy to clipboard")); bool is_opened = wxTheClipboard->IsOpened(); if (is_opened || wxTheClipboard->Open()) { wxString str = plotFunc.GetFunctionString() + wxT(";") + plotFunc.GetVariableString(); wxTextDataObject *textDataObject = new wxTextDataObject(str); wxTheClipboard->SetData( textDataObject ); if (!is_opened) wxTheClipboard->Close(); return true; } return false; } #endif // wxUSE_DATAOBJ && wxUSE_CLIPBOARD gambit-0.2010.09.01/src/labenski/src/plotmark.cpp0000644000076500007650000001152211350032206016134 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotmark.cpp // Purpose: wxPlotMarker // Author: John Labenski // Modified by: // Created: 8/27/2002 // Copyright: (c) John Labenski // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "plotmark.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif // WX_PRECOMP #include "wx/image.h" #include "wx/plotctrl/plotmark.h" #include "wx/plotctrl/plotctrl.h" #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY( wxArrayPlotMarker ); //----------------------------------------------------------------------------- // wxPlotMarkerRefData //----------------------------------------------------------------------------- class wxPlotMarkerRefData : public wxObjectRefData { public: wxPlotMarkerRefData(int type = 0, const wxRect2DDouble& rect = wxRect2DDouble()) : wxObjectRefData(), m_markerType(type), m_rect(rect), m_size(wxSize(-1, -1)) {} wxPlotMarkerRefData( const wxPlotMarkerRefData& data ) : wxObjectRefData(), m_markerType(data.m_markerType), m_rect(data.m_rect), m_size(data.m_size), m_bitmap(data.m_bitmap), m_pen(data.m_pen), m_brush(data.m_brush) {} int m_markerType; wxRect2DDouble m_rect; wxSize m_size; wxBitmap m_bitmap; wxGenericPen m_pen; wxGenericBrush m_brush; }; #define M_PMARKERDATA ((wxPlotMarkerRefData*)m_refData) //----------------------------------------------------------------------------- // wxPlotMarker //----------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxPlotMarker, wxObject); wxObjectRefData *wxPlotMarker::CreateRefData() const { return new wxPlotMarkerRefData; } wxObjectRefData *wxPlotMarker::CloneRefData(const wxObjectRefData *data) const { return new wxPlotMarkerRefData(*(const wxPlotMarkerRefData *)data); } void wxPlotMarker::Create(int marker_type, const wxRect2DDouble& rect, const wxSize& size, const wxGenericPen& pen, const wxGenericBrush& brush, const wxBitmap& bitmap) { UnRef(); m_refData = new wxPlotMarkerRefData(marker_type, rect); M_PMARKERDATA->m_size = size; M_PMARKERDATA->m_pen = pen; M_PMARKERDATA->m_brush = brush; M_PMARKERDATA->m_bitmap = bitmap; } int wxPlotMarker::GetMarkerType() const { wxCHECK_MSG(Ok(), wxPLOTMARKER_NONE, wxT("Invalid plot marker")); return M_PMARKERDATA->m_markerType; } void wxPlotMarker::SetMarkerType(int type) { wxCHECK_RET(Ok(), wxT("Invalid plot marker")); M_PMARKERDATA->m_markerType = type; } wxRect2DDouble wxPlotMarker::GetPlotRect() const { wxCHECK_MSG(Ok(), wxRect2DDouble(), wxT("Invalid plot marker")); return M_PMARKERDATA->m_rect; } wxRect2DDouble& wxPlotMarker::GetPlotRect() { static wxRect2DDouble s_rect; wxCHECK_MSG(Ok(), s_rect, wxT("Invalid plot marker")); return M_PMARKERDATA->m_rect; } void wxPlotMarker::SetPlotRect(const wxRect2DDouble& rect) { wxCHECK_RET(Ok(), wxT("Invalid plot marker")); M_PMARKERDATA->m_rect = rect; } wxPoint2DDouble wxPlotMarker::GetPlotPosition() const { wxCHECK_MSG(Ok(), wxPoint2DDouble(), wxT("Invalid plot marker")); return M_PMARKERDATA->m_rect.GetLeftTop(); } void wxPlotMarker::SetPlotPosition(const wxPoint2DDouble& pos) { wxCHECK_RET(Ok(), wxT("Invalid plot marker")); M_PMARKERDATA->m_rect.m_x = pos.m_x; M_PMARKERDATA->m_rect.m_y = pos.m_y; } wxSize wxPlotMarker::GetSize() const { wxCHECK_MSG(Ok(), wxSize(-1, -1), wxT("Invalid plot marker")); return M_PMARKERDATA->m_size; } void wxPlotMarker::SetSize(const wxSize& size) { wxCHECK_RET(Ok(), wxT("Invalid plot marker")); M_PMARKERDATA->m_size = size; } wxGenericPen wxPlotMarker::GetPen() const { wxCHECK_MSG(Ok(), wxNullGenericPen, wxT("Invalid plot marker")); return M_PMARKERDATA->m_pen; } void wxPlotMarker::SetPen(const wxGenericPen& pen) { wxCHECK_RET(Ok(), wxT("Invalid plot marker")); M_PMARKERDATA->m_pen = pen; } wxGenericBrush wxPlotMarker::GetBrush() const { wxCHECK_MSG(Ok(), wxNullGenericBrush, wxT("Invalid plot marker")); return M_PMARKERDATA->m_brush; } void wxPlotMarker::SetBrush(const wxGenericBrush& brush) { wxCHECK_RET(Ok(), wxT("Invalid plot marker")); M_PMARKERDATA->m_brush = brush; } wxBitmap wxPlotMarker::GetBitmap() const { wxCHECK_MSG(Ok(), wxNullBitmap, wxT("Invalid plot marker")); return M_PMARKERDATA->m_bitmap; } void wxPlotMarker::SetBitmap(const wxBitmap& bitmap) { wxCHECK_RET(Ok(), wxT("Invalid plot marker")); M_PMARKERDATA->m_bitmap = bitmap; } gambit-0.2010.09.01/src/labenski/src/plotprnt.cpp0000644000076500007650000002001211350032206016157 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: plotprnt.cpp // Purpose: wxPlotPrintout // Author: John Labenski // Modified by: // Created: 8/27/2002 // Copyright: (c) John Labenski // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "plotprnt.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/msgdlg.h" #include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/module.h" #include "wx/printdlg.h" #include "wx/plotctrl/plotctrl.h" #include "wx/plotctrl/plotprnt.h" #define RINT(x) int((x) >= 0 ? ((x) + 0.5) : ((x) - 0.5)) //----------------------------------------------------------------------------- // wxPlotPrintout //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotPrintout, wxPrintout) wxPrintData *wxPlotPrintout::s_wxPlotPrintData = NULL; wxPageSetupData *wxPlotPrintout::s_wxPlotPageSetupData = NULL; bool wxPlotPrintout::s_wxPlotPrintdata_static = false; bool wxPlotPrintout::s_wxPlotPagesetupdata_static = false; wxPrintData *wxPlotPrintout::GetPrintData(bool create_on_demand) { if (create_on_demand && (s_wxPlotPrintData == NULL)) { wxPrintData *printData = new wxPrintData; printData->SetPaperId(wxPAPER_LETTER); SetPrintData(printData, false); } return s_wxPlotPrintData; } wxPageSetupData *wxPlotPrintout::GetPageSetupData(bool create_on_demand) { if (create_on_demand && (s_wxPlotPageSetupData == NULL)) { wxPageSetupData *pageSetupData = new wxPageSetupData; pageSetupData->SetPaperSize(wxPAPER_LETTER); pageSetupData->SetMarginTopLeft(wxPoint(20, 20)); pageSetupData->SetMarginBottomRight(wxPoint(20, 20)); SetPageSetupData(pageSetupData, false); } return s_wxPlotPageSetupData; } bool wxPlotPrintout::GetPrintDataStatic() { return s_wxPlotPrintdata_static; } bool wxPlotPrintout::GetPageSetupDataStatic() { return s_wxPlotPagesetupdata_static; } void wxPlotPrintout::SetPrintData( wxPrintData *printData, bool is_static ) { if (s_wxPlotPrintData && !s_wxPlotPrintdata_static) delete s_wxPlotPrintData; s_wxPlotPrintData = printData; s_wxPlotPrintdata_static = is_static; } void wxPlotPrintout::SetPageSetupData( wxPageSetupData *pageSetupData, bool is_static ) { if (s_wxPlotPageSetupData && !s_wxPlotPagesetupdata_static) delete s_wxPlotPageSetupData; s_wxPlotPageSetupData = pageSetupData; s_wxPlotPagesetupdata_static = is_static; } wxPlotPrintout::wxPlotPrintout( wxPlotCtrl* plotWin, const wxString &title ) : wxPrintout(title), m_plotWin(plotWin) { } bool wxPlotPrintout::OnBeginDocument(int startPage, int endPage) { if (!wxPrintout::OnBeginDocument(startPage, endPage)) return false; return true; } bool wxPlotPrintout::OnPrintPage(int page) { wxCHECK_MSG(m_plotWin, false, wxT("Invalid plotctrl")); if (page != 1) return false; wxPoint pagePix; //GetPageSizePixels(&pagePix.x, &pagePix.y); // no good for preview when scaled GetDC()->GetSize(&pagePix.x, &pagePix.y); wxPoint tl = GetPageSetupData(true)->GetMarginTopLeft(); wxPoint br = GetPageSetupData(true)->GetMarginBottomRight(); wxPoint ppi; if (IsPreview()) GetPPIScreen(&ppi.x, &ppi.y); else GetPPIPrinter(&ppi.x, &ppi.y); //wxPrintf(wxT("ppi %d %d dc size %d %d margin tl %d %d br %d %d\n"), ppi.x, ppi.y, pagePix.x, pagePix.y, tl.x, tl.y, br.x, br.y); tl.x = int((tl.x*ppi.x)/25.4); tl.y = int((tl.y*ppi.y)/25.4); br.x = int((br.x*ppi.x)/25.4); br.y = int((br.y*ppi.y)/25.4); wxRect rect(tl.x, tl.y, pagePix.x - tl.x - br.x, pagePix.y - tl.y - br.y); //wxPrintf(wxT("dc size %d %d margin tl %d %d br %d %d\n"), rect.width, rect.height, tl.x, tl.y, br.x, br.y); int dpi = ppi.x; //set dpi of the drawwholeplot function if (IsPreview()) { //dpi is the (screen dpi) * (percent of screen used by preview) dpi = RINT(ppi.x * ((double)rect.width / pagePix.x)); } m_plotWin->DrawWholePlot( GetDC(), rect, dpi ); return true; } bool wxPlotPrintout::ShowPrintDialog() { wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); wxPrintDialogData printDialogData(*wxPlotPrintout::GetPrintData(true)); wxPrinter printer(& printDialogData); if (!printer.Print(GetPlotCtrl(), this, true)) { if (wxPrinter::GetLastError() == wxPRINTER_ERROR) wxMessageBox(_("There was a problem printing.\n" "Perhaps your printer is not setup correctly?"), _("Printing"), wxOK, GetPlotCtrl()); } if (wxPrinter::GetLastError() != wxPRINTER_CANCELLED) *wxPlotPrintout::GetPrintData(true) = printer.GetPrintDialogData().GetPrintData(); return wxPrinter::GetLastError() == wxPRINTER_NO_ERROR; } bool wxPlotPrintout::ShowPrintPreviewDialog(const wxString& frameTitle) { wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); // Pass two printout objects: for preview, and possible printing. wxPrintDialogData printDialogData(*wxPlotPrintout::GetPrintData(true)); wxPrintPreview *preview = new wxPrintPreview(new wxPlotPrintout(GetPlotCtrl(), GetTitle()), new wxPlotPrintout(GetPlotCtrl(), GetTitle()), &printDialogData); if (!preview->Ok()) { delete preview; wxMessageBox(_("There was a problem previewing.\n" "Perhaps your printer is not setup correctly?"), _("Previewing"), wxOK, GetPlotCtrl()); return false; } wxRect r(wxGetClientDisplayRect()); r.width = wxMin(r.width, 600); r.height = wxMin(r.height, 650); wxPreviewFrame *frame = new wxPreviewFrame(preview, GetPlotCtrl(), frameTitle, wxDefaultPosition, r.GetSize()); frame->Centre(wxBOTH); frame->Initialize(); frame->Show(true); return true; } bool wxPlotPrintout::ShowPrintSetupDialog() { wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); wxPrintDialogData printDialogData(*wxPlotPrintout::GetPrintData(true)); wxPrintDialog printerDialog(GetPlotCtrl(), & printDialogData); #if !wxCHECK_VERSION(2,7,0) printerDialog.GetPrintDialogData().SetSetupDialog(true); #endif //!wxCHECK_VERSION(2,7,0) if (printerDialog.ShowModal() != wxID_CANCEL) { *wxPlotPrintout::GetPrintData(true) = printerDialog.GetPrintDialogData().GetPrintData(); return true; } return false; } bool wxPlotPrintout::ShowPrintPageSetupDialog() { wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); *wxPlotPrintout::GetPageSetupData(true) = *wxPlotPrintout::GetPrintData(); wxPageSetupDialog pageSetupDialog(GetPlotCtrl(), wxPlotPrintout::GetPageSetupData()); if (pageSetupDialog.ShowModal() != wxID_CANCEL) { *wxPlotPrintout::GetPrintData(true) = pageSetupDialog.GetPageSetupData().GetPrintData(); *wxPlotPrintout::GetPageSetupData(true) = pageSetupDialog.GetPageSetupData(); return true; } return false; } //----------------------------------------------------------------------------- // wxPlotCtrlModule - setup anything after init and delete before closing //----------------------------------------------------------------------------- class wxPlotCtrlModule : public wxModule { DECLARE_DYNAMIC_CLASS(wxPlotCtrlModule) public: wxPlotCtrlModule() : wxModule() {} bool OnInit() { return true; } void OnExit() { wxPlotPrintout::SetPrintData(NULL, false); wxPlotPrintout::SetPageSetupData(NULL, false); } }; IMPLEMENT_DYNAMIC_CLASS(wxPlotCtrlModule, wxModule) gambit-0.2010.09.01/src/labenski/src/range.cpp0000644000076500007650000004043611350032206015405 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: range.cpp // Purpose: Simple min-max range class and associated selection array class // Author: John Labenski // Created: 12/01/2000 // Copyright: (c) John Labenski 2004 // Licence: wxWidgets ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "range.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/utils.h" #endif // WX_PRECOMP #include "wx/wxthings/range.h" #include const wxRangeInt wxEmptyRangeInt(0, -1); const wxRangeDouble wxEmptyRangeDouble(0, -1); #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArrayRangeInt); WX_DEFINE_OBJARRAY(wxArrayRangeDouble); WX_DEFINE_OBJARRAY(wxArrayRangeIntSelection); WX_DEFINE_OBJARRAY(wxArrayRangeDoubleSelection); // set this if you want to double check that that ranges are really working //#define CHECK_RANGES //============================================================================= // wxRangeInt //============================================================================= bool wxRangeInt::Combine(int i, bool only_if_touching) { if (only_if_touching) { if (i == m_min-1) { m_min--; return true; } else if (i == m_max+1) { m_max++; return true; } } else { if (i < m_min) { m_min = i; return true; } else if (i > m_max) { m_max = i; return true; } } return false; } bool wxRangeInt::Combine( const wxRangeInt &r, bool only_if_touching ) { if (only_if_touching) { if (Touches(r)) { *this+=r; return true; } } else { bool added = false; if (r.m_min < m_min) { m_min = r.m_min; added = true; } if (r.m_max > m_max) { m_max = r.m_max; added = true; } return added; } return false; } bool wxRangeInt::Delete( const wxRangeInt &r, wxRangeInt *right ) { if (!Contains(r)) return false; if (right) *right = wxEmptyRangeInt; if (r.m_min <= m_min) { if (r.m_max >= m_max) { *this = wxEmptyRangeInt; return true; } m_min = r.m_max + 1; return true; } if (r.m_max >= m_max) { m_max = r.m_min - 1; return true; } if (right) *right = wxRangeInt(r.m_max + 1, m_max); m_max = r.m_min - 1; return true; } //============================================================================= // wxRangeIntSelection //============================================================================= const wxRangeInt& wxRangeIntSelection::GetRange( int index ) const { wxCHECK_MSG((index>=0) && (index m_ranges[count-1].m_max) return wxNOT_FOUND; // Binary search int res, tmp, lo = 0, hi = count; while ( lo < hi ) { tmp = (lo + hi)/2; res = m_ranges[tmp].Position(i); if (res == 0) return tmp; else if ( res < 0 ) hi = tmp; else //if ( res > 0 ) lo = tmp + 1; } return wxNOT_FOUND; } int wxRangeIntSelection::Index( const wxRangeInt &r ) const { register int i, count = m_ranges.GetCount(); for (i=0; i m_ranges[count-1].m_max) return count; // Binary search int res, tmp, lo = 0, hi = count; while ( lo < hi ) { tmp = (lo + hi)/2; res = m_ranges[tmp].Position(i); if ( res == 0 ) return tmp; else if ((i >= m_ranges[tmp].m_max) && (i < m_ranges[wxMin(tmp+1, count-1)].m_min)) return tmp; else if ( res < 0 ) hi = tmp; else //if ( res > 0 ) lo = tmp + 1; } // oops shouldn't get here wxCHECK_MSG(0, -1, wxT("Error calculating NearestIndex in wxRangeIntSelection")); } int wxRangeIntSelection::GetItemCount() const { register int i, items = 0, count = m_ranges.GetCount(); for (i=0; i 0 ? NearestIndex(range.m_min) : -1; if ((nearest < 0) || (nearest == count)) return false; wxRangeInt r; for (i=nearest; i 0) ? i-1 : -1; } else if (!r.IsEmpty()) m_ranges.Insert(r, i+1); done = true; } } return done; } bool wxRangeIntSelection::SelectRange(const wxRangeInt &range) { wxCHECK_MSG(!range.IsEmpty(), false, wxT("Invalid Selection Range") ); // Try to find a range that includes this one and combine it, else insert it, else append it bool done = false; int i, count = m_ranges.GetCount(); int nearest = count > 0 ? NearestIndex(range.m_min) : -1; if (nearest < 0) { if (!((count > 0) && m_ranges[0].Combine(range, true))) m_ranges.Insert(range, 0); return true; } else if (nearest == count) { if (!((count > 0) && m_ranges[count-1].Combine(range, true))) m_ranges.Add(range); return true; } else { if (m_ranges[nearest].Contains(range)) return false; for (i=nearest; i= range.m_min) break; if (m_ranges[i].m_max < range.m_min) // range is out of bounds { done = true; m_ranges.RemoveAt(i); count--; i--; } else { done = true; m_ranges[i].m_min = range.m_min; break; } } for (i = m_ranges.GetCount() - 1; i >= 0; i--) { if (m_ranges[i].m_max <= range.m_max) break; if (m_ranges[i].m_min > range.m_max) // range is out of bounds { done = true; m_ranges.RemoveAt(i); } else { done = true; m_ranges[i].m_max = range.m_max; break; } } return done; } //============================================================================= // wxRangeDouble //============================================================================= bool wxRangeDouble::Combine(wxDouble i) { if (i < m_min) { m_min = i; return true; } else if (i > m_max) { m_max = i; return true; } return false; } bool wxRangeDouble::Combine( const wxRangeDouble &r, bool only_if_touching ) { if (only_if_touching) { if (Contains(r)) { *this+=r; return true; } } else { bool added = false; if (r.m_min < m_min) { m_min = r.m_min; added = true; } if (r.m_max > m_max) { m_max = r.m_max; added = true; } return added; } return false; } bool wxRangeDouble::Delete( const wxRangeDouble &r, wxRangeDouble *right ) { if (!Contains(r)) return false; if (right) *right = wxEmptyRangeDouble; if (r.m_min <= m_min) { if (r.m_max >= m_max) { *this = wxEmptyRangeDouble; return true; } m_min = r.m_max; return true; } if (r.m_max >= m_max) { m_max = r.m_min; return true; } if (right) *right = wxRangeDouble(r.m_max, m_max); m_max = r.m_min; return true; } //============================================================================= // wxRangeDoubleSelection //============================================================================= const wxRangeDouble& wxRangeDoubleSelection::GetRange( int index ) const { wxCHECK_MSG((index>=0) && (index m_ranges[count-1].m_max) return wxNOT_FOUND; // Binary search int res, tmp, lo = 0, hi = count; while ( lo < hi ) { tmp = (lo + hi)/2; res = m_ranges[tmp].Position(i); if ( res == 0 ) return tmp; else if ( res < 0 ) hi = tmp; else //if ( res > 0 ) lo = tmp + 1; } return wxNOT_FOUND; /* for (register int j=0; j m_ranges[count-1].m_max) return count; // Binary search int res, tmp, lo = 0, hi = count; while ( lo < hi ) { tmp = (lo + hi)/2; res = m_ranges[tmp].Position(i); if ( res == 0 ) return tmp; else if ((i >= m_ranges[tmp].m_max) && (i < m_ranges[wxMin(tmp+1, count-1)].m_min)) return tmp; else if ( res < 0 ) hi = tmp; else //if ( res > 0 ) lo = tmp + 1; } // oops shouldn't get here wxCHECK_MSG(0, -1, wxT("Error calculating NearestIndex in wxRangeDoubleSelection")); } bool wxRangeDoubleSelection::SelectRange(const wxRangeDouble &range) { wxCHECK_MSG(!range.IsEmpty(), false, wxT("Invalid Selection Range") ); // Try to find a range that includes this one and combine it, else insert it, else append it bool done = false; int i, count = m_ranges.GetCount(); int nearest = count > 0 ? NearestIndex(range.m_min) : -1; if (nearest < 0) { if (!((count > 0) && m_ranges[0].Combine(range, true))) m_ranges.Insert(range, 0); return true; } else if (nearest == count) { if (!((count > 0) && m_ranges[count-1].Combine(range, true))) m_ranges.Add(range); return true; } else { if (m_ranges[nearest].Contains(range)) return false; for (i=nearest; i 0 ? NearestIndex(range.m_min) : -1; if ((nearest < 0) || (nearest == count)) return false; wxRangeDouble r; for (i=nearest; i 0) ? i-1 : -1; } else if (!r.IsEmpty()) m_ranges.Insert(r, i+1); done = true; } } return done; } bool wxRangeDoubleSelection::BoundRanges(const wxRangeDouble& range) { wxCHECK_MSG(!range.IsEmpty(), false, wxT("Invalid Bounding Range") ); int i, count = m_ranges.GetCount(); bool done = false; for (i = 0; i < count; i++) { if (m_ranges[i].m_min >= range.m_min) break; if (m_ranges[i].m_max < range.m_min) // range is out of bounds { done = true; m_ranges.RemoveAt(i); count--; i--; } else { done = true; m_ranges[i].m_min = range.m_min; break; } } for (i = m_ranges.GetCount() - 1; i >= 0; i--) { if (m_ranges[i].m_max <= range.m_max) break; if (m_ranges[i].m_min > range.m_max) // range is out of bounds { done = true; m_ranges.RemoveAt(i); } else { done = true; m_ranges[i].m_max = range.m_max; break; } } return done; } gambit-0.2010.09.01/src/labenski/src/sheet.cpp0000644000076500007650000071364711350032206015434 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheet.cpp // Purpose: wxSheet and related classes // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) // Modified by: John Labenski, Robin Dunn, Vadim Zeitlin // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski, Michael Bedward (mbedward@ozemail.com.au) // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// // wxSheet code is based on wxGrid, to ensure that it stays up to date changes // in the wxGrid files should be noted and incorporated if applicable. // Note: very little code remains, update colours and sizing... // wx/include/wx/generic/grid.h 1.140 // wx/include/wx/generic/gridctrl.h 1.15 // wx/include/wx/generic/gridsel.h 1.18 // wx/src/generic/grid.cpp 1.318 // wx/src/generic/gridctrl.cpp 1.15 // wx/src/generic/gridsel.cpp 1.20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "sheet.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/defs.h" #include "wx/utils.h" #include "wx/dcclient.h" #include "wx/settings.h" #include "wx/log.h" #include "wx/dcscreen.h" #endif // WX_PRECOMP #include "wx/sheet/sheet.h" #include "wx/sheet/sheetspt.h" // for wxSheetSplitterEvent, wxEVT_SHEET_SPLIT_BEGIN #include "wx/timer.h" #include "wx/clipbrd.h" #include "wx/renderer.h" // Required for wxIs... functions #include #define PRINT_BLOCK(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); #define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); #define SPLIT_BUTTON_WIDTH 6 #define wxStrF wxString::Format #ifndef wxSL_INVERSE // !wxCHECK_VERSION(2,5,3) // FIXME temp fix until 2.5.4 #define SetOwnBackgroundColour SetBackgroundColour #define SetOwnForegroundColour SetForegroundColour #endif #ifdef __wxGTK__ //#define USE_RENDERNATIVE 1 #endif // __wxGTK__ static inline bool wxRectIsEmpty(const wxRect& rect) { return (rect.width < 1) || (rect.height < 1); } // ---------------------------------------------------------------------------- // conditional compilation // ---------------------------------------------------------------------------- // Gambit modification for custom border drawing #define WXSHEET_DRAW_LINES 0 #ifndef WXSHEET_DRAW_LINES #define WXSHEET_DRAW_LINES 1 #endif // ---------------------------------------------------------------------------- // globals // ---------------------------------------------------------------------------- //#define DEBUG_ATTR_CACHE #ifdef DEBUG_ATTR_CACHE static size_t gs_nAttrCacheHits = 0; static size_t gs_nAttrCacheMisses = 0; #endif // DEBUG_ATTR_CACHE // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- // scroll line size // TODO: this doesn't work at all, sheet cells have different sizes and approx // calculations don't work as because of the size mismatch scrollbars // sometimes fail to be shown when they should be or vice versa // // The scroll bars may be a little flakey once in a while, but that is // surely much less horrible than having scroll lines of only 1!!! // -- Robin // // Well, it's still seriously broken so it might be better but needs // fixing anyhow // -- Vadim #define SHEET_SCROLL_LINE_X 15 // 1 #define SHEET_SCROLL_LINE_Y SHEET_SCROLL_LINE_X // ---------------------------------------------------------------------------- // wxSheetDataTypeInfo: for the data type registry // ---------------------------------------------------------------------------- class wxSheetDataTypeInfo { public: wxSheetDataTypeInfo(const wxString& typeName, const wxSheetCellRenderer& renderer, const wxSheetCellEditor& editor) : m_typeName(typeName), m_renderer(renderer), m_editor(editor) {} wxString m_typeName; wxSheetCellRenderer m_renderer; wxSheetCellEditor m_editor; }; // ---------------------------------------------------------------------------- // wxSheetTypeRegistry // ---------------------------------------------------------------------------- class WXDLLIMPEXP_SHEET wxSheetTypeRegistry { public: wxSheetTypeRegistry() {} virtual ~wxSheetTypeRegistry(); // register a new data type returning position int RegisterDataType(const wxString& typeName, const wxSheetCellRenderer& renderer, const wxSheetCellEditor& editor); // find one of already registered data types int FindRegisteredDataType(const wxString& typeName); // try to FindRegisteredDataType(), if this fails and typeName is one of // standard typenames, register it and return its index int FindDataType(const wxString& typeName); // try to FindDataType(), if it fails, see if it is not one of already // registered data types with some params in which case clone the // registered data type and set params for it int FindOrCloneDataType(const wxString& typeName); const wxSheetCellRenderer& GetRenderer(int index); const wxSheetCellEditor& GetEditor(int index); private: wxArrayPtrVoid m_typeInfo; }; wxSheetTypeRegistry::~wxSheetTypeRegistry() { size_t i, count = m_typeInfo.Count(); for ( i = 0; i < count; i++ ) delete (wxSheetDataTypeInfo*)m_typeInfo[i]; } int wxSheetTypeRegistry::RegisterDataType(const wxString& typeName, const wxSheetCellRenderer& renderer, const wxSheetCellEditor& editor) { wxSheetDataTypeInfo* info = new wxSheetDataTypeInfo(typeName, renderer, editor); // is it already registered? int index = FindRegisteredDataType(typeName); if ( index != wxNOT_FOUND ) { wxSheetDataTypeInfo *oldInfo = (wxSheetDataTypeInfo*)m_typeInfo[index]; delete oldInfo; m_typeInfo[index] = info; return index; } m_typeInfo.Add(info); return m_typeInfo.GetCount() - 1; } int wxSheetTypeRegistry::FindRegisteredDataType(const wxString& typeName) { if (typeName.IsEmpty()) return wxNOT_FOUND; size_t i, count = m_typeInfo.GetCount(); for ( i = 0; i < count; i++ ) { if (typeName == ((wxSheetDataTypeInfo*)m_typeInfo[i])->m_typeName) return i; } return wxNOT_FOUND; } int wxSheetTypeRegistry::FindDataType(const wxString& typeName) { int index = FindRegisteredDataType(typeName); if (index != wxNOT_FOUND) return index; // if one of the standard ones, register it "on the fly" #if wxUSE_TEXTCTRL if ( typeName == wxSHEET_VALUE_STRING ) { wxSheetCellRenderer renderer(new wxSheetCellStringRendererRefData()); wxSheetCellEditor editor(new wxSheetCellTextEditorRefData()); return RegisterDataType(wxSHEET_VALUE_STRING, renderer, editor); } else if ( typeName == wxSHEET_VALUE_NUMBER ) { wxSheetCellRenderer renderer(new wxSheetCellNumberRendererRefData()); wxSheetCellEditor editor(new wxSheetCellNumberEditorRefData()); return RegisterDataType(wxSHEET_VALUE_NUMBER, renderer, editor); } else if ( typeName == wxSHEET_VALUE_FLOAT ) { wxSheetCellRenderer renderer(new wxSheetCellFloatRendererRefData()); wxSheetCellEditor editor(new wxSheetCellFloatEditorRefData()); return RegisterDataType(wxSHEET_VALUE_FLOAT, renderer, editor); } else if ( typeName == wxSHEET_VALUE_LABEL ) { wxSheetCellRenderer renderer(new wxSheetCellRolColLabelRendererRefData()); wxSheetCellEditor editor(new wxSheetCellTextEditorRefData()); return RegisterDataType(wxSHEET_VALUE_LABEL, renderer, editor); } #endif // wxUSE_TEXTCTRL #if wxUSE_CHECKBOX else if ( typeName == wxSHEET_VALUE_BOOL ) { wxSheetCellRenderer renderer(new wxSheetCellBoolRendererRefData()); wxSheetCellEditor editor(new wxSheetCellBoolEditorRefData()); return RegisterDataType(wxSHEET_VALUE_BOOL, renderer, editor); } #endif // wxUSE_CHECKBOX #if wxUSE_COMBOBOX else if ( typeName == wxSHEET_VALUE_CHOICE ) { wxSheetCellRenderer renderer(new wxSheetCellStringRendererRefData()); wxSheetCellEditor editor(new wxSheetCellChoiceEditorRefData()); return RegisterDataType(wxSHEET_VALUE_CHOICE, renderer, editor); } #endif // wxUSE_COMBOBOX return wxNOT_FOUND; } int wxSheetTypeRegistry::FindOrCloneDataType(const wxString& typeName) { if (typeName.IsEmpty()) return wxNOT_FOUND; int index = FindDataType(typeName); if ( index != wxNOT_FOUND ) return index; // the first part of the typename is the "real" type, anything after ':' // are the parameters for the renderer index = FindDataType(typeName.BeforeFirst(_T(':'))); if ( index == wxNOT_FOUND ) return wxNOT_FOUND; wxSheetCellRenderer renderer(GetRenderer(index).Clone()); wxSheetCellEditor editor(GetEditor(index).Clone()); // do it even if there are no parameters to reset them to defaults wxString params = typeName.AfterFirst(_T(':')); renderer.SetParameters(params); editor.SetParameters(params); return RegisterDataType(typeName, renderer, editor); } const wxSheetCellRenderer& wxSheetTypeRegistry::GetRenderer(int index) { wxCHECK_MSG((index >= 0) && (index < int(m_typeInfo.GetCount())), wxNullSheetCellRenderer, wxT("Invalid index in wxSheetTypeRegistry::GetRenderer")); return ((wxSheetDataTypeInfo*)m_typeInfo[index])->m_renderer; } const wxSheetCellEditor& wxSheetTypeRegistry::GetEditor(int index) { wxCHECK_MSG((index >= 0) && (index < int(m_typeInfo.GetCount())), wxNullSheetCellEditor, wxT("Invalid index in wxSheetTypeRegistry::GetEditor")); return ((wxSheetDataTypeInfo*)m_typeInfo[index])->m_editor; } // ---------------------------------------------------------------------------- // wxSheetChildWindow // ---------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS( wxSheetChildWindow, wxWindow ) BEGIN_EVENT_TABLE( wxSheetChildWindow, wxWindow ) EVT_PAINT ( wxSheetChildWindow::OnPaint ) EVT_MOUSEWHEEL ( wxSheetChildWindow::OnMouse ) EVT_MOUSE_EVENTS ( wxSheetChildWindow::OnMouse ) EVT_KEY_DOWN ( wxSheetChildWindow::OnKeyAndChar ) EVT_KEY_UP ( wxSheetChildWindow::OnKeyAndChar ) EVT_CHAR ( wxSheetChildWindow::OnKeyAndChar ) EVT_SET_FOCUS ( wxSheetChildWindow::OnFocus ) EVT_KILL_FOCUS ( wxSheetChildWindow::OnFocus ) END_EVENT_TABLE() wxSheetChildWindow::wxSheetChildWindow( wxSheet *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString& name ) :wxWindow( parent, id, pos, size, style, name ), m_owner(parent), m_mouseCursor(wxSheet::WXSHEET_CURSOR_SELECT_CELL) { } void wxSheetChildWindow::OnPaint( wxPaintEvent& event ) { if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) { wxPaintDC dc(this); // MSW at least requires this } } void wxSheetChildWindow::OnMouse( wxMouseEvent& event ) { if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) event.Skip(); } // This seems to be required for wxMotif otherwise the mouse // cursor must be in the cell edit control to get key events void wxSheetChildWindow::OnKeyAndChar( wxKeyEvent& event ) { if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) event.Skip(); } void wxSheetChildWindow::OnFocus( wxFocusEvent& event ) { if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) event.Skip(); } void wxSheetChildWindow::OnEraseBackground( wxEraseEvent& event) { if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) event.Skip(false); } //----------------------------------------------------------------------------- // wxSheetRefData //----------------------------------------------------------------------------- wxSheetRefData::wxSheetRefData() { m_table = NULL; m_ownTable = false; m_typeRegistry = new wxSheetTypeRegistry; m_rowEdges.SetDefaultSize(WXSHEET_DEFAULT_ROW_HEIGHT); m_colEdges.SetDefaultSize(WXSHEET_DEFAULT_COL_WIDTH); m_rowEdges.SetMinAllowedSize(WXSHEET_MIN_ROW_HEIGHT); m_colEdges.SetMinAllowedSize(WXSHEET_MIN_COL_WIDTH); m_rowLabelWidth = WXSHEET_DEFAULT_ROW_LABEL_WIDTH; m_colLabelHeight = WXSHEET_DEFAULT_COL_LABEL_HEIGHT; m_equal_col_widths = 0; m_gridLineColour = wxColour( 192, 192, 192 ); m_gridLinesEnabled = wxBOTH; m_cursorCellHighlightColour = *wxBLACK; m_cursorCellHighlightPenWidth = 2; m_cursorCellHighlightROPenWidth = 1; m_labelOutlineColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW); m_rowResizeCursor = wxCursor( wxCURSOR_SIZENS ); m_colResizeCursor = wxCursor( wxCURSOR_SIZEWE ); m_editable = true; // default for whole grid m_canDrag = wxSHEET_DragCellSize; m_cursorCoords = wxNullSheetCoords; m_selectingAnchor = wxNullSheetCoords; m_selectionMode = wxSHEET_SelectCells; m_selection = new wxSheetSelection; m_selectionBackground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); m_selectionForeground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); m_cellEditorCoords = wxNullSheetCoords; m_pasting = false; } wxSheetRefData::~wxSheetRefData() { if (m_ownTable && m_table) delete m_table; delete m_typeRegistry; delete m_selection; } int wxSheetRefData::FindSheet(wxSheet* sheet) const { return m_sheets.Index(sheet); } void wxSheetRefData::AddSheet(wxSheet* sheet) { wxCHECK_RET(sheet, wxT("Invalid sheet")); // not an error, just let them do it to avoid having to check if (!HasSheet(sheet)) m_sheets.Add(sheet); } void wxSheetRefData::RemoveSheet(wxSheet* sheet) { wxCHECK_RET(sheet, wxT("Invalid sheet")); // not an error, if not found allows for this to be called in destructor const int index = FindSheet(sheet); if (index != wxNOT_FOUND) m_sheets.RemoveAt(index); } //----------------------------------------------------------------------------- // RTTI stuff for ? //----------------------------------------------------------------------------- #if wxUSE_EXTENDED_RTTI WX_DEFINE_FLAGS( wxSheetStyle ) wxBEGIN_FLAGS( wxSheetStyle ) // new style border flags, we put them first to // use them for streaming out wxFLAGS_MEMBER(wxBORDER_SIMPLE) wxFLAGS_MEMBER(wxBORDER_SUNKEN) wxFLAGS_MEMBER(wxBORDER_DOUBLE) wxFLAGS_MEMBER(wxBORDER_RAISED) wxFLAGS_MEMBER(wxBORDER_STATIC) wxFLAGS_MEMBER(wxBORDER_NONE) // old style border flags wxFLAGS_MEMBER(wxSIMPLE_BORDER) wxFLAGS_MEMBER(wxSUNKEN_BORDER) wxFLAGS_MEMBER(wxDOUBLE_BORDER) wxFLAGS_MEMBER(wxRAISED_BORDER) wxFLAGS_MEMBER(wxSTATIC_BORDER) wxFLAGS_MEMBER(wxBORDER) // standard window styles wxFLAGS_MEMBER(wxTAB_TRAVERSAL) wxFLAGS_MEMBER(wxCLIP_CHILDREN) wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW) wxFLAGS_MEMBER(wxWANTS_CHARS) wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE) wxFLAGS_MEMBER(wxALWAYS_SHOW_SB ) wxFLAGS_MEMBER(wxVSCROLL) wxFLAGS_MEMBER(wxHSCROLL) wxEND_FLAGS( wxSheetStyle ) IMPLEMENT_DYNAMIC_CLASS_XTI(wxSheet, wxWindow,"wx/sheet/sheet.h") wxBEGIN_PROPERTIES_TABLE(wxSheet) wxHIDE_PROPERTY( Children ) wxPROPERTY_FLAGS( WindowStyle , wxSheetStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style wxEND_PROPERTIES_TABLE() wxBEGIN_HANDLERS_TABLE(wxSheet) wxEND_HANDLERS_TABLE() wxCONSTRUCTOR_5( wxSheet , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle ) /* TODO : Expose more information of a list's layout etc. via appropriate objects (a la NotebookPageInfo) */ #else IMPLEMENT_DYNAMIC_CLASS( wxSheet, wxWindow ) #endif BEGIN_EVENT_TABLE( wxSheet, wxWindow ) EVT_PAINT ( wxSheet::OnPaint ) EVT_SIZE ( wxSheet::OnSize ) //EVT_ERASE_BACKGROUND( wxSheet::OnEraseBackground ) EVT_KEY_DOWN ( wxSheet::OnKeyDown ) EVT_KEY_UP ( wxSheet::OnKeyUp ) EVT_CHAR ( wxSheet::OnChar ) EVT_MOUSEWHEEL ( wxSheet::OnMouseWheel ) EVT_MOUSE_EVENTS ( wxSheet::OnMouse ) EVT_COMMAND_SCROLL ( wxSheet::ID_HORIZ_SCROLLBAR, wxSheet::OnScroll ) EVT_COMMAND_SCROLL ( wxSheet::ID_VERT_SCROLLBAR, wxSheet::OnScroll ) EVT_TIMER ( wxSheet::ID_MOUSE_DRAG_TIMER, wxSheet::OnMouseTimer ) END_EVENT_TABLE() void wxSheet::Init() { m_cornerLabelWin = NULL; m_rowLabelWin = NULL; m_colLabelWin = NULL; m_gridWin = NULL; m_horizScrollBar = NULL; m_vertScrollBar = NULL; m_scrollBarMode = wxSheet::SB_AS_NEEDED; m_keySelecting = false; // init attr cache m_cacheAttr = wxNullSheetCellAttr; m_cacheAttrCoords = wxNullSheetCoords; m_cacheAttrType = -1; m_inOnKeyDown = false; m_batchCount = 0; m_resizing = false; m_mouseCursorMode = WXSHEET_CURSOR_SELECT_CELL; m_mouseCursor = WXSHEET_CURSOR_SELECT_CELL; m_winCapture = (wxWindow *)NULL; m_dragLastPos = -1; m_dragRowOrCol = -1; m_isDragging = false; m_startDragPos = wxDefaultPosition; m_waitForSlowClick = false; m_mouseTimer = NULL; m_enable_split_vert = false; m_enable_split_horiz = false; m_refData = new wxSheetRefData; // ALWAYS CREATED and ALWAYS EXISTS! } // NOTE: If using the default visual attributes works everywhere then this can // be removed as well as the #else cases below. #define _USE_VISATTR 0 #if _USE_VISATTR #include "wx/listbox.h" #endif bool wxSheet::Create( wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) { if (!wxWindow::Create(parent, id, pos, size, style | wxWANTS_CHARS, name)) return false; #if wxCHECK_VERSION(2,5,2) && _USE_VISATTR wxVisualAttributes gva = wxListBox::GetClassDefaultAttributes(); wxVisualAttributes lva = wxPanel::GetClassDefaultAttributes(); wxColour gfg = gva.colFg; // grid foreground wxColour gbg = gva.colBg; // grid background wxColour lfg = lva.colFg; // label foreground wxColour lbg = lva.colBg; // label background #else // 2.4.x wxColour gfg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); wxColour gbg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ); wxColour lfg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); wxColour lbg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ); #endif //wxCHECK_VERSION(2,5,2) // Set default cell attributes wxSheetCellAttr *attr = &GetSheetRefData()->m_defaultGridCellAttr; attr->Create(); attr->SetKind(wxSHEET_AttrDefault); attr->SetFont(GetFont()); // need window created for this attr->SetAlignment(wxALIGN_LEFT | wxALIGN_TOP); attr->SetOrientation(wxHORIZONTAL); attr->SetLevel(wxSHEET_AttrLevelBottom); attr->SetOverflow(true); attr->SetOverflowMarker(true); attr->SetShowEditor(false); attr->SetReadOnly(false); attr->SetForegroundColour(gfg); attr->SetBackgroundColour(gbg); attr->SetRenderer(GetDefaultRendererForType(wxSHEET_VALUE_STRING)); attr->SetEditor(GetDefaultEditorForType(wxSHEET_VALUE_STRING)); wxFont labelFont = wxWindow::GetFont(); labelFont.SetWeight( wxBOLD ); // default row label attr attr = &GetSheetRefData()->m_defaultRowLabelAttr; attr->Create(); attr->SetKind(wxSHEET_AttrDefault); attr->SetFont(labelFont); // need window created for this attr->SetAlignment(wxALIGN_CENTRE); attr->SetOrientation(wxHORIZONTAL); attr->SetLevel(wxSHEET_AttrLevelBottom); attr->SetOverflow(false); attr->SetOverflowMarker(false); // just cutoff, looks better? attr->SetShowEditor(false); attr->SetReadOnly(true); attr->SetForegroundColour(lfg); attr->SetBackgroundColour(lbg); attr->SetRenderer(GetDefaultRendererForType(wxSHEET_VALUE_LABEL)); attr->SetEditor(GetDefaultEditorForType(wxSHEET_VALUE_STRING)); // default col and corner label attr are identical to row label attr GetSheetRefData()->m_defaultColLabelAttr = attr->Clone(); GetSheetRefData()->m_defaultCornerLabelAttr = attr->Clone(); // subwindow components that make up the wxSheet m_gridWin = new wxSheetChildWindow( this, ID_GRID_WINDOW ); m_rowLabelWin = new wxSheetChildWindow( this, ID_ROW_LABEL_WINDOW ); m_colLabelWin = new wxSheetChildWindow( this, ID_COL_LABEL_WINDOW ); m_cornerLabelWin = new wxSheetChildWindow( this, ID_CORNER_LABEL_WINDOW ); m_horizScrollBar = new wxScrollBar(this, ID_HORIZ_SCROLLBAR, wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL); m_vertScrollBar = new wxScrollBar(this, ID_VERT_SCROLLBAR, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL); // det the default colours for each window m_cornerLabelWin->SetOwnForegroundColour(lfg); m_cornerLabelWin->SetOwnBackgroundColour(lbg); m_rowLabelWin->SetOwnForegroundColour(lfg); m_rowLabelWin->SetOwnBackgroundColour(lbg); m_colLabelWin->SetOwnForegroundColour(lfg); m_colLabelWin->SetOwnBackgroundColour(lbg); m_gridWin->SetOwnForegroundColour(gfg); m_gridWin->SetOwnBackgroundColour(gbg); // figure out what a reasonable size would be int char_w = 5, char_h = 10; GetTextExtent(wxT("W1!(jJ"), &char_w, &char_h, NULL, NULL, &labelFont); #if defined(__WXMOTIF__) || defined(__WXGTK__) // see also text ctrl sizing in ShowCellEditControl() char_h += 8; #else char_h += 6; // test in wx24 #endif GetSheetRefData()->m_rowEdges.SetDefaultSize(char_h); GetSheetRefData()->AddSheet(this); #if wxCHECK_VERSION(2,7,2) SetInitialSize(size); #elif wxCHECK_VERSION(2,5,2) SetBestFittingSize(size); #endif // wxCHECK_VERSION(2,5,2) return true; } wxSheet::~wxSheet() { SetCaptureWindow(NULL); StopMouseTimer(); GetSheetRefData()->RemoveSheet(this); // destroy the edit control if this is the "parent" if (GetEditControl().Ok() && GetEditControl().GetControl()) { wxWindowID win_id = GetEditControl().GetControl()->GetId(); if (FindWindow(win_id) == GetEditControl().GetControl()) { GetSheetRefData()->m_cellEditor.DestroyControl(); GetSheetRefData()->m_cellEditor.Destroy(); GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; } } #ifdef DEBUG_ATTR_CACHE size_t total = gs_nAttrCacheHits + gs_nAttrCacheMisses; wxPrintf(_T("wxSheet attribute cache statistics: " "total: %u, hits: %u (%u%%)\n"), total, gs_nAttrCacheHits, total ? (gs_nAttrCacheHits*100) / total : 0); #endif } bool wxSheet::Destroy() { SetCaptureWindow(NULL); StopMouseTimer(); GetSheetRefData()->RemoveSheet(this); return wxWindow::Destroy(); } void wxSheet::RefSheet(wxSheet* sheet) { wxCHECK_RET(sheet, wxT("Invalid wxSheet")); SetCaptureWindow(NULL); StopMouseTimer(); GetSheetRefData()->RemoveSheet(this); // remove from old data UnRef(); Ref(*sheet); GetSheetRefData()->AddSheet(this); CalcWindowSizes(); } wxSheet* wxSheet::Clone(wxWindowID id) { wxSheet *sheet = (wxSheet*)GetClassInfo()->CreateObject(); sheet->Create(GetParent(), id); return sheet; } bool wxSheet::Enable(bool enable) { if ( !wxWindow::Enable(enable) ) return false; // redraw in the new state Refresh(); return true; } // ------------------------------------------------------------------------ bool wxSheet::SetTable( wxSheetTable *table, bool takeOwnership ) { if ( GetSheetRefData()->m_table ) { if (GetSheetRefData()->m_ownTable) delete GetSheetRefData()->m_table; if (GetSelection()) GetSelection()->Clear(); GetSheetRefData()->m_table = NULL; GetSheetRefData()->m_rowEdges.Clear(); GetSheetRefData()->m_colEdges.Clear(); } if (table) { GetSheetRefData()->m_rowEdges.UpdatePos(0, table->GetNumberRows()); GetSheetRefData()->m_colEdges.UpdatePos(0, table->GetNumberCols()); GetSheetRefData()->m_table = table; GetSheetRefData()->m_table->SetView( this ); GetSheetRefData()->m_ownTable = takeOwnership; CalcWindowSizes(); } return true; } bool wxSheet::CreateGrid( int numRows, int numCols, int options ) { // Create a table and assign it's data structures wxSheetTable *table = new wxSheetTable( this ); table->SetGridCellValueProvider(new wxSheetValueProviderString(numRows, numCols, options), true); //table->SetGridCellValueProvider(new wxSheetValueProviderSparseString(numRows, numCols, options), true); // label data containers are optional and needed only if you Set values for them // we create both of them. // NB. They're the same as the grid data but only have one row or col each. // NB. wxSHEET_ValueProviderColPref is used for the col labels since // we expect more cols than rows table->SetRowLabelValueProvider(new wxSheetValueProviderString(numRows, 1), true); table->SetColLabelValueProvider(new wxSheetValueProviderString(1, numCols, wxSHEET_ValueProviderColPref), true); // Set the attribute provider if you plan to "Set" attributes for particular // cells/rows/cols, otherwise the default attributes will suffice table->SetAttrProvider(new wxSheetCellAttrProvider, true); return SetTable(table, true); } // ------------------------------------------------------------------------ // Dimensions of the sheet wxSheetCell_Type wxSheet::GetCellCoordsType(const wxSheetCoords& coords) { if ((coords.m_row >= 0) && (coords.m_col >= 0)) { return wxSHEET_CELL_GRID; } else if (coords.m_row == -1) { if (coords.m_col == -1) return wxSHEET_CELL_CORNERLABEL; if (coords.m_col >= 0) return wxSHEET_CELL_COLLABEL; } else if (coords.m_col == -1) { if (coords.m_row >= 0) return wxSHEET_CELL_ROWLABEL; } return wxSHEET_CELL_UNKNOWN; } void wxSheet::ClearValues(int update) { if ( GetTable() ) { if (IsCellEditControlCreated()) DisableCellEditControl(false); GetTable()->ClearValues(update); RefreshGridWindow(); } } bool wxSheet::UpdateRows( size_t row, int numRows, int update ) { wxCHECK_MSG(GetTable(), false, wxT("Called wxSheet::UpdateRows() before calling CreateGrid()")); // the table should then call DoUpdateRows back on the sheet before returning return GetTable()->UpdateRows(row, numRows, update); } bool wxSheet::UpdateCols( size_t col, int numCols, int update ) { wxCHECK_MSG(GetTable(), false, wxT("Called wxSheet::UpdateCols() before calling CreateGrid()")); // the table should then call DoUpdateRows back on the sheet before returning return GetTable()->UpdateCols(col, numCols, update); } bool wxSheet::SetNumberCols( size_t cols, int update ) { const int n_cols = int(cols) - GetNumberCols(); if (n_cols > 0) return AppendCols(n_cols, update); else if (n_cols < 0) return DeleteCols(cols, -n_cols, update); return false; } bool wxSheet::SetNumberRows( size_t rows, int update ) { const int n_rows = int(rows) - GetNumberRows(); if (n_rows > 0) return AppendRows(n_rows, update); else if (n_rows < 0) return DeleteRows(rows, -n_rows, update); return false; } bool wxSheet::DoUpdateRows( size_t row, int numRows, int update) { // Clear the attribute cache as the attribute might refer to a invalid cell ClearAttrCache(); if (numRows == 0) return false; // By the same reasoning, the editor should be dismissed if columns are // added or removed. And for consistency, it should IMHO always be // removed, not only if the cell "underneath" it actually changes. // For now, I intentionally do not save the editor's content as the // cell it might want to save that stuff to might no longer exist. if (IsCellEditControlCreated()) DisableCellEditControl(false); // FIXME - do I want to UpdateRows/Cols for selection or just clear them // the event it would send would be confusing at best // first a deselect and then a select... should sel follow insert? // I don't think it's worth the confusion and since a click on // a cell is deselect all, the selection is not that precious. //ClearSelection(true); GetSheetRefData()->m_rowEdges.UpdatePos(row, numRows); // Update any data structures if ( ((update & wxSHEET_UpdateSelection) != 0) && GetSelection() ) GetSelection()->UpdateRows( row, numRows ); GetSheetRefData()->m_cursorCoords.UpdateRows(row, numRows); // try to force the cursor to a valid cell if ( !ContainsGridCell(GetGridCursorCell()) && ContainsGridCell(wxSheetCoords(0,0)) ) SetGridCursorCell( wxSheetCoords(0, 0) ); else GetSheetRefData()->m_cursorCoords = wxNullSheetCoords; AdjustScrollbars(); RefreshRowLabelWindow(true); RefreshGridWindow(); return true; } bool wxSheet::DoUpdateCols( size_t col, int numCols, int update) { ClearAttrCache(); if (numCols == 0) return false; if (IsCellEditControlCreated()) DisableCellEditControl(false); GetSheetRefData()->m_colEdges.UpdatePos(col, numCols); if ( ((update & wxSHEET_UpdateSelection) != 0) && GetSelection() ) GetSelection()->UpdateCols( col, numCols ); GetSheetRefData()->m_cursorCoords.UpdateCols(col, numCols); if ( !ContainsGridCell(GetGridCursorCell()) && ContainsGridCell(wxSheetCoords(0,0)) ) SetGridCursorCell( wxSheetCoords(0, 0) ); else GetSheetRefData()->m_cursorCoords = wxNullSheetCoords; AdjustScrollbars(); RefreshColLabelWindow(true); RefreshGridWindow(); return true; } // ---------------------------------------------------------------------------- // Dimensions of the row and column sizes void wxSheet::SetDefaultRowHeight( int height, bool resizeExistingRows ) { GetSheetRefData()->m_rowEdges.SetDefaultSize(height, resizeExistingRows); if ( resizeExistingRows && !GetBatchCount() ) CalcWindowSizes(true); } void wxSheet::SetDefaultColWidth( int width, bool resizeExistingCols ) { GetSheetRefData()->m_colEdges.SetDefaultSize(width, resizeExistingCols); if ( resizeExistingCols && !GetBatchCount() ) CalcWindowSizes(true); } void wxSheet::SetRowHeight( int row, int height ) { if (row == -1) { SetColLabelHeight(height); return; } wxCHECK_RET(ContainsGridRow(row), _T("invalid row index") ); const int old_height = GetRowHeight(row); // if < 0 calc new height from label if ( height < 0 ) height = GetCellBestSize(wxSheetCoords(row, -1)).y + 6; // FIXME test this // should we check that it's bigger than GetMinimalRowHeight(row) here? // (VZ) // No, because it is reasonable to assume the library user know's // what he is doing. However whe should test against the weaker // constariant of minimalAcceptableHeight, as this breaks rendering if ( height == old_height ) return; if (height < GetMinimalAcceptableRowHeight()) height = GetMinimalAcceptableRowHeight(); GetSheetRefData()->m_rowEdges.SetSize(row, height); if ( !GetBatchCount() ) { CalcWindowSizes(true); SetGridOrigin(GetGridOrigin(), true); RefreshBlock(wxSheetBlock(row, -1, GetNumberRows()-row+1, GetNumberCols()+1)); } } void wxSheet::SetColWidth( int col, int width ) { if (col == -1) { SetRowLabelWidth(width); return; } wxCHECK_RET(ContainsGridCol(col), _T("invalid column index") ); const int old_width = GetColWidth(col); if ( width < 0 ) width = GetCellBestSize(wxSheetCoords(-1, col)).x + 6; if ( width == old_width ) return; if ( width < GetMinimalAcceptableColWidth() ) width = GetMinimalAcceptableColWidth(); GetSheetRefData()->m_colEdges.SetSize(col, width); if ( !GetBatchCount() ) { CalcWindowSizes(true); SetGridOrigin(GetGridOrigin(), true); RefreshBlock(wxSheetBlock(-1, col, GetNumberRows()+1, GetNumberCols()-col+1)); } } int wxSheet::GetColWidth(int col) const { if (col == -1) return GetRowLabelWidth(); return GetSheetRefData()->m_colEdges.GetSize(col); } int wxSheet::GetColLeft(int col) const { if (col == -1) return 1; // 1 for border return GetSheetRefData()->m_colEdges.GetMin(col); } int wxSheet::GetColRight(int col) const { if (col == -1) return GetRowLabelWidth(); return GetSheetRefData()->m_colEdges.GetMax(col); } int wxSheet::GetRowHeight(int row) const { if (row == -1) return GetColLabelHeight(); return GetSheetRefData()->m_rowEdges.GetSize(row); } int wxSheet::GetRowTop(int row) const { if (row == -1) return 1; // 1 for border return GetSheetRefData()->m_rowEdges.GetMin(row); } int wxSheet::GetRowBottom(int row) const { if (row == -1) return GetColLabelHeight(); return GetSheetRefData()->m_rowEdges.GetMax(row); } wxSize wxSheet::GetCellSize(const wxSheetCoords& coords) const { return wxSize(GetColWidth(coords.m_row), GetRowHeight(coords.m_row)); } bool wxSheet::IsCellShown( const wxSheetCoords& coords ) const { wxCHECK_MSG(ContainsCell(coords), false, wxT("Invalid coords in wxSheet::IsCellShown")); return (GetColWidth(coords.GetCol()) > 0) && (GetRowHeight(coords.GetRow()) > 0); } wxSize wxSheet::GetCellBestSize(const wxSheetCoords& coords, wxDC *dc) const { wxCHECK_MSG(ContainsCell(coords), wxSize(GetDefaultColWidth(), GetDefaultRowHeight()), wxT("Invalid coords")); wxSheetCellAttr attr(GetAttr(coords)); wxSheet *sheet = (wxSheet*)this; wxSheetCellRenderer renderer(attr.GetRenderer(sheet, coords)); if (!dc) { wxClientDC cdc(sheet); return renderer.GetBestSize(*sheet, attr, cdc, coords); } return renderer.GetBestSize(*sheet, attr, *dc, coords); } int wxSheet::GetRowBestHeight(int row) const { wxCHECK_MSG(ContainsGridRow(row), GetDefaultRowHeight(), wxT("Invalid coords in wxSheet::GetRowBestHeight")); wxClientDC dc(m_gridWin); wxCoord bestHeight = 0; const int numCols = GetNumberCols(); wxSheetCoords coords( row, row ); for ( coords.m_col = -1; coords.m_col < numCols; coords.m_col++ ) { const int height = GetCellBestSize(coords, &dc).GetHeight(); if ( height > bestHeight ) bestHeight = height; } return bestHeight; } int wxSheet::GetColBestWidth(int col) const { wxCHECK_MSG(ContainsGridCol(col), GetDefaultColWidth(), wxT("Invalid col in wxSheet::GetColBestWidth")); wxClientDC dc(m_gridWin); wxCoord bestWidth = 0; const int numRows = GetNumberRows(); wxSheetCoords coords( col, col ); for ( coords.m_row = -1; coords.m_row < numRows; coords.m_row++ ) { const int width = GetCellBestSize(coords, &dc).GetWidth(); if ( width > bestWidth ) bestWidth = width; } return bestWidth; } // ---------------------------------------------------------------------------- // Row/Col label size and attributes int wxSheet::GetRowLabelWidth(bool zero_not_shown) const { if (zero_not_shown && !m_cornerLabelWin->IsShown() && !m_rowLabelWin->IsShown()) return 0; return GetSheetRefData()->m_rowLabelWidth; } int wxSheet::GetColLabelHeight(bool zero_not_shown) const { if (zero_not_shown && !m_cornerLabelWin->IsShown() && !m_colLabelWin->IsShown()) return 0; return GetSheetRefData()->m_colLabelHeight; } void wxSheet::SetRowLabelWidth( int width ) { width = wxMax( width, 0 ); if ( width == 0 ) { m_rowLabelWin->Show( false ); m_cornerLabelWin->Show( false ); } else if ( GetRowLabelWidth(false) > 0 ) { GetSheetRefData()->m_rowLabelWidth = width; m_rowLabelWin->Show( true ); if ( GetColLabelHeight() > 0 ) m_cornerLabelWin->Show( true ); } CalcWindowSizes(); } void wxSheet::SetColLabelHeight( int height ) { height = wxMax( height, 0 ); if ( height == 0 ) { m_colLabelWin->Show( false ); m_cornerLabelWin->Show( false ); } else if ( GetColLabelHeight(false) > 0 ) { GetSheetRefData()->m_colLabelHeight = height; m_colLabelWin->Show( true ); if ( GetRowLabelWidth() > 0 ) m_cornerLabelWin->Show( true ); } CalcWindowSizes(); } // ---------------------------------------------------------------------------- // Auto sizing of the row/col widths/heights int wxSheet::AutoSizeRow( int row, bool setAsMin ) { wxCHECK_MSG(ContainsGridRow(row), 0, wxT("Invalid coords in wxSheet::AutoSizeRow")); int bestHeight = GetRowBestHeight(row); // if empty row - give default extent (notice that if extentMax is less // than default extent but != 0, it's ok) if ( bestHeight == 0 ) bestHeight = GetDefaultRowHeight(); else bestHeight += 6; // leave some space around text if (GetRowHeight(row) != bestHeight) SetRowHeight(row, bestHeight); if ( setAsMin ) SetMinimalRowHeight(row, bestHeight); return bestHeight; } int wxSheet::AutoSizeCol( int col, bool setAsMin ) { wxCHECK_MSG(ContainsGridCol(col), 0, wxT("Invalid col in wxSheet::AutoSizeCol")); int bestWidth = GetColBestWidth(col); if ( bestWidth == 0 ) bestWidth = GetDefaultColWidth(); else bestWidth += 10; // leave some space around text if (GetColWidth(col) != bestWidth) SetColWidth(col, bestWidth); if ( setAsMin ) SetMinimalColWidth(col, bestWidth); return bestWidth; } void wxSheet::AutoSizeRows(bool setAsMin) { BeginBatch(); const int numRows = GetNumberRows(); for ( int row = 0; row < numRows; row++ ) AutoSizeRow(row, setAsMin); EndBatch(); } void wxSheet::AutoSizeCols(bool setAsMin) { BeginBatch(); const int numCols = GetNumberCols(); for ( int col = 0; col < numCols; col++ ) AutoSizeCol(col, setAsMin); EndBatch(); } void wxSheet::AutoSize(bool setAsMin) { BeginBatch(); SetMargins(0, 0); AutoSizeRows(setAsMin); AutoSizeCols(setAsMin); wxSize sizeFit(GetGridVirtualSize()); sizeFit.x += GetRowLabelWidth(); sizeFit.y += GetColLabelHeight(); wxSize winSize(GetClientSize()); // distribute the extra space between the columns/rows to avoid having // extra white space const int numCols = GetNumberCols(); const int numRows = GetNumberRows(); // Remove the extra m_extraWidth + 1 added above wxCoord diff = winSize.x - sizeFit.x; if ( diff && numCols ) { // try to resize the columns uniformly wxCoord diffPerCol = diff / numCols; if ( diffPerCol != 0 ) { for ( int col = 0; col < numCols; col++ ) SetColWidth(col, GetColWidth(col) + diffPerCol); } // add remaining amount to the last columns diff -= diffPerCol * numCols; if ( diff != 0 ) { for ( int col = numCols - 1; col >= numCols - diff; col-- ) SetColWidth(col, GetColWidth(col) + 1); } } // same for rows diff = winSize.y - sizeFit.y; if ( diff && numRows ) { // try to resize the columns uniformly wxCoord diffPerRow = diff / numRows; if ( diffPerRow != 0 ) { for ( int row = 0; row < numRows; row++ ) SetRowHeight(row, GetRowHeight(row) + diffPerRow); } // add remaining amount to the last rows diff -= diffPerRow * numRows; if ( diff != 0 ) { for ( int row = numRows - 1; row >= numRows - diff; row-- ) SetRowHeight(row, GetRowHeight(row) + 1); } } sizeFit = GetGridVirtualSize(); sizeFit.x += GetRowLabelWidth(); sizeFit.y += GetColLabelHeight(); SetClientSize(sizeFit + wxSize(2,2)); // FIXME ? Where's the extra 2 from in wxGTK EndBatch(); } void wxSheet::AutoSizeRowLabelHeight( int row ) { wxCHECK_RET(ContainsGridRow(row), wxT("Invalid row in wxSheet::AutoSizeRowLabelHeight")); // Hide the edit control, so it won't interfer with drag-shrinking. if ( IsCellEditControlShown() ) DisableCellEditControl(true); // autosize row height depending on label text const wxSheetCoords coords(row, -1); wxSize size(GetCellBestSize(coords)); if (size.y < GetDefaultRowHeight()) size.y = GetDefaultRowHeight(); SetRowHeight(row, size.y); } void wxSheet::AutoSizeColLabelWidth( int col ) { wxCHECK_RET(ContainsGridCol(col), wxT("Invalid col in wxSheet::AutoSizeColLabelWidth")); // Hide the edit control, so it won't interfer with drag-shrinking. if ( IsCellEditControlShown() ) DisableCellEditControl(true); // autosize column width depending on label text const wxSheetCoords coords(-1, col); wxSize size(GetCellBestSize(coords)); if (size.x < GetDefaultColWidth()) size.x = GetDefaultColWidth(); SetColWidth(col, size.x); } void wxSheet::SetEqualColWidths(int min_width) { GetSheetRefData()->m_equal_col_widths = wxMax(min_width, 0); const int numCols = GetNumberCols(); // don't fail here, since EVT_SIZEs are generated before the grid is if ((min_width > 0) && (numCols > 0) && GetTable() && m_gridWin) { const int colwidth = m_gridWin->GetClientSize().GetWidth()/numCols; SetDefaultColWidth( colwidth, true ); } } // ---------------------------------------------------------------------------- // Grid line and cell highlight colouring void wxSheet::EnableGridLines( int dir ) { GetSheetRefData()->m_gridLinesEnabled = dir; RefreshGridWindow(false); } void wxSheet::SetGridLineColour( const wxColour& colour ) { wxCHECK_RET(colour.Ok(), wxT("Invalid colour in wxSheet::SetGridLineColour")); GetSheetRefData()->m_gridLineColour = colour; RefreshGridWindow(false); } void wxSheet::SetCursorCellHighlightColour( const wxColour& colour ) { wxCHECK_RET(colour.Ok(), wxT("Invalid colour in wxSheet::SetGridLineColour")); GetSheetRefData()->m_cursorCellHighlightColour = colour; if (ContainsCell(GetGridCursorCell())) RefreshCell(GetGridCursorCell(), true); } void wxSheet::SetCursorCellHighlightPenWidth(int width) { wxCHECK_RET(width >= 0, wxT("Invalid pen width in wxSheet::SetGridLineColour")); GetSheetRefData()->m_cursorCellHighlightPenWidth = width; if (ContainsCell(GetGridCursorCell())) RefreshCell(GetGridCursorCell(), true); } void wxSheet::SetCursorCellHighlightROPenWidth(int width) { wxCHECK_RET(width >= 0, wxT("Invalid pen width in wxSheet::SetCursorCellHighlightROPenWidth")); GetSheetRefData()->m_cursorCellHighlightROPenWidth = width; if (ContainsCell(GetGridCursorCell())) RefreshCell(GetGridCursorCell(), true); } void wxSheet::SetLabelOutlineColour( const wxColour& colour ) { wxCHECK_RET(colour.Ok(), wxT("Invalid colour in wxSheet::SetLabelOutlineColour")); GetSheetRefData()->m_labelOutlineColour = colour; RefreshColLabelWindow(true); RefreshRowLabelWindow(true); RefreshCornerLabelWindow(true); } // ---------------------------------------------------------------------------- // Spanned cells bool wxSheet::HasSpannedCells() const { return GetTable() && GetTable()->HasSpannedCells(); } wxSheetCoords wxSheet::GetCellOwner( const wxSheetCoords& coords ) const { return GetCellBlock(coords).GetLeftTop(); } wxSheetBlock wxSheet::GetCellBlock( const wxSheetCoords& coords ) const { return GetTable() ? GetTable()->GetCellBlock(coords) : wxSheetBlock(coords, 1, 1); } wxSheetCoords wxSheet::GetCellSpan( const wxSheetCoords& coords ) const { const wxSheetBlock block(GetCellBlock(coords)); if (coords == block.GetLeftTop()) return block.GetSize(); else return block.GetLeftTop() - coords; } void wxSheet::SetCellSpan( const wxSheetBlock& block ) { wxCHECK_RET(GetTable(), wxT("The wxSheetTable doesn't exist to SetCellSpan")); GetTable()->SetCellSpan(block); } // **************************************************************************** wxSheetCellAttr wxSheet::GetOrCreateAttr(const wxSheetCoords& coords, wxSheetAttr_Type type) const { wxSheetCellAttr attr; wxCHECK_MSG( type != wxSHEET_AttrAny, attr, wxT("Cannot create attribute of type wxSHEET_AttrAny") ); if (IsGridCell(coords)) { switch (type) { case wxSHEET_AttrDefault : return DoGetDefaultGridAttr(); case wxSHEET_AttrCell : case wxSHEET_AttrRow : case wxSHEET_AttrCol : { wxCHECK_MSG(GetTable() && ContainsGridCell(coords), attr, wxT("Invalid table or attr coords")); attr = GetTable()->GetAttr(coords, type); if ( !attr.Ok() ) { attr.Create(); attr.SetKind(type); attr.SetDefaultAttr(DoGetDefaultGridAttr()); GetTable()->SetAttr(coords, attr, type); } else InitAttr(attr, DoGetDefaultGridAttr()); return attr; } default : { wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); return attr; } } } else if (IsCornerLabelCell(coords)) { switch (type) { case wxSHEET_AttrDefault : // only one of these, ever case wxSHEET_AttrCell : return DoGetDefaultCornerLabelAttr(); default : { wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); return attr; } } } else if (IsRowLabelCell(coords)) { switch (type) { case wxSHEET_AttrDefault : return DoGetDefaultRowLabelAttr(); case wxSHEET_AttrCell : { wxCHECK_MSG(GetTable() && ContainsRowLabelCell(coords), attr, wxT("Invalid table or attr coords")); attr = GetTable()->GetAttr(coords, type); if ( !attr.Ok() ) { attr.Create(); attr.SetKind(type); attr.SetDefaultAttr(DoGetDefaultRowLabelAttr()); GetTable()->SetAttr(coords, attr, type); } else InitAttr(attr, DoGetDefaultRowLabelAttr()); return attr; } default : { wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); return attr; } } } else if (IsColLabelCell(coords)) { switch (type) { case wxSHEET_AttrDefault : return DoGetDefaultColLabelAttr(); case wxSHEET_AttrCell : { wxCHECK_MSG(GetTable() && ContainsColLabelCell(coords), attr, wxT("Invalid table or attr coords")); attr = GetTable()->GetAttr(coords, type); if ( !attr.Ok() ) { attr.Create(); attr.SetKind(type); attr.SetDefaultAttr(DoGetDefaultColLabelAttr()); GetTable()->SetAttr(coords, attr, type); } else InitAttr(attr, DoGetDefaultColLabelAttr()); return attr; } default : { wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); return attr; } } } wxFAIL_MSG(wxString::Format(wxT("Unable to get or create attribute for cell(%d,%d)"), coords.m_row, coords.m_col)); return wxSheetCellAttr(); } wxSheetCellAttr wxSheet::GetAttr(const wxSheetCoords& coords, wxSheetAttr_Type type) const { if (IsGridCell(coords)) { switch (type) { case wxSHEET_AttrDefault : return DoGetDefaultGridAttr(); case wxSHEET_AttrCell : case wxSHEET_AttrRow : case wxSHEET_AttrCol : case wxSHEET_AttrAny : default : { wxCHECK_MSG(ContainsGridCell(coords), DoGetDefaultGridAttr(), wxT("Invalid attr coords")); wxSheetCellAttr attr; if ( !LookupAttr(coords, type, attr) ) { if (GetTable()) { attr = GetTable()->GetAttr(coords, type); if (attr.Ok()) CacheAttr(coords, attr, type); } } if ((type == wxSHEET_AttrAny) && !attr.Ok()) attr = DoGetDefaultGridAttr(); return attr; } } } else if (IsCornerLabelCell(coords)) { switch (type) { case wxSHEET_AttrDefault : case wxSHEET_AttrCell : // only one of these, ever case wxSHEET_AttrAny : return DoGetDefaultCornerLabelAttr(); default : { wxFAIL_MSG(wxT("Invalid attr type for corner label")); } } return wxNullSheetCellAttr; } else if (IsRowLabelCell(coords)) { switch (type) { case wxSHEET_AttrDefault : return DoGetDefaultRowLabelAttr(); case wxSHEET_AttrCell : case wxSHEET_AttrAny : { wxCHECK_MSG(ContainsRowLabelCell(coords), DoGetDefaultRowLabelAttr(), wxT("Invalid attr coords")); wxSheetCellAttr attr; if (GetTable()) attr = GetTable()->GetAttr(coords, type); if ((type == wxSHEET_AttrAny) && !attr.Ok()) attr = DoGetDefaultRowLabelAttr(); return attr; } default : { wxFAIL_MSG(wxT("Invalid attr type for row label")); } } } else if (IsColLabelCell(coords)) { switch (type) { case wxSHEET_AttrDefault : return DoGetDefaultColLabelAttr(); case wxSHEET_AttrCell : case wxSHEET_AttrAny : { wxCHECK_MSG(ContainsColLabelCell(coords), DoGetDefaultColLabelAttr(), wxT("Invalid attr coords")); wxSheetCellAttr attr; if (GetTable()) attr = GetTable()->GetAttr(coords, type); if ((type == wxSHEET_AttrAny) && !attr.Ok()) attr = DoGetDefaultColLabelAttr(); return attr; } default : { wxFAIL_MSG(wxT("Invalid attr type for col label")); } } } // return garbage, maybe they can hobble along for a bit this way wxFAIL_MSG(wxString::Format(wxT("Unable to get attribute for cell(%d,%d)"), coords.m_row, coords.m_col)); return wxSheetCellAttr(true); } void wxSheet::SetAttr(const wxSheetCoords& coords, const wxSheetCellAttr& attr_, wxSheetAttr_Type type) { wxCHECK_RET(attr_.Ok(), wxT("Invalid attribute in wxSheet::SetDefaultAttr")); wxCHECK_RET( type != wxSHEET_AttrAny, wxT("Cannot create attribute of type wxSHEET_AttrAny") ); wxSheetCellAttr attr(attr_); ClearAttrCache(); if (IsGridCell(coords)) { switch (type) { case wxSHEET_AttrDefault : { wxSheetCellAttr defAttr(DoGetDefaultGridAttr()); defAttr.UpdateWith(attr); // force good vals after update defAttr.SetDefaultAttr(wxNullSheetCellAttr); defAttr.SetKind(wxSHEET_AttrDefault); return; } case wxSHEET_AttrCell : case wxSHEET_AttrRow : case wxSHEET_AttrCol : { wxCHECK_RET(GetTable() && ContainsGridCell(coords), wxT("Invalid table or attr coords")); if (attr.Ok()) InitAttr(attr, DoGetDefaultGridAttr()); GetTable()->SetAttr(coords, attr, type); return; } default : { wxFAIL_MSG(wxT("Invalid attr type for grid cell")); return; } } } else if (IsCornerLabelCell(coords)) { // only one attr for the corner window switch (type) { case wxSHEET_AttrDefault : case wxSHEET_AttrCell : { wxSheetCellAttr defAttr(DoGetDefaultCornerLabelAttr()); defAttr.UpdateWith(attr); // force good vals after update defAttr.SetDefaultAttr(wxNullSheetCellAttr); defAttr.SetKind(wxSHEET_AttrDefault); return; } default : { wxFAIL_MSG(wxT("Invalid attr type for corner label")); return; } } } else if (IsRowLabelCell(coords)) { switch (type) { case wxSHEET_AttrDefault : { wxSheetCellAttr defAttr(DoGetDefaultRowLabelAttr()); defAttr.UpdateWith(attr); // force good vals after update defAttr.SetDefaultAttr(wxNullSheetCellAttr); defAttr.SetKind(wxSHEET_AttrDefault); return; } case wxSHEET_AttrCell : { wxCHECK_RET(GetTable() && ContainsRowLabelCell(coords), wxT("Invalid table or attr coords")); if (attr.Ok()) InitAttr(attr, DoGetDefaultRowLabelAttr()); GetTable()->SetAttr(coords, attr, type); return; } default : { wxFAIL_MSG(wxT("Invalid attr type for row label")); return; } } } else if (IsColLabelCell(coords)) { switch (type) { case wxSHEET_AttrDefault : { wxSheetCellAttr defAttr(DoGetDefaultRowLabelAttr()); defAttr.UpdateWith(attr); // force good vals after update defAttr.SetDefaultAttr(wxNullSheetCellAttr); defAttr.SetKind(wxSHEET_AttrDefault); return; } case wxSHEET_AttrCell : { wxCHECK_RET(GetTable() && ContainsColLabelCell(coords), wxT("Invalid table or attr coords")); if (attr.Ok()) InitAttr(attr, DoGetDefaultColLabelAttr()); GetTable()->SetAttr(coords, attr, type); return; } default : { wxFAIL_MSG(wxT("Invalid attr type for col label")); return; } } } wxFAIL_MSG(wxString::Format(wxT("Unable to set attribute for cell(%d,%d)"), coords.m_row, coords.m_col)); } bool wxSheet::InitAttr( wxSheetCellAttr& initAttr, const wxSheetCellAttr& defAttr ) const { if (initAttr == defAttr) return false; wxSheetCellAttr attr(initAttr); wxSheetCellAttr attrDef(attr.GetDefaultAttr()); // only 100000 def attr, should be enough? for (int n=0; n<100000; n++) { if (!attrDef.Ok()) { attr.SetDefaultAttr(defAttr); return true; } else if (attrDef == defAttr) { return false; // already set } attr = attrDef; attrDef = attr.GetDefaultAttr(); } wxFAIL_MSG(wxT("Unable to set default attribute for cell")); return false; } const wxColour& wxSheet::GetAttrBackgroundColour( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetBackgroundColour(); } const wxColour& wxSheet::GetAttrForegoundColour( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetForegroundColour(); } const wxFont& wxSheet::GetAttrFont( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetFont(); } int wxSheet::GetAttrAlignment( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetAlignment(); } int wxSheet::GetAttrOrientation( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetOrientation(); } int wxSheet::GetAttrLevel( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetLevel(); } bool wxSheet::GetAttrOverflow( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetOverflow(); } bool wxSheet::GetAttrOverflowMarker( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetOverflowMarker(); } bool wxSheet::GetAttrShowEditor( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetShowEditor(); } bool wxSheet::GetAttrReadOnly( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetReadOnly(); } wxSheetCellRenderer wxSheet::GetAttrRenderer( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetRenderer((wxSheet*)this, coords); } wxSheetCellEditor wxSheet::GetAttrEditor( const wxSheetCoords& coords, wxSheetAttr_Type type ) const { return GetAttr(coords, type).GetEditor((wxSheet*)this, coords); } void wxSheet::SetAttrBackgroundColour( const wxSheetCoords& coords, const wxColour& colour, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetBackgroundColour(colour); RefreshAttrChange(coords, type); } void wxSheet::SetAttrForegroundColour( const wxSheetCoords& coords, const wxColour& colour, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetForegroundColour(colour); RefreshAttrChange(coords, type); } void wxSheet::SetAttrFont( const wxSheetCoords& coords, const wxFont& font, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetFont(font); RefreshAttrChange(coords, type); } void wxSheet::SetAttrAlignment( const wxSheetCoords& coords, int align, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetAlignment(align); RefreshAttrChange(coords, type); } void wxSheet::SetAttrOrientation( const wxSheetCoords& coords, int orient, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetOrientation(orient); RefreshAttrChange(coords, type); } void wxSheet::SetAttrLevel( const wxSheetCoords& coords, int level, wxSheetAttr_Type type ) { wxCHECK_RET(type != wxSHEET_AttrDefault, wxT("Unable to change level of default attribute")); GetOrCreateAttr(coords, type).SetLevel(wxSheetAttrLevel_Type(level)); RefreshAttrChange(coords, type); } void wxSheet::SetAttrOverflow( const wxSheetCoords& coords, bool allow, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetOverflow(allow); RefreshAttrChange(coords, type); } void wxSheet::SetAttrOverflowMarker( const wxSheetCoords& coords, bool draw_marker, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetOverflowMarker(draw_marker); RefreshAttrChange(coords, type); } void wxSheet::SetAttrShowEditor( const wxSheetCoords& coords, bool show_editor, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetShowEditor(show_editor); RefreshAttrChange(coords, type); } void wxSheet::SetAttrReadOnly( const wxSheetCoords& coords, bool isReadOnly, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetReadOnly(isReadOnly); RefreshAttrChange(coords, type); } void wxSheet::SetAttrRenderer( const wxSheetCoords& coords, const wxSheetCellRenderer& renderer, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetRenderer(renderer); RefreshAttrChange(coords, type); } void wxSheet::SetAttrEditor( const wxSheetCoords& coords, const wxSheetCellEditor& editor, wxSheetAttr_Type type ) { GetOrCreateAttr(coords, type).SetEditor(editor); RefreshAttrChange(coords, type); } // ---------------------------------------------------------------------------- // Get/Set the attributes for individual sheet cells/rows/cols void wxSheet::SetColFormatFloat(int col, int width, int precision) { wxString typeName = wxSHEET_VALUE_FLOAT; if ( (width != -1) || (precision != -1) ) typeName << _T(':') << width << _T(',') << precision; SetColFormatCustom(col, typeName); } void wxSheet::SetColFormatCustom(int col, const wxString& typeName) { wxCHECK_RET(ContainsGridCol(col), wxT("Invalid col in wxSheet::SetColFormatCustom")); wxSheetCellRenderer ren(GetDefaultRendererForType(typeName)); wxCHECK_RET(ren.Ok(), wxT("Invalid renderer in wxSheet::SetColFormatCustom")); SetAttrRenderer(wxSheetCoords(0,col), ren.Clone(), wxSHEET_AttrCol); } // ---------------------------------------------------------------------------- // Get/Set cell value wxString wxSheet::GetCellValue( const wxSheetCoords& coords ) { if ( GetTable() ) return GetTable()->GetValue( coords ); return wxEmptyString; } void wxSheet::SetCellValue( const wxSheetCoords& coords, const wxString& s ) { wxCHECK_RET( GetTable(), wxT("Invalid sheet table for SetCellValue")); GetTable()->SetValue( coords, s ); // Note: If we are using IsCellEditControlEnabled, // this interacts badly with calling SetCellValue from // an EVT_SHEET_CELL_CHANGE handler. if ((GetEditControlCoords() == coords) && IsCellEditControlShown()) { HideCellEditControl(); ShowCellEditControl(); // will reread data from table } else RefreshCell(coords, false); } bool wxSheet::HasCellValue( const wxSheetCoords& coords ) { if ( GetTable() ) return GetTable()->HasValue( coords ); // this tries the table too, but maybe they've only overridden GetCellValue return !GetCellValue(coords).IsEmpty(); } // ---------------------------------------------------------------------------- // Register mapping between data types to Renderers/Editors void wxSheet::RegisterDataType(const wxString& typeName, const wxSheetCellRenderer& renderer, const wxSheetCellEditor& editor) { GetSheetRefData()->m_typeRegistry->RegisterDataType(typeName, renderer, editor); } wxSheetCellEditor wxSheet::GetDefaultEditorForType(const wxString& typeName) const { int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(typeName); wxCHECK_MSG(index != wxNOT_FOUND, wxNullSheetCellEditor, wxT("Unknown data type name")); return GetSheetRefData()->m_typeRegistry->GetEditor(index); } wxSheetCellRenderer wxSheet::GetDefaultRendererForType(const wxString& typeName) const { int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(typeName); wxCHECK_MSG(index != wxNOT_FOUND, wxNullSheetCellRenderer, wxT("Unknown data type name")); return GetSheetRefData()->m_typeRegistry->GetRenderer(index); } wxSheetCellEditor wxSheet::GetDefaultEditorForCell(const wxSheetCoords& coords) const { wxCHECK_MSG(GetTable(), wxNullSheetCellEditor, wxT("Grid table is not created")); //return GetDefaultEditorForType(GetTable()->GetTypeName(coords)); // Default is to NOT use this as a default, but the defAttr's editor int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(GetTable()->GetTypeName(coords)); if (index == wxNOT_FOUND) return wxNullSheetCellEditor; return GetSheetRefData()->m_typeRegistry->GetEditor(index); } wxSheetCellRenderer wxSheet::GetDefaultRendererForCell(const wxSheetCoords& coords) const { if (!GetTable()) return wxNullSheetCellRenderer; //return GetDefaultRendererForType(GetTable()->GetTypeName(coords)); // Default is to NOT use this as a default, but the defAttr's renderer int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(GetTable()->GetTypeName(coords)); if (index == wxNOT_FOUND) return wxNullSheetCellRenderer; return GetSheetRefData()->m_typeRegistry->GetRenderer(index); } // ---------------------------------------------------------------------------- // Cursor movement and visibility functions bool wxSheet::IsCellVisible( const wxSheetCoords& coords, bool wholeCellVisible ) const { wxCHECK_MSG(ContainsCell(coords), false, wxT("Invalid coords in wxSheet::IsCellVisible")); const wxRect clientRect(wxPoint(0,0), GetWindowForCoords(coords)->GetClientSize()); const wxRect devRect(CellToRect(coords, true)); // rect in device coords if ( wholeCellVisible ) // is the whole cell visible? { wxRect intersectRect( devRect.Intersect(clientRect) ); return intersectRect == devRect; } return devRect.Intersects(clientRect); // is the cell partly visible ? } bool wxSheet::IsRowVisible( int row, bool wholeRowVisible ) const { if (row == -1) return m_colLabelWin && m_colLabelWin->IsShown(); wxCHECK_MSG(ContainsGridRow(row), false, wxT("Invalid row in wxSheet::IsRowVisible")); const wxRect clientRect(wxPoint(0,0), m_gridWin->GetClientSize()); const wxRect logRect(0, GetRowTop(row), clientRect.width, GetRowHeight(row)); const wxRect devRect(clientRect.x, CalcScrolledRect(logRect).y, logRect.width, logRect.height); if (wholeRowVisible) // is the whole row visible? { wxRect intersectRect( devRect.Intersect(clientRect) ); return intersectRect == devRect; } return devRect.Intersects(clientRect); // is the cell partly visible ? } bool wxSheet::IsColVisible( int col, bool wholeColVisible ) const { if (col == -1) return m_rowLabelWin && m_rowLabelWin->IsShown(); wxCHECK_MSG(ContainsGridCol(col), false, wxT("Invalid row in wxSheet::IsColVisible")); const wxRect clientRect(wxPoint(0,0), m_gridWin->GetClientSize()); const wxRect logRect(GetColLeft(col), 0, GetColWidth(col), clientRect.height); const wxRect devRect(CalcScrolledRect(logRect).x, clientRect.y, logRect.width, logRect.height); if (wholeColVisible) // is the whole row visible? { wxRect intersectRect( devRect.Intersect(clientRect) ); return intersectRect == devRect; } return devRect.Intersects(clientRect); // is the cell partly visible ? } void wxSheet::MakeCellVisible( const wxSheetCoords& coords ) { wxCHECK_RET(ContainsCell(coords), wxT("Invalid coords in wxSheet::MakeCellVisible")); if (IsCornerLabelCell(coords)) return; int xpos = -1, ypos = -1; const wxRect logRect( CellToRect(coords) ); // cell rect in logical coords const wxRect devRect( CalcScrolledRect(logRect) ); // rect in device coords int x0, y0, cw, ch; m_gridWin->GetClientSize( &cw, &ch ); CalcUnscrolledPosition(0, 0, &x0, &y0); if (!IsColLabelCell(coords)) { if ( devRect.GetTop() < 0 ) { ypos = logRect.GetTop(); ypos -= SHEET_SCROLL_LINE_Y; // add a little padding if (ypos < 0) ypos = 0; } else if ( devRect.GetBottom() > ch ) { ypos = y0 + (devRect.GetBottom() - ch); ypos += SHEET_SCROLL_LINE_Y; if (ypos < 0) ypos = 0; } } if (!IsRowLabelCell(coords)) { if ( devRect.GetLeft() < 0 ) { xpos = logRect.GetLeft(); xpos -= SHEET_SCROLL_LINE_X; if (xpos < 0) xpos = 0; } else if ( devRect.GetRight() > cw ) { xpos = x0 + (devRect.GetRight() - cw); xpos += SHEET_SCROLL_LINE_X; if (xpos < 0) xpos = 0; } } // -1 means leave that postion the same, see if (x/ypos < 0) x/ypos = 0 above if ((xpos != -1) || (ypos != -1)) SetGridOrigin( xpos, ypos, true, true ); } void wxSheet::SetGridCursorCell( const wxSheetCoords& coords ) { // Note: can set to invalid coords < 0 to hide cursor, but not out of range wxCHECK_RET((coords.GetRow() < GetNumberRows()) && (coords.GetCol() < GetNumberCols()), wxT("Invalid coords in wxSheet::SetGridCursorCell")); if (GetGridCursorCell() == coords) return; m_waitForSlowClick = false; // the event has been intercepted - do nothing if (SendEvent(wxEVT_SHEET_SELECTING_CELL, coords) != EVT_SKIPPED) return; const wxSheetCoords oldCursorCell(GetGridCursorCell()); if ( ContainsGridCell(oldCursorCell) ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); // Otherwise refresh redraws the highlight! GetSheetRefData()->m_cursorCoords = coords; RefreshCell(oldCursorCell, true); } GetSheetRefData()->m_cursorCoords = coords; if (ContainsGridCell(GetGridCursorCell())) RefreshCell(GetGridCursorCell(), true); SendEvent(wxEVT_SHEET_SELECTED_CELL, coords); } bool wxSheet::DoMoveCursor( const wxSheetCoords& relCoords, bool expandSelection ) { const wxSheetCoords cursorCoords(GetGridCursorCell()); const wxSheetCoords coords( cursorCoords + relCoords ); if ( (relCoords == wxSheetCoords(0,0)) || !ContainsGridCell(cursorCoords) || !ContainsGridCell(coords) ) return false; if ( expandSelection) { m_keySelecting = true; if ( !ContainsGridCell(GetSelectingAnchor()) ) SetSelectingAnchor(cursorCoords); } else ClearSelection(true); MakeCellVisible( coords ); SetGridCursorCell( coords ); if (expandSelection && !HasSelectionMode(wxSHEET_SelectNone)) HighlightSelectingBlock( GetSelectingAnchor(), GetGridCursorCell() ); return true; } bool wxSheet::DoMoveCursorBlock( const wxSheetCoords& relDir, bool expandSelection ) { const wxSheetCoords cursorCoords(GetGridCursorCell()); wxSheetCoords coords(cursorCoords + relDir); if ( !ContainsGridCell(cursorCoords) || !ContainsGridCell(coords) ) return false; if ( !HasCellValue(cursorCoords) ) { // starting in an empty cell: find the next block of non-empty cells while ( ContainsGridCell(coords) ) { if (HasCellValue(coords) || !ContainsGridCell(coords + relDir)) break; coords += relDir; } } else if ( !HasCellValue(coords) ) { // starting at the edge of a block: find the next block while ( ContainsGridCell(coords + relDir) ) { coords += relDir; if ( HasCellValue(coords) ) break; } } else { // starting within a block with value: find the edge of the block while ( ContainsGridCell(coords + relDir) ) { if ( !HasCellValue(coords + relDir) ) break; coords += relDir; } } return DoMoveCursor(coords-cursorCoords, expandSelection); } bool wxSheet::DoMoveCursorUpDownPage( bool page_up, bool expandSelection ) { if (!ContainsGridCell(GetGridCursorCell())) return false; const int row = GetGridCursorRow(); if ((page_up && (row < 1)) || (!page_up && (row >= GetNumberRows() - 1))) return false; int cw, ch; m_gridWin->GetClientSize( &cw, &ch ); int y = GetRowTop(row) + (page_up ? (-ch + 1) : ch); const int newRow = YToGridRow( y, true ); return DoMoveCursor(wxSheetCoords(newRow - row, 0), expandSelection); } // ---------------------------------------------------------------------------- // Cell/Row/Col selection and deselection bool wxSheet::HasSelection(bool selecting) const { if (selecting) return (!GetSelectingBlock().IsEmpty() || (GetSelection() && GetSelection()->HasSelection())); return GetSelection() && GetSelection()->HasSelection(); } bool wxSheet::IsCellSelected( const wxSheetCoords& coords ) const { return ( GetSelectingBlock().Contains(coords) || (GetSelection() && GetSelection()->Contains(coords)) ); } bool wxSheet::IsRowSelected( int row ) const { wxSheetBlock rowBlock(row, 0, 1, GetNumberCols()); // not +1 return ( GetSelectingBlock().Contains(rowBlock) || (GetSelection() && GetSelection()->Contains(rowBlock)) ); } bool wxSheet::IsColSelected( int col ) const { wxSheetBlock colBlock(0, col, GetNumberRows(), 1); // not +1 return ( GetSelectingBlock().Contains(colBlock) || (GetSelection() && GetSelection()->Contains(colBlock)) ); } void wxSheet::SetSelectionMode(wxSheetSelectionMode_Type selmode) { wxCHECK_RET( GetSelection(), wxT("Called wxSheet::SetSelectionMode() before calling CreateGrid()") ); // yes we could patch up the selection, but does it really make sense? // like you'd have to send a slew of confusing (de)selection events ClearSelection(true); GetSheetRefData()->m_selectionMode = selmode; } bool wxSheet::SelectRow( int row, bool addToSelected, bool sendEvt ) { if (HasSelectionMode(wxSHEET_SelectCols)) return false; // selection to # of cols means whole row is selected return SelectBlock( wxSheetBlock(row, 0, 1, GetNumberCols()+1), addToSelected, sendEvt ); } bool wxSheet::SelectRows( int rowTop, int rowBottom, bool addToSelected, bool sendEvt ) { if (HasSelectionMode(wxSHEET_SelectCols) || (rowTop > rowBottom)) return false; // selection to # of cols means whole row is selected return SelectBlock( wxSheetBlock(rowTop, 0, rowBottom-rowTop+1, GetNumberCols()+1), addToSelected, sendEvt ); } bool wxSheet::SelectCol( int col, bool addToSelected, bool sendEvt ) { if (HasSelectionMode(wxSHEET_SelectRows)) return false; // selection to # of rows means whole col is selected return SelectBlock( wxSheetBlock(0, col, GetNumberRows()+1, 1), addToSelected, sendEvt ); } bool wxSheet::SelectCols( int colLeft, int colRight, bool addToSelected, bool sendEvt ) { if (HasSelectionMode(wxSHEET_SelectRows) || (colLeft > colRight)) return false; // selection to # of rows means whole col is selected return SelectBlock( wxSheetBlock(0, colLeft, GetNumberRows()+1, colRight-colLeft+1), addToSelected, sendEvt ); } bool wxSheet::SelectCell( const wxSheetCoords& coords, bool addToSelected, bool sendEvt ) { return SelectBlock(wxSheetBlock(coords, 1, 1), addToSelected, sendEvt); } bool wxSheet::SelectBlock( const wxSheetBlock& block, bool addToSelected, bool sendEvt ) { if (!GetSelection()) return false; if ( !addToSelected ) ClearSelection(sendEvt); wxArraySheetBlock addedBlocks; if (!GetSelection()->SelectBlock( block, true, &addedBlocks )) return false; if (!GetBatchCount()) { wxSheetBlock bounds; for (size_t n=0; n rowBottom)) return false; // selection to # of cols means whole row is deselected return DeselectBlock( wxSheetBlock(rowTop, 0, rowBottom-rowTop+1, GetNumberCols()+1), sendEvt ); } bool wxSheet::DeselectCol( int col, bool sendEvt ) { if (HasSelectionMode(wxSHEET_SelectRows)) return false; // deselection to # of rows means whole col is deselected return DeselectBlock( wxSheetBlock(0, col, GetNumberRows(), 1), sendEvt ); } bool wxSheet::DeselectCols( int colLeft, int colRight, bool sendEvt ) { if (HasSelectionMode(wxSHEET_SelectRows) || (colLeft > colRight)) return false; // selection to # of rows means whole col is deselected return DeselectBlock( wxSheetBlock(0, colLeft, GetNumberRows()+1, colRight-colLeft+1), sendEvt ); } bool wxSheet::DeselectCell( const wxSheetCoords& coords, bool sendEvt ) { return DeselectBlock(wxSheetBlock(coords, 1, 1), sendEvt); } bool wxSheet::DeselectBlock( const wxSheetBlock& block, bool sendEvt ) { if (!GetSelection()) return false; // do they want to clear the whole grid wxSheetBlock gridBlock(0, 0, GetNumberRows(), GetNumberCols()); if (gridBlock.Intersect(block) == gridBlock) return ClearSelection(sendEvt); wxArraySheetBlock deletedBlocks; if (!GetSelection()->DeselectBlock( block, true, &deletedBlocks )) return false; if (!GetBatchCount()) { wxSheetBlock bounds; for (size_t n=0; nGetBoundingBlock())); SetSelectingBlock(wxNullSheetBlock); GetSelection()->Clear(); RefreshGridCellBlock(bounds); if (send_event) { // One deselection event, indicating deselection of _all_ cells. SendRangeEvent( wxEVT_SHEET_RANGE_SELECTED, wxSheetBlock(0, 0, GetNumberRows(), GetNumberCols()), false, false ); } return true; } bool wxSheet::ToggleCellSelection( const wxSheetCoords& coords, bool addToSelected, bool sendEvt ) { int sel = IsCellSelected(coords); if (!sel) return SelectCell(coords, addToSelected, sendEvt); return DeselectCell(coords, sendEvt ); } bool wxSheet::ToggleRowSelection( int row, bool addToSelected, bool sendEvt ) { int sel = IsRowSelected(row); if (!sel) return SelectRow(row, addToSelected, sendEvt); return DeselectRow(row, sendEvt ); } bool wxSheet::ToggleColSelection( int col, bool addToSelected, bool sendEvt ) { int sel = IsColSelected(col); if (!sel) return SelectCol(col, addToSelected, sendEvt); return DeselectCol(col, sendEvt ); } // ---------------------------------------------------------------------------- // Copy/Paste #include "wx/dataobj.h" //#define wxDF_wxSHEET (wxDF_MAX+1001) // works w/ GTK 1.2 non unicode const wxChar* wxDF_wxSHEET = wxT("wxDF_wxSHEET"); class wxSheetDataObject : public wxDataObjectSimple { public: wxSheetDataObject() : wxDataObjectSimple(wxDF_wxSHEET) {} wxSheetDataObject(const wxSheetValueProviderSparseString &values) : wxDataObjectSimple(wxDF_wxSHEET), m_values(values) { CreateDataString(); m_values.ClearValues(); } virtual size_t GetDataSize() const { return (m_data.Len()+1)*sizeof(wxChar); } virtual bool GetDataHere(void *buf) const; virtual bool SetData(size_t len, const void *buf); const wxSheetValueProviderSparseString& GetValues() const { return m_values; } void CreateDataString(); protected: wxSheetValueProviderSparseString m_values; wxString m_data; private: // I don't understand these? from include/wx/gtk/dataobj2.h // virtual function hiding supression size_t GetDataSize(const wxDataFormat& format) const { return(wxDataObjectSimple::GetDataSize(format)); } bool GetDataHere(const wxDataFormat& format, void* pBuf) const { return(wxDataObjectSimple::GetDataHere(format, pBuf)); } bool SetData(const wxDataFormat& format, size_t nLen, const void* pBuf) { return(wxDataObjectSimple::SetData(format, nLen, pBuf)); } }; // FIXME! this is just a hack and kinda works const wxString s_nextRow(wxT("\1\1"), 2); // just increment row number const wxString s_nextCol(wxT("\1\2"), 2); // end of value marker const wxString s_newRow(wxT("\1\3"), 2); // specify a row number const wxString s_newCol(wxT("\1\4"), 2); // specify a col number //const wxString s_nextRow(wxT("s")); // just increment row number //const wxString s_nextCol(wxT("d")); // end of value marker //const wxString s_newRow(wxT("r")); // specify a row number //const wxString s_newCol(wxT("c")); // specify a col number // Data string looks like this: `r23c12:size:some data string` // 'r' followed by a number specifies a row # // without a number means next row // 'c' followed by a number specifies a col # // without a number means next col // size is the number of chars of the data string // Data string looks like this: start by specifying the row and col number // then data and end data marker (s_nextCol) more data, if you skip cols // then specify the col number with s_newCol. // [s_newRow:][s_newCol:]hello[s_nextCol]text[s_nextCol][s_newCol:]More[s_nextCol] void wxSheetDataObject::CreateDataString() { m_data.Clear(); wxPairArrayIntPairArraySheetString &values = m_values.GetData(); m_values.RemoveEmpty(); if (values.GetCount() == 0u) return; int c, ncols, r, nrows = values.GetCount(); int row, col; int last_row = values.GetItemKey(0) - 10, last_col; for (r=0; rOpen()) return false; // save data to clipboard, we want the internal data back if possible wxDataObjectComposite *data = new wxDataObjectComposite; data->Add(new wxSheetDataObject(GetSheetRefData()->m_copiedData), true); data->Add(new wxTextDataObject(CopyInternalSelectionToString(colSep)), false); wxTheClipboard->SetData( data ); wxTheClipboard->Close(); return true; } bool wxSheet::CopyCurrentSelectionToClipboard(bool copy_cursor, const wxChar& colSep) { CopyCurrentSelectionInternal(copy_cursor); return CopyInternalSelectionToClipboard(colSep); } bool wxSheet::PasteFromClipboard( const wxSheetCoords &topLeft, const wxChar& colSep ) { if ( !wxTheClipboard->Open() ) return false; bool ret = false; wxSheetDataObject sheetData; if (wxTheClipboard->IsSupported(wxDF_wxSHEET) && wxTheClipboard->GetData(sheetData)) { GetSheetRefData()->m_copiedData = sheetData.GetValues(); ret = PasteInternalCopiedSelection( topLeft ); } else if (wxTheClipboard->IsSupported(wxDF_TEXT)) { wxTextDataObject textData; if (wxTheClipboard->GetData(textData)) { CopyStringToSelection(textData.GetText(), colSep); ret = PasteInternalCopiedSelection( topLeft ); } } wxTheClipboard->Close(); return ret; } bool wxSheet::CopyCurrentSelectionInternal(bool copy_cursor) { wxPairArrayIntPairArraySheetString &copiedData = GetSheetRefData()->m_copiedData.GetData(); copiedData.Clear(); wxSheetSelection sel = *GetSelection(); if (!GetSelectingBlock().IsEmpty()) sel.SelectBlock(GetSelectingBlock()); sel.SetBoundingBlock(wxSheetBlock(0, 0, GetNumberRows(), GetNumberCols())); if (!sel.HasSelection()) { if (copy_cursor && ContainsGridCell(GetGridCursorCell())) sel.SelectBlock(wxSheetBlock(GetGridCursorCell(), 1, 1)); else return false; } wxSheetSelectionIterator selIter(sel); wxSheetCoords cell; while (selIter.GetNext(cell)) copiedData.GetOrCreateValue(cell.m_row).SetValue(cell.m_col, GetCellValue(cell)); return copiedData.GetCount() > 0; } wxString wxSheet::CopyInternalSelectionToString(const wxChar& colSep) { wxPairArrayIntPairArraySheetString &copiedData = GetSheetRefData()->m_copiedData.GetData(); wxString value; GetSheetRefData()->m_copiedData.RemoveEmpty(); if (copiedData.GetCount() == 0) return value; int i, r, c; int row, col; int nrows = copiedData.GetCount(); // find leftmost col int left_col = copiedData.GetItemValue(0).GetItemKey(0); for (r=1; r copiedData.GetItemValue(r).GetItemKey(0)) left_col = copiedData.GetItemValue(r).GetItemKey(0); } int last_row=copiedData.GetItemKey(0), last_col=left_col; for (r=0; rm_copiedData.GetData(); copiedData.Clear(); if (string.IsEmpty()) return false; const wxChar *c = string.GetData(); int n, len = string.Length(); int row = 0, col = 0; wxString buf; for (n=0; nm_copiedData.GetData(); // clean up, shouldn't happen but don't want to have to check it later GetSheetRefData()->m_copiedData.RemoveEmpty(); if (copiedData.GetCount() == 0) return false; wxSheetBlock currentBlock = GetSelection()->GetBoundingBlock().ExpandUnion(GetSelectingBlock()); bool is_selection = !currentBlock.IsEmpty(); wxSheetCoords topLeft(topLeft_); if (topLeft == wxNullSheetCoords) { if (is_selection) topLeft = currentBlock.GetLeftTop(); else topLeft = GetGridCursorCell(); } if (!ContainsGridCell(topLeft)) return false; wxSheetCoords copiedTopLeft( copiedData.GetItemKey(0), copiedData.GetItemValue(0).GetItemKey(0) ); wxSheetCoords shiftCell = topLeft - copiedTopLeft; GetSheetRefData()->m_pasting = true; wxSheetCoords cell, pasteCell; size_t r, nrows = copiedData.GetCount(); size_t c, ncols; for (r=0; r= GetNumberRows()) break; for (c=0; c= GetNumberCols()) break; const wxString& value = copiedData.GetItemValue(r).GetItemValue(c); // only paste into selected cells if selection if (is_selection && IsCellSelected(pasteCell)) SetCellValue(pasteCell, value); else SetCellValue(pasteCell, value); } } GetSheetRefData()->m_pasting = false; return true; } // ---------------------------------------------------------------------------- // Edit control functions (mostly used internally) void wxSheet::EnableEditing( bool edit ) { // TODO: improve this ? if ( edit != IsEditable() ) { if (!edit && IsCellEditControlCreated()) DisableCellEditControl(true); GetSheetRefData()->m_editable = edit; } } bool wxSheet::EnableCellEditControl( const wxSheetCoords& coords_ ) { // move to owner cell since that's where the editor is const wxSheetCoords coords(GetCellOwner(coords_)); wxCHECK_MSG(CanEnableCellControl(coords), false, _T("can't enable editing for this cell!")); // already editing elsewhere, disable it if (IsCellEditControlCreated() && !DisableCellEditControl(true)) return false; if (SendEvent( wxEVT_SHEET_EDITOR_ENABLED, coords ) == EVT_VETOED) return false; // guarantee that it's visible MakeCellVisible(coords); GetSheetRefData()->m_cellEditorCoords = coords; // Get the appropriate editor for this cell wxSheetCellAttr attr(GetAttr(coords)); GetSheetRefData()->m_cellEditor = attr.GetEditor(this, coords); if (!GetEditControl().Ok()) { GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; wxFAIL_MSG(wxT("Unable to get cell edit control")); return false; } return ShowCellEditControl(); } bool wxSheet::DisableCellEditControl( bool save_value ) { //wxCHECK_RET(, wxT("Edit control not enabled in wxSheet::DisableCellEditControl")); if (!IsCellEditControlCreated()) { // just in case something failed earlier, make sure it's gone if (GetEditControl().Ok()) GetSheetRefData()->m_cellEditor.Destroy(); GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; return true; } if (SendEvent(wxEVT_SHEET_EDITOR_DISABLED, GetEditControlCoords()) == EVT_VETOED) return false; if (save_value) SaveEditControlValue(); HideCellEditControl(); // FIXME always destroy it else memory leak, maybe fixed with handler OnDestroy GetSheetRefData()->m_cellEditor.DestroyControl(); GetSheetRefData()->m_cellEditor.Destroy(); GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; return true; } bool wxSheet::CanEnableCellControl(const wxSheetCoords& coords) const { wxCHECK_MSG(ContainsCell(coords), false, wxT("Invalid coords")); return IsEditable() && !GetAttr(coords).GetReadOnly(); } bool wxSheet::IsCellEditControlCreated() const { return GetEditControl().Ok() && GetEditControl().IsCreated(); } bool wxSheet::IsCellEditControlShown() const { return GetEditControl().Ok() && GetEditControl().IsCreated() && GetEditControl().IsShown(); } bool wxSheet::ShowCellEditControl() { wxCHECK_MSG(CanEnableCellControl(GetEditControlCoords()), false, // also checks coords wxT("Editor not enabled in wxSheet::ShowCellEditControl")); wxWindow *win = GetWindowForCoords(GetEditControlCoords()); // If the control's parent is not correct we must recreate it if (GetEditControl().GetControl() && (GetEditControl().GetControl()->GetParent() != win)) GetSheetRefData()->m_cellEditor.DestroyControl(); // Make sure the editor is created if (!GetEditControl().IsCreated()) { GetSheetRefData()->m_cellEditor.CreateEditor(win, -1, new wxSheetCellEditorEvtHandler(this, GetEditControl()), this); wxSheetEditorCreatedEvent evt(GetId(), wxEVT_SHEET_EDITOR_CREATED, this, GetEditControlCoords(), GetSheetRefData()->m_cellEditor.GetControl()); GetEventHandler()->ProcessEvent(evt); if (!GetEditControl().IsCreated()) { // kill it all off, something went wrong if (GetEditControl().GetControl()) GetSheetRefData()->m_cellEditor.DestroyControl(); GetSheetRefData()->m_cellEditor.Destroy(); GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; wxFAIL_MSG(wxT("Unable to create edit control")); return false; } } wxSheetCellAttr attr(GetAttr(GetEditControlCoords())); // the rectangle bounding the cell wxRect rect( CellToRect(GetEditControlCoords(), true) ); // FIXME use GetBestSize // resize editor to overflow into righthand cells if wider than cell wxString value = GetCellValue(GetEditControlCoords()); int clientWidth = win->GetClientSize().GetWidth(); if (!value.IsEmpty() && attr.GetOverflow() && (GetEditControlCoords().m_col < GetNumberCols())) { int w=rect.width, h=0; // expand width if text only if text is wider than cell width GetTextExtent(value, &w, &h, NULL, NULL, &attr.GetFont()); if (w > rect.width) { wxSheetCoords cellSize(GetCellSpan(GetEditControlCoords())); wxSheetCoords c(GetEditControlCoords()); wxSheetCoords oneCell(1,1); int numCols = GetNumberCols(); for (c.m_col = c.m_col + cellSize.m_col; c.m_col < numCols; c.m_col++) { cellSize = GetCellSpan(c); // looks weird going over a spanned cell if ((rect.width < w) && (rect.GetRight() < clientWidth) && (cellSize == oneCell)) rect.width += GetColWidth(c.m_col); else break; } } } // clip width to window size rect.width = wxMin(rect.width, clientWidth - rect.x); GetSheetRefData()->m_cellEditor.SetSize( rect, attr ); GetSheetRefData()->m_cellEditor.Show( true, attr ); // recalc dimensions, maybe expand the scrolled window to account for editor CalcWindowSizes(); GetSheetRefData()->m_cellEditor.BeginEdit(GetEditControlCoords(), this); // FIXME other spreadsheets don't clear cells to right, it looks weird? why not? // if this is empty, cell to right maybe overflowed into from left, clear it //if (value.IsEmpty() && (m_cellEditorCoords.m_col < m_numCols - 1)) // RefreshCell(m_cellEditorCoords+wxSheetCoords(0, 1)); return true; } bool wxSheet::HideCellEditControl() { wxCHECK_MSG(IsCellEditControlShown(), false, wxT("Edit control not shown in wxSheet::HideCellEditControl")); GetSheetRefData()->m_cellEditor.Show( false, GetAttr(GetEditControlCoords()) ); m_gridWin->SetFocus(); RefreshCell(GetEditControlCoords(), false); return true; } void wxSheet::SaveEditControlValue() { wxCHECK_RET(IsCellEditControlCreated(), wxT("Edit control not shown in wxSheet::HideCellEditControl")); wxString oldval = GetCellValue(GetEditControlCoords()); if (GetSheetRefData()->m_cellEditor.EndEdit(GetEditControlCoords(), this)) { // Event has been vetoed, set the data back. if ( SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGED, GetEditControlCoords()) == EVT_VETOED ) SetCellValue(GetEditControlCoords(), oldval); } } // ---------------------------------------------------------------------------- // Drawing functions void wxSheet::EndBatch(bool refresh) { if ( m_batchCount > 0 ) { m_batchCount--; if ( !m_batchCount && refresh ) { m_batchCount++; // temp block refresh for window sizing AdjustScrollbars(); m_batchCount--; Refresh(true); } } } void wxSheet::Refresh(bool eraseb, const wxRect* rect_) { // Don't do anything if between Begin/EndBatch... // EndBatch() will do all this on the last nested one anyway. if (GetBatchCount()) return; if (rect_) { const wxRect rect(*rect_); const int rowLabelWidth = GetRowLabelWidth(); const int colLabelHeight = GetColLabelHeight(); const wxSize extentSize(GetGridExtent()); wxRect cornerRect(0, 0, rowLabelWidth, colLabelHeight); cornerRect.Intersect(rect); wxRect rowLabelRect(0, colLabelHeight, rowLabelWidth, extentSize.y); rowLabelRect.Intersect(rect); rowLabelRect.y -= colLabelHeight; wxRect colLabelRect(rowLabelWidth, 0, extentSize.x, colLabelHeight); colLabelRect.Intersect(rect); colLabelRect.x -= rowLabelWidth; wxRect gridRect(rowLabelWidth, colLabelHeight, extentSize.x, extentSize.y); gridRect.Intersect(rect); gridRect.x -= rowLabelWidth; gridRect.y -= colLabelHeight; if ( !wxRectIsEmpty(cornerRect) ) RefreshCornerLabelWindow(eraseb, &cornerRect); if ( !wxRectIsEmpty(rowLabelRect) ) RefreshRowLabelWindow(eraseb, &rowLabelRect); if ( !wxRectIsEmpty(colLabelRect) ) RefreshColLabelWindow(eraseb, &colLabelRect); if ( !wxRectIsEmpty(gridRect) ) RefreshGridWindow(eraseb, &gridRect); } else { RefreshCornerLabelWindow(eraseb, NULL); RefreshRowLabelWindow(eraseb, NULL); RefreshColLabelWindow(eraseb, NULL); RefreshGridWindow(eraseb, NULL); } } void wxSheet::RefreshGridWindow(bool eraseb, const wxRect* rect) { if (GetBatchCount()) return; size_t n, count = GetSheetRefData()->GetSheetCount(); for (n=0; nGetSheet(n); wxWindow *win = (wxWindow*)s->GetGridWindow(); if (win && win->IsShown()) { if (rect) { wxRect scrolledRect(s->CalcScrolledRect(*rect)); const wxRect refedRect(wxPoint(0,0), win->GetSize()); scrolledRect.Intersect(refedRect); if (!wxRectIsEmpty(scrolledRect)) win->Refresh(eraseb, &scrolledRect); } else win->Refresh(eraseb, NULL); } } } void wxSheet::RefreshRowLabelWindow(bool eraseb, const wxRect* rect) { if (GetBatchCount()) return; size_t n, count = GetSheetRefData()->GetSheetCount(); for (n=0; nGetSheet(n); wxWindow *win = (wxWindow*)s->GetRowLabelWindow(); if (win && win->IsShown()) { if (rect) { wxRect scrolledRect(*rect); s->CalcScrolledPosition(0, scrolledRect.y, NULL, &scrolledRect.y); const wxRect refedRect(wxPoint(0,0), win->GetSize()); scrolledRect.Intersect(refedRect); if (!wxRectIsEmpty(scrolledRect)) win->Refresh(eraseb, &scrolledRect); } else win->Refresh(eraseb, NULL); } } } void wxSheet::RefreshColLabelWindow(bool eraseb, const wxRect* rect) { if (GetBatchCount()) return; size_t n, count = GetSheetRefData()->GetSheetCount(); for (n=0; nGetSheet(n); wxWindow *win = (wxWindow*)s->GetColLabelWindow(); if (win && win->IsShown()) { if (rect) { wxRect scrolledRect(*rect); s->CalcScrolledPosition(scrolledRect.x, 0, &scrolledRect.x, NULL); const wxRect refedRect(wxPoint(0,0), win->GetSize()); scrolledRect.Intersect(refedRect); if (!wxRectIsEmpty(scrolledRect)) win->Refresh(eraseb, &scrolledRect); } else win->Refresh(eraseb, NULL); } } } void wxSheet::RefreshCornerLabelWindow(bool eraseb, const wxRect* rect) { if (GetBatchCount()) return; size_t n, count = GetSheetRefData()->GetSheetCount(); for (n=0; nGetSheet(n); wxWindow *win = (wxWindow*)s->GetCornerLabelWindow(); if (win && win->IsShown()) win->Refresh(eraseb, rect); } } void wxSheet::RefreshCell(const wxSheetCoords& coords, bool single_cell) { if ( GetBatchCount() ) return; //wxPrintf(wxT("RefreshCell %d %d\n"), coords.m_row, coords.m_col); if (IsCornerLabelCell(coords)) { RefreshCornerLabelWindow(true); return; } wxRect rect(CellToRect(coords, false)); if (ContainsRowLabelCell(coords)) { RefreshRowLabelWindow( true, &rect ); return; } else if (ContainsColLabelCell(coords)) { RefreshColLabelWindow( true, &rect ); return; } else if (ContainsGridCell(coords)) { if (!single_cell) { // hack to draw previous cell, if this cell turns empty and can be // overflowed into we need to erase the previous cell's |> cutoff marker if (coords.m_col > 0) rect.x = GetColLeft(coords.m_col-1); // we do have to draw the whole row right though rect.width = GetVirtualSize().x - rect.x; } RefreshGridWindow( false, &rect ); } else wxFAIL_MSG(wxT("Invalid coords in wxSheet::RefreshCell")); } void wxSheet::RefreshBlock(const wxSheetBlock& block) { if ( GetBatchCount() || block.IsEmpty() ) return; //PRINT_BLOCK(wxT("RefreshBlock "), block) // This function also refreshes beyond the labels and grid since if a // cell is resized smaller that may have to be repainted wxSheetBlock b; const wxSheetCoords coords(block.GetLeftTop()); const wxSize winSize(GetGridExtent()); const int numRows = GetNumberRows(); const int numCols = GetNumberCols(); // Corner Labels if (IsCornerLabelCell(coords)) { RefreshCornerLabelWindow(true); } // Row Labels b = block.Intersect(wxSheetBlock(0, -1, numRows, 1)); if (!b.IsEmpty()) { wxRect rect(BlockToLogicalRect(b)); if (b.GetBottom() == numRows - 1) rect.height = winSize.y - rect.y; RefreshRowLabelWindow( true, &rect ); } // Col Labels b = block.Intersect(wxSheetBlock(-1, 0, 1, numCols)); if (!b.IsEmpty()) { wxRect rect(BlockToLogicalRect(b)); if (b.GetRight() == numCols - 1) rect.width = winSize.x - rect.x; RefreshColLabelWindow( true, &rect ); } // Grid cells b = block.Intersect(wxSheetBlock(0, 0, numRows, numCols)); if (!b.IsEmpty()) { wxRect rect(BlockToLogicalRect(b)); if (b.GetBottom() == numRows - 1) rect.height = winSize.y - rect.y; if (b.GetRight() == numCols - 1) rect.width = winSize.x - rect.x; RefreshGridWindow( false, &rect ); } } void wxSheet::RefreshRow( int row ) { RefreshBlock(wxSheetBlock(row, 0, 1, GetNumberCols())); } void wxSheet::RefreshCol( int col ) { RefreshBlock(wxSheetBlock(0, col, GetNumberRows(), 1)); } void wxSheet::RefreshGridCellBlock( const wxSheetBlock& block ) { RefreshBlock(block); } void wxSheet::RefreshAttrChange(const wxSheetCoords& coords, wxSheetAttr_Type type) { switch (GetCellCoordsType(coords)) { case wxSHEET_CELL_GRID : { switch (type) { case wxSHEET_AttrDefault : { m_gridWin->SetBackgroundColour(DoGetDefaultGridAttr().GetBackgroundColour()); RefreshGridWindow(false); break; } case wxSHEET_AttrCol : { if (ContainsGridCol(coords.m_col)) RefreshCol(coords.m_col); break; } case wxSHEET_AttrRow : { if (ContainsGridRow(coords.m_row)) RefreshRow(coords.m_row); break; } case wxSHEET_AttrCell : default : { if (ContainsGridCell(coords)) RefreshCell(coords, false); break; } } break; } case wxSHEET_CELL_CORNERLABEL : { m_cornerLabelWin->SetBackgroundColour(DoGetDefaultCornerLabelAttr().GetBackgroundColour()); RefreshCornerLabelWindow(true); break; } case wxSHEET_CELL_ROWLABEL : { switch (type) { case wxSHEET_AttrDefault : { m_rowLabelWin->SetBackgroundColour(DoGetDefaultRowLabelAttr().GetBackgroundColour()); RefreshRowLabelWindow(true); break; } case wxSHEET_AttrCell : default : { if (ContainsRowLabelCell(coords)) RefreshCell(coords); break; } } break; } case wxSHEET_CELL_COLLABEL : { switch (type) { case wxSHEET_AttrDefault : { m_colLabelWin->SetBackgroundColour(DoGetDefaultColLabelAttr().GetBackgroundColour()); RefreshColLabelWindow(true); break; } case wxSHEET_AttrCell : default : { if (ContainsColLabelCell(coords)) RefreshCell(coords); break; } } break; } default : break; } } void wxSheet::OnPaint( wxPaintEvent& event ) { wxWindow *win = (wxWindow*)event.GetEventObject(); wxPaintDC dc(win); wxRegion reg(win->GetUpdateRegion()); if (!IsShown()) return; if (win == this) { PaintSheetWindow( dc, reg ); } else if (win == m_cornerLabelWin) { if (m_cornerLabelWin->IsShown()) { PaintCornerLabelWindow( dc, reg ); } } else if (win == m_rowLabelWin) { if (m_rowLabelWin->IsShown()) { PrepareRowLabelDC( dc ); PaintRowLabelWindow( dc, reg ); } } else if (win == m_colLabelWin) { if (m_colLabelWin->IsShown()) { PrepareColLabelDC( dc ); PaintColLabelWindow( dc, reg ); } } else if (win == m_gridWin) { if (m_gridWin->IsShown()) { PrepareGridDC( dc ); PaintGridWindow( dc, reg ); } } } void wxSheet::OnEraseBackground( wxEraseEvent& event ) { wxWindow *win = (wxWindow*)event.GetEventObject(); if (win == this) event.Skip(false); else if ((win == m_cornerLabelWin) || (win == m_rowLabelWin) || (win == m_colLabelWin)) event.Skip(false); else if (win == m_gridWin) event.Skip(false); } void wxSheet::DrawSplitterButton(wxDC &dc, const wxRect& rect) { //dc.SetPen(*wxBLACK_PEN); //dc.SetBrush(*wxBLACK_BRUSH); //dc.DrawRectangle(rect); wxPen highlight(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNHIGHLIGHT), 1, wxSOLID); wxPen shadow(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW), 1, wxSOLID); wxPen darkShadow(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW), 1, wxSOLID); dc.SetPen(shadow); dc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID)); dc.DrawRectangle(rect); dc.DrawLine(rect.GetRight()-1, rect.y+2, rect.GetRight()-1, rect.GetBottom()-1); dc.DrawLine(rect.x+2, rect.GetBottom()-1, rect.GetRight(), rect.GetBottom()-1); dc.SetPen(darkShadow); dc.DrawLine(rect.GetRight(), rect.y+1, rect.GetRight(), rect.GetBottom()); dc.DrawLine(rect.x+1, rect.GetBottom(), rect.GetRight(), rect.GetBottom()); dc.SetPen(highlight); dc.DrawLine(rect.x+1, rect.y+1, rect.GetRight()-1, rect.y+1); dc.DrawLine(rect.x+1, rect.y+1, rect.x+1, rect.GetBottom()-1); } void wxSheet::PaintSheetWindow( wxDC& dc, const wxRegion& WXUNUSED(reg) ) { // draw the bottom right square area between the scrollbars // since we trap EVT_ERASE_BACKGROUND if (m_vertScrollBar->IsShown() && m_horizScrollBar->IsShown()) { dc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID)); dc.SetPen(*wxTRANSPARENT_PEN); wxSize clientSize = GetClientSize(); int top = m_vertScrollBar->GetRect().GetBottom(); int left = m_horizScrollBar->GetRect().GetRight() + m_horizSplitRect.GetWidth(); dc.DrawRectangle(left, top, clientSize.x-left, clientSize.y-top); } if (!wxRectIsEmpty(m_vertSplitRect)) DrawSplitterButton(dc, m_vertSplitRect); if (!wxRectIsEmpty(m_horizSplitRect)) DrawSplitterButton(dc, m_horizSplitRect); } void wxSheet::PaintGridWindow( wxDC& dc, const wxRegion& reg ) { wxSheetSelection dirtyBlocks; CalcCellsExposed( reg, dirtyBlocks ); DrawGridCells( dc, dirtyBlocks ); #if WXSHEET_DRAW_LINES DrawAllGridLines( dc, reg ); #endif DrawGridSpace( dc ); DrawCursorHighlight( dc, dirtyBlocks ); } void wxSheet::PaintRowLabelWindow( wxDC& dc, const wxRegion& reg ) { const int numRows = GetNumberRows(); if (0 && numRows) { wxRect r(0, GetRowBottom(numRows-1), GetRowLabelWidth(), GetGridVirtualSize(true).y); r = CalcScrolledRect(r); r.Intersect(reg.GetBox()); dc.DrawRectangle(r); } wxArrayInt rows; if (CalcRowLabelsExposed(reg, rows)) DrawRowLabels( dc, rows ); } void wxSheet::PaintColLabelWindow( wxDC& dc, const wxRegion& reg ) { const int numCols = GetNumberCols(); if (0 && numCols) { wxRect r(GetColRight(numCols-1), 0, GetGridVirtualSize(true).x, GetColLabelHeight()); r = CalcScrolledRect(r); r.Intersect(reg.GetBox()); dc.DrawRectangle(r); } wxArrayInt cols; if (CalcColLabelsExposed(reg, cols)) DrawColLabels( dc, cols ); } void wxSheet::PaintCornerLabelWindow( wxDC& dc, const wxRegion& WXUNUSED(reg) ) { DrawCornerLabel( dc ); } int wxSheet::FindOverflowCell( const wxSheetCoords& coords, wxDC& dc ) { wxSheetCoords c(coords); while (c.m_col > 0) { c.m_col = GetTable()->GetFirstNonEmptyColToLeft(c); if (c.m_col < 0) return -1; // if !empty, stop, this is the only cell that could overflow // Must check since default implementation of // GetFirstNonEmptyColToLeft just returns the previous col if (HasCellValue(c)) { wxSheetCellAttr attr(GetAttr(c)); if (attr.GetOverflow()) { // check if this cell actually does overflow into coords int width = attr.GetRenderer(this, c).GetBestSize(*this, attr, dc, c).GetWidth(); if (GetColLeft(c.m_col)+width > GetColLeft(coords.m_col)) return c.m_col; } break; } } return -1; } // Note - this function only draws cells that are in the list of // exposed cells (usually set from the update region by CalcExposedCells) void wxSheet::DrawGridCells( wxDC& dc, const wxSheetSelection& blockSel ) { if ( !GetNumberRows() || !GetNumberCols() || GetBatchCount() ) return; //static long counter = 0; ++counter; // for testing only wxSheetSelection removedSel; // removed spanned wxSheetCoords coords; wxSheetCoords lastCoords(-1,-1); wxSheetBlock cellBlock; wxPairArrayIntInt leftCols; // paint cells in reverse order bottom to top, right to left for overflow wxSheetSelectionIterator revIter(blockSel, wxSSI_REVERSE); while (revIter.GetNext(coords) != wxSHEET_SELECTIONITER_GET_END) { // already painted this cell if (removedSel.Contains(coords)) { lastCoords = coords; continue; } // trim out cells part of spanned cells, leaving only the owner cell cellBlock = GetCellBlock(coords); if (!cellBlock.IsOneCell()) { // forget part of spanned cell, we only care about owner cell coords = cellBlock.GetLeftTop(); // don't bother checking whole block again removedSel.SelectBlock(cellBlock, false); } // if empty find cell to left that might overflow into this one // only need to check left side of each block, when row increments if ((lastCoords.m_row > coords.m_row) && !HasCellValue(lastCoords)) { int overflow_col = FindOverflowCell(lastCoords, dc); if ((overflow_col >= 0) && !blockSel.Contains(lastCoords.m_row, overflow_col)) leftCols.SetValue(lastCoords.m_row, overflow_col); } //wxPrintf(wxT("%ld Drawing Cell %d %d - has %d %d\n"), counter, coords.m_row, coords.m_col, HasCellValue(coords), HasCellValue(lastCoords)); fflush(stdout); DrawCell( dc, coords ); lastCoords = coords; } // check the top left cell of the last block too if (ContainsGridCell(lastCoords) && !HasCellValue(lastCoords)) { int overflow_col = FindOverflowCell(lastCoords, dc); if ((overflow_col >= 0) && !blockSel.Contains(lastCoords.m_row, overflow_col)) leftCols.SetValue(lastCoords.m_row, overflow_col); } // now redraw the cells that could have overflowed into these int n, count = leftCols.GetCount(); for (n = 0; n < count; n++) { coords.Set(leftCols.GetItemKey(n), leftCols.GetItemValue(n)); DrawCell( dc, coords ); //wxPrintf(wxT("%ld Overflow Drawing Cell %d %d\n"), counter, coords.m_row, coords.m_col); fflush(stdout); } } /* // Note - this function only draws cells that are in the list of // exposed cells (usually set from the update region by CalcExposedCells) void wxSheet::DrawGridCells( wxDC& dc, const wxSheetSelection& blockSel_ ) { if ( !GetNumberRows() || !GetNumberCols() || GetBatchCount() ) return; wxSheetSelection blockSel(blockSel_); // modified to remove spanned cells wxSheetSelection removedSel; // removed spanned wxSheetSelectionIterator selIter(blockSel); // forward iterator wxSheetCoords coords; wxSheetBlock cellBlock; int check_overflow_row = -1; while (selIter.GetNext(coords)) { if (removedSel.Contains(coords)) continue; // trim out cells part of spanned cells, leaving only the owner cell cellBlock = GetCellBlock(coords); if (!cellBlock.IsOneCell()) { // forget part of spanned cell, we only care about owner cell coords = cellBlock.GetLeftTop(); // remove whole spanned cell and add back the owner blockSel.DeselectBlock(cellBlock, false); blockSel.SelectBlock(wxSheetBlock(coords, 1, 1), false); // don't bother checking whole block again removedSel.SelectBlock(cellBlock, false); } int bottom = cellBlock.GetBottom(); // if empty find cell to left that might overflow into this one // only need to check left side of each block, hence check_overflow_row if ((bottom > check_overflow_row) && !HasValue()) //GetTable() && !GetTable()->HasValue(coords)) { check_overflow_row = bottom; wxSheetCoords c; for ( c.m_row = coords.m_row; c.m_row <= bottom; c.m_row++ ) { c.m_col = coords.m_col; while (c.m_col > 0) { c.m_col = GetTable()->GetFirstNonEmptyColToLeft(c); if (c.m_col < 0) break; // if !empty, stop, this is the only cell that could overflow // Must check since default implementation of // GetFirstNonEmptyColToLeft just returns the previous col if (GetTable()->HasValue(c)) { wxSheetCellAttr attr(GetAttr(c)); if (attr.GetOverflow()) { // check if this cell actually does overflow into coords int width = attr.GetRenderer(this, c).GetBestSize(*this, attr, dc, c).GetWidth(); if (GetColLeft(c.m_col)+width > GetColLeft(coords.m_col)) blockSel.SelectBlock(wxSheetBlock(c, 1, 1), false); } break; } } } } } //static long counter = 0; ++counter; // paint cells in reverse order bottom to top, right to left for overflow wxSheetSelectionIterator revIter(blockSel, wxSSI_REVERSE); while (revIter.GetNext(coords)) { //wxPrintf(wxT("%ld Drawing Cell %d %d\n"), counter, coords.m_row, coords.m_col); DrawCell( dc, coords ); } } */ void wxSheet::DrawGridSpace( wxDC& dc ) { int cw, ch; m_gridWin->GetClientSize( &cw, &ch ); int right, bottom; CalcUnscrolledPosition( cw, ch, &right, &bottom ); const int numRows = GetNumberRows(); const int numCols = GetNumberCols(); const int bottomRow = numRows > 0 ? GetRowBottom(numRows - 1) + 1: 0; const int rightCol = numCols > 0 ? GetColRight(numCols - 1) + 1: 0; if ( (right > rightCol) || (bottom > bottomRow) ) { int left, top; CalcUnscrolledPosition( 0, 0, &left, &top ); dc.SetBrush( wxBrush(GetAttrBackgroundColour(wxSheetCoords(0,0), wxSHEET_AttrDefault), wxSOLID) ); dc.SetPen( *wxTRANSPARENT_PEN ); if ( right > rightCol ) dc.DrawRectangle( rightCol, top, right - rightCol, ch ); if ( bottom > bottomRow ) dc.DrawRectangle( left, bottomRow, cw, bottom - bottomRow ); } } void wxSheet::DrawCell( wxDC& dc, const wxSheetCoords& coords ) { wxRect rect(CellToRect(coords)); if (wxRectIsEmpty(rect)) // !IsShown return; // we draw the cell border ourselves #if !WXSHEET_DRAW_LINES if ( GridLinesEnabled() != 0 ) DrawCellBorder( dc, coords ); #endif wxSheetCellAttr attr(GetAttr(coords)); // if the editor is shown, we should use it and not the renderer if ( (coords == GetEditControlCoords()) && IsCellEditControlShown() ) GetSheetRefData()->m_cellEditor.PaintBackground(*this, attr, dc, rect, coords, IsCellSelected(coords)); else attr.GetRenderer(this, coords).Draw(*this, attr, dc, rect, coords, IsCellSelected(coords)); } void wxSheet::DrawCursorHighlight(wxDC& dc, const wxSheetSelection& blockSel) { // Make sure that the cursor is valid (just in case) if ( !ContainsGridCell(GetGridCursorCell()) && GetNumberRows() && GetNumberCols() ) GetSheetRefData()->m_cursorCoords.Set(0, 0); // don't show highlight when the edit control is shown if (!blockSel.Contains(GetGridCursorCell()) || IsCellEditControlShown()) return; DrawCursorCellHighlight(dc, GetAttr(GetGridCursorCell())); } void wxSheet::DrawCursorCellHighlight( wxDC& dc, const wxSheetCellAttr& attr ) { if (!ContainsGridCell(GetGridCursorCell())) return; wxSheetCoords coords(GetCellOwner(GetGridCursorCell())); wxRect rect( CellToRect(coords) ); if (wxRectIsEmpty(rect)) // !IsCellShown return; // hmmm... what could we do here to show that the cell is disabled? // for now, I just draw a thinner border than for the other ones, but // it doesn't look really good int penWidth = attr.GetReadOnly() ? GetCursorCellHighlightROPenWidth() : GetCursorCellHighlightPenWidth(); if (penWidth > 0) { // The center of the drawn line is where the position/width/height of // the rectangle is actually at, (on wxMSW atr least,) so we will // reduce the size of the rectangle to compensate for the thickness of // the line. If this is too strange on non wxMSW platforms then // please #ifdef this appropriately. rect.x += penWidth/2; rect.y += penWidth/2; rect.width -= penWidth-1; rect.height -= penWidth-1; // Now draw the rectangle // use the cellHighlightColour if the cell is inside a selection, this // will ensure the cell is always visible. dc.SetPen(wxPen(IsCellSelected(coords) ? GetSelectionForeground() : GetCursorCellHighlightColour(), penWidth, wxSOLID)); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRectangle(rect); } #if 0 // VZ: my experiments with 3d borders... // how to properly set colours for arbitrary bg? wxCoord x1 = rect.x, y1 = rect.y, x2 = rect.x + rect.width -1, y2 = rect.y + rect.height -1; dc.SetPen(*wxWHITE_PEN); dc.DrawLine(x1, y1, x2, y1); dc.DrawLine(x1, y1, x1, y2); dc.DrawLine(x1 + 1, y2 - 1, x2 - 1, y2 - 1); dc.DrawLine(x2 - 1, y1 + 1, x2 - 1, y2 ); dc.SetPen(*wxBLACK_PEN); dc.DrawLine(x1, y2, x2, y2); dc.DrawLine(x2, y1, x2, y2+1); #endif // 0 } void wxSheet::DrawCellBorder( wxDC& dc, const wxSheetCoords& coords ) { wxRect rect(CellToRect( coords )); if ( wxRectIsEmpty(rect) ) // !IsCellShown return; dc.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID) ); if ((GridLinesEnabled() & wxVERTICAL) != 0) { // right hand border dc.DrawLine( rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + rect.height + 1 ); } if ((GridLinesEnabled() & wxHORIZONTAL) != 0) { // bottom border dc.DrawLine( rect.x, rect.y + rect.height, rect.x + rect.width, rect.y + rect.height); } } // TODO: remove this ??? // This is used to redraw all grid lines e.g. when the grid line colour // has been changed void wxSheet::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) ) { #if !WXSHEET_DRAW_LINES return; #endif const int numRows = GetNumberRows(); const int numCols = GetNumberCols(); if ( GetBatchCount() || (GridLinesEnabled() == 0) || !numRows || !numCols ) return; int top, bottom, left, right; #if 0 //#ifndef __WXGTK__ if (reg.IsEmpty()) { int cw, ch; m_gridWin->GetClientSize(&cw, &ch); // virtual coords of visible area CalcUnscrolledPosition( 0, 0, &left, &top ); CalcUnscrolledPosition( cw, ch, &right, &bottom ); } else { wxCoord x, y, w, h; reg.GetBox(x, y, w, h); CalcUnscrolledPosition( x, y, &left, &top ); CalcUnscrolledPosition( x + w, y + h, &right, &bottom ); } #else int cw, ch; m_gridWin->GetClientSize(&cw, &ch); CalcUnscrolledPosition( 0, 0, &left, &top ); CalcUnscrolledPosition( cw, ch, &right, &bottom ); #endif // avoid drawing grid lines past the last row and col right = wxMin( right, GetColRight(numCols - 1) ); bottom = wxMin( bottom, GetRowBottom(numRows - 1) ); // no gridlines inside spanned cells, clip them out int leftCol = XToGridCol(left, true); int topRow = YToGridRow(top, true); int rightCol = XToGridCol(right, true); int bottomRow = YToGridRow(bottom, true); int i; if (HasSpannedCells()) { const wxSheetBlock block(topRow, leftCol, bottomRow-topRow+1, rightCol-leftCol+1); wxRegion clippedcells(0, 0, cw, ch); bool done = false; if (GetSpannedBlocks()) { const wxSheetSelection* spannedBlocks = GetSpannedBlocks(); const int count = spannedBlocks->GetCount(); for (i=spannedBlocks->FindTopRow(topRow); iGetBlock(i); if (block.Intersects(b)) { clippedcells.Subtract(BlockToRect(b, true)); done = true; } else if (bottomRow < b.GetTop()) break; } } else // grind through it { wxSheetCoords c; for (c.m_row = topRow; c.m_row <= bottomRow; c.m_row++) { for (c.m_col = leftCol; c.m_col <= rightCol; c.m_col++) { const wxSheetBlock b(GetCellBlock(c)); if (!b.IsOneCell()) { done = true; clippedcells.Subtract(BlockToRect(b, true)); } } } } if (done) dc.SetClippingRegion( clippedcells ); } dc.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID) ); if ((GridLinesEnabled() & wxHORIZONTAL) != 0) { for ( i = topRow; i < numRows; i++ ) { int rowBottom = GetRowBottom(i); if ( rowBottom > bottom ) break; if ( rowBottom >= top ) dc.DrawLine( left, rowBottom, right, rowBottom ); } } if ((GridLinesEnabled() & wxVERTICAL) != 0) { for ( i = leftCol; i < numCols; i++ ) { int colRight = GetColRight(i); if ( colRight > right ) break; if ( colRight >= left ) dc.DrawLine( colRight, top, colRight, bottom ); } } dc.DestroyClippingRegion(); } void wxSheet::DrawRowLabels( wxDC& dc, const wxArrayInt& rows ) { size_t i, numLabels = rows.GetCount(); if ( !GetNumberRows() || !numLabels ) return; for ( i = 0; i < numLabels; i++ ) DrawCell( dc, wxSheetCoords(rows[i], -1) ); /* // sample native rendernative code - FIXME rect.SetX( 1 ); rect.SetY( GetRowTop(row) + 1 ); rect.SetWidth( m_rowLabelWidth - 2 ); rect.SetHeight( GetRowHeight(row) - 2 ); CalcScrolledPosition( 0, rect.y, NULL, &rect.y ); wxWindowDC *win_dc = (wxWindowDC*) &dc; wxRendererNative::Get().DrawHeaderButton( win_dc->m_owner, dc, rect, 0 ); */ // Now draw the dividing lines dc.SetPen( wxPen(GetLabelOutlineColour(), 1, wxSOLID) ); int top; CalcUnscrolledPosition(0, 0, NULL, &top); //int top = GetRowTop(rows[0]); int bottom = top + m_gridWin->GetSize().y; //GetRowBottom(rows[numLabels-1]); int width = GetRowLabelWidth(); // left of row labels dc.DrawLine(0, top, 0, bottom); // right of row labels dc.DrawLine(width-1, top, width-1, bottom); // draw bottoms wxSheetCoords coords(0, -1); for ( i = 0; i < numLabels; i++ ) { coords.m_row = rows[i]; bottom = GetRowBottom(GetCellBlock(coords).GetBottom()); dc.DrawLine(0, bottom, width-1, bottom); } } void wxSheet::DrawColLabels( wxDC& dc, const wxArrayInt& cols ) { size_t i, numLabels = cols.GetCount(); if ( !GetNumberCols() || !numLabels ) return; for ( i = 0; i < numLabels; i++ ) DrawCell( dc, wxSheetCoords(-1, cols[i]) ); /* // sample native rendernative code - FIXME rect.SetX( colLeft + 1 ); rect.SetY( 1 ); rect.SetWidth( GetColWidth(col) - 2 ); rect.SetHeight( m_colLabelHeight - 2 ); wxWindowDC *win_dc = (wxWindowDC*) &dc; wxRendererNative::Get().DrawHeaderButton( win_dc->m_owner, dc, rect, 0 ); */ // Now draw the dividing lines dc.SetPen( wxPen(GetLabelOutlineColour(), 1, wxSOLID) ); int left; CalcUnscrolledPosition(0, 0, &left, NULL); //int left = GetColLeft(cols[0]); int right = left + m_gridWin->GetSize().x; //GetColRight(cols[numLabels-1]); int height = GetColLabelHeight(); // top of col labels dc.DrawLine(left, 0, right, 0); // bottom of col labels dc.DrawLine(left, height-1, right, height-1); // draw rights wxSheetCoords coords(-1, 0); for ( i = 0; i < numLabels; i++ ) { coords.m_col = cols[i]; right = GetColRight(GetCellBlock(coords).GetRight()); dc.DrawLine(right, 0, right, height-1); } } void wxSheet::DrawCornerLabel( wxDC& dc ) { DrawCell( dc, wxSheetCoords(-1, -1) ); wxSize size(m_cornerLabelWin->GetClientSize()); #ifdef USE_RENDERNATIVE wxRect rect(1, 1, size.x-2, size.y-2); //rect.SetX( 1 ); //rect.SetY( 1 ); //rect.SetWidth( client_width - 2 ); //rect.SetHeight( client_height - 2 ); wxRendererNative::Get().DrawHeaderButton( this, dc, rect, 0 ); #else // Now draw the dividing lines dc.SetPen( wxPen(GetLabelOutlineColour(), 1, wxSOLID) ); dc.DrawLine(0, 0, size.x, 0); // top dc.DrawLine(0, size.y-1, size.x, size.y-1); // bottom dc.DrawLine(0, 0, 0, size.y-1); // left dc.DrawLine(size.x-1, 0, size.x-1, size.y-1); // right #endif } void wxSheet::DrawRowColResizingMarker( int newDragPos ) { if ( !HasMouseCursorMode(WXSHEET_CURSOR_RESIZING) || ((m_dragLastPos == -1) && (newDragPos == -1)) ) return; wxClientDC dc( m_gridWin ); PrepareGridDC( dc ); int left = 0, top = 0; CalcUnscrolledPosition( 0, 0, &left, &top ); int right = GetColRight(GetNumberCols()-1); int bottom = GetRowBottom(GetNumberRows()-1); int cw = 0, ch = 0; m_gridWin->GetClientSize( &cw, &ch ); right = wxMin(left+cw, right); bottom = wxMin(top+ch, bottom); const bool resizingRow = HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW); if (GridLinesEnabled()) { dc.SetPen(wxPen(GetGridLineColour(), 3, wxSOLID)); // Draw the anchor marker so you know what row/col you're resizing if (resizingRow) { int anchor = GetRowTop(m_dragRowOrCol); dc.DrawLine( left, anchor, right, anchor ); } else // resizing col { int anchor = GetColLeft(m_dragRowOrCol); dc.DrawLine( anchor, top, anchor, bottom ); } } int log_fn = dc.GetLogicalFunction(); dc.SetLogicalFunction(wxINVERT); if (m_dragLastPos >= 0) { if (resizingRow) dc.DrawLine( left, m_dragLastPos, right, m_dragLastPos ); else // resizing col dc.DrawLine( m_dragLastPos, top, m_dragLastPos, bottom ); } if (newDragPos >= 0) { m_dragLastPos = newDragPos; if (resizingRow) dc.DrawLine( left, m_dragLastPos, right, m_dragLastPos ); else // resizing col dc.DrawLine( m_dragLastPos, top, m_dragLastPos, bottom ); } dc.SetLogicalFunction(log_fn); // set it back since nobody else wants invert } bool wxSheet::CalcRowLabelsExposed( const wxRegion& reg, wxArrayInt& rowLabels ) const { const int numRows = GetNumberRows(); if (!numRows) return false; const bool spanned = HasSpannedCells(); wxRegionIterator iter( reg ); while ( iter ) { wxRect r(iter.GetRect()); // TODO: remove this when we can... // There is a bug in wxMotif that gives garbage update // rectangles if you jump-scroll a long way by clicking the // scrollbar with middle button. This is a work-around // #if defined(__WXMOTIF__) int cw, ch; m_gridWin->GetClientSize( &cw, &ch ); if ( r.GetTop() > ch ) r.SetTop( 0 ); r.SetBottom( wxMin( r.GetBottom(), ch ) ); #endif // logical bounds of update region int top; CalcUnscrolledPosition( 0, r.GetTop(), NULL, &top ); int bottom = top + r.GetHeight(); //CalcUnscrolledPosition( 0, r.GetBottom(), &dummy, &bottom ); // find the row labels within these bounds for ( int row = YToGridRow(top, true); row < numRows; row++ ) { if ( GetRowBottom(row) < top ) continue; if ( GetRowTop(row) > bottom ) break; if (spanned) { const wxSheetBlock block(GetCellBlock(wxSheetCoords(row, -1))); if (block.GetHeight() >= 1) { rowLabels.Add( block.GetTop() ); row = block.GetBottom(); } else if (block.GetHeight() < 1) row = block.GetBottom(); } else rowLabels.Add( row ); } iter++ ; } return rowLabels.GetCount() > 0u; } bool wxSheet::CalcColLabelsExposed( const wxRegion& reg, wxArrayInt& colLabels ) const { const int numCols = GetNumberCols(); if (!numCols) return false; const bool spanned = HasSpannedCells(); wxRegionIterator iter( reg ); while ( iter ) { wxRect r(iter.GetRect()); // TODO: remove this when we can... // There is a bug in wxMotif that gives garbage update // rectangles if you jump-scroll a long way by clicking the // scrollbar with middle button. This is a work-around // #if defined(__WXMOTIF__) int cw, ch; m_gridWin->GetClientSize( &cw, &ch ); if ( r.GetLeft() > cw ) r.SetLeft( 0 ); r.SetRight( wxMin( r.GetRight(), cw ) ); #endif // logical bounds of update region int left; CalcUnscrolledPosition( r.GetLeft(), 0, &left, NULL ); int right = left + r.GetWidth(); //CalcUnscrolledPosition( r.GetRight(), 0, &right, &dummy ); // find the cells within these bounds for ( int col = XToGridCol(left, true); col < numCols; col++ ) { if ( GetColRight(col) < left ) continue; if ( GetColLeft(col) > right ) break; if (spanned) { const wxSheetBlock block(GetCellBlock(wxSheetCoords(-1, col))); if (block.GetWidth() >= 1) { colLabels.Add( block.GetLeft() ); col = block.GetRight(); } else if (block.GetWidth() < 1) col = block.GetRight(); } else colLabels.Add( col ); } iter++ ; } return colLabels.GetCount() > 0u; } bool wxSheet::CalcCellsExposed( const wxRegion& reg, wxSheetSelection& blockSel ) const { const int numRows = GetNumberRows(); const int numCols = GetNumberCols(); if (!numRows || !numCols) return false; wxRegionIterator iter( reg ); while ( iter ) { wxRect r(iter.GetRect()); // TODO: remove this when we can... // There is a bug in wxMotif that gives garbage update // rectangles if you jump-scroll a long way by clicking the // scrollbar with middle button. This is a work-around // #if defined(__WXMOTIF__) int cw, ch; m_gridWin->GetClientSize( &cw, &ch ); if ( r.GetTop() > ch ) r.SetTop( 0 ); if ( r.GetLeft() > cw ) r.SetLeft( 0 ); r.SetRight( wxMin( r.GetRight(), cw ) ); r.SetBottom( wxMin( r.GetBottom(), ch ) ); #endif // logical bounds of update region int left, top, right, bottom; CalcUnscrolledPosition( r.GetLeft(), r.GetTop(), &left, &top ); CalcUnscrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom ); // find the cells within these bounds wxSheetBlock block(YToGridRow(top, true), XToGridCol(left, true), 0, 0); int row, col; for ( row = block.GetTop(); row < numRows; row++ ) { if ( GetRowBottom(row) <= top ) continue; else if ( GetRowTop(row) > bottom ) break; } for ( col = block.GetLeft(); col < numCols; col++ ) { if ( GetColRight(col) <= left ) continue; else if ( GetColLeft(col) > right ) break; } block.SetRight(col - 1); block.SetBottom(row - 1); blockSel.SelectBlock(block, false); iter++; } return blockSel.GetCount() > 0; } void wxSheet::DrawTextRectangle( wxDC& dc, const wxString& value, const wxRect& rect, int align, int textOrientation ) { wxArrayString lines; if (StringToLines( value, lines ) > 0) DrawTextRectangle( dc, lines, rect, align, textOrientation ); } void wxSheet::DrawTextRectangle( wxDC& dc, const wxArrayString& lines, const wxRect& rect, int align, int textOrientation ) { int nLines = lines.GetCount(); if ( (nLines == 0) || ((nLines == 1) && lines[0].IsEmpty()) ) return; dc.SetClippingRegion( rect ); int l; float x = 0.0, y = 0.0; long textWidth=0, textHeight=0; long lineWidth=0, lineHeight=0; wxArrayInt lineWidths, lineHeights; // Measure the text extent once, Gtk2 is slow (takes 2sec off 23sec run) for ( l = 0; l < nLines; l++ ) { dc.GetTextExtent(lines[l], &lineWidth, &lineHeight); lineWidths.Add(lineWidth); lineHeights.Add(lineHeight); textHeight += lineHeight; if (lineWidth > textWidth) textWidth = lineWidth; } // swap width and height if vertically orientated if ( textOrientation == wxVERTICAL ) { long tmp = textHeight; textHeight = textWidth; textWidth = tmp; } if ((align & wxALIGN_BOTTOM) != 0) { if ( textOrientation == wxHORIZONTAL ) y = rect.y + (rect.height - textHeight - 1); else // wxVERTICAL x = rect.x + rect.width - textWidth; } else if ((align & wxALIGN_CENTRE_VERTICAL) != 0) { if ( textOrientation == wxHORIZONTAL ) y = rect.y + (rect.height - textHeight)/2; else // wxVERTICAL x = rect.x + (rect.width - textWidth)/2; } else // wxALIGN_TOP { if ( textOrientation == wxHORIZONTAL ) y = rect.y + 1; else // wxVERTICAL x = rect.x + 1; } // Align each line of a multi-line label for ( l = 0; l < nLines; l++ ) { lineWidth = lineWidths[l]; lineHeight = lineHeights[l]; if ((align & wxALIGN_RIGHT) != 0) { if ( textOrientation == wxHORIZONTAL ) x = rect.x + (rect.width - lineWidth - 1); else // wxVERTICAL y = rect.y + lineWidth + 1; } else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) { if ( textOrientation == wxHORIZONTAL ) x = rect.x + (rect.width - lineWidth)/2; else // wxVERTICAL y = rect.y + rect.height - (rect.height - lineWidth)/2; } else // wxALIGN_LEFT { if ( textOrientation == wxHORIZONTAL ) x = rect.x + 1; else // wxVERTICAL y = rect.y + rect.height - 1; } if ( textOrientation == wxHORIZONTAL ) { dc.DrawText( lines[l], (int)x, (int)y ); y += lineHeight; } else // wxVERTICAL { dc.DrawRotatedText( lines[l], (int)x, (int)y, 90.0 ); x += lineHeight; } } dc.DestroyClippingRegion(); } int wxSheet::StringToLines( const wxString& value, wxArrayString& lines ) const { size_t len = value.Length(); if (!len) return 0; const wxChar *c = value.GetData(); size_t pos, count = 0, start_pos = 0; for (pos = 0; pos < len; pos++, c++) { if ((*c == wxT('\n') || (*c == wxT('\r')))) { if (pos == start_pos) lines.Add(wxEmptyString); else lines.Add(value.Mid(start_pos, pos - start_pos)); start_pos = pos + 1; count++; // Check for DOS line endings and skip them if ((*c == wxT('\r')) && (pos + 1 < len) && (c[1] == wxT('\n'))) { c++; pos++; start_pos++; } } } if ( start_pos < len ) { if (start_pos == 0) lines.Add(value); else lines.Add(value.Mid(start_pos)); count++; } return count; } bool wxSheet::GetTextBoxSize( wxDC& dc, const wxArrayString& lines, long *width, long *height ) const { long w = 0, h = 0; long lineW, lineH; size_t i, count = lines.GetCount(); for ( i = 0; i < count; i++ ) { dc.GetTextExtent( lines[i], &lineW, &lineH ); if (w < lineW) w = lineW; h += lineH; } if (width) *width = w; if (height) *height = h; return (w > 0) && (h > 0); } // ---------------------------------------------------------------------------- wxSheetCoords wxSheet::XYToGridCell( int x, int y, bool clipToMinMax ) const { return wxSheetCoords(YToGridRow(y, clipToMinMax), XToGridCol(x, clipToMinMax)); } int wxSheet::YToGridRow( int y, bool clipToMinMax ) const { return GetSheetRefData()->m_rowEdges.FindIndex(y, clipToMinMax); } int wxSheet::XToGridCol( int x, bool clipToMinMax ) const { return GetSheetRefData()->m_colEdges.FindIndex(x, clipToMinMax); } int wxSheet::YToEdgeOfGridRow( int y ) const { return GetSheetRefData()->m_rowEdges.FindMaxEdgeIndex(y); } int wxSheet::XToEdgeOfGridCol( int x ) const { return GetSheetRefData()->m_colEdges.FindMaxEdgeIndex(x); } wxRect wxSheet::CellToRect( const wxSheetCoords& coords, bool getDeviceRect ) const { wxCHECK_MSG(ContainsCell(coords), wxRect(0,0,0,0), wxT("Invalid coords")); return BlockToRect(GetCellBlock(coords), getDeviceRect); } wxRect wxSheet::BlockToRect( const wxSheetBlock& block, bool getDeviceRect ) const { wxRect rect(BlockToLogicalRect(block, false)); // if grid lines are enabled, then the area of the cell is a bit smaller if ((GridLinesEnabled() & wxHORIZONTAL) != 0) rect.height--; if ((GridLinesEnabled() & wxVERTICAL) != 0) rect.width--; if (getDeviceRect) { switch (GetCellCoordsType(block.GetLeftTop())) { case wxSHEET_CELL_GRID : return CalcScrolledRect(rect); case wxSHEET_CELL_ROWLABEL : CalcScrolledPosition(0, rect.y, NULL, &rect.y); break; case wxSHEET_CELL_COLLABEL : CalcScrolledPosition(rect.x, 0, &rect.x, NULL); break; default : break; } } return rect; } wxSheetBlock wxSheet::ExpandSpannedBlock(const wxSheetBlock& block_) const { if (!HasSpannedCells() || block_.IsEmpty()) return block_; wxSheetBlock block(block_); if (GetSpannedBlocks()) { const wxSheetSelection* spannedBlocks = GetSpannedBlocks(); size_t n, count = spannedBlocks->GetCount(); for (n=0; nGetBlock(n); if (block_.Intersects(b)) // use original block so it doesn't keep growing block = block.Union(b); } } else // brute force expansion { wxSheetCoords c; int row_bottom = block_.GetBottom(); int col_right = block_.GetRight(); for (c.m_row = block_.GetTop(); c.m_row <= row_bottom; c.m_row++) { for (c.m_col = block_.GetLeft(); c.m_col <= col_right; c.m_col++) { block = block.Union(GetCellBlock(c)); } } } return block; } wxRect wxSheet::BlockToLogicalRect( const wxSheetBlock& block_, bool expand_spanned ) const { wxSheetBlock block(expand_spanned ? ExpandSpannedBlock(block_) : block_); wxRect rect(GetColLeft(block.GetLeft()), GetRowTop(block.GetTop()), 0, 0); rect.width = GetColRight(block.GetRight()) - rect.x + 1; rect.height = GetRowBottom(block.GetBottom()) - rect.y + 1; return rect; } wxRect wxSheet::BlockToDeviceRect( const wxSheetBlock &block_, bool expand_spanned) const { // merely convert to scrolled coords return CalcScrolledRect(BlockToLogicalRect(block_, expand_spanned)); } wxSheetBlock wxSheet::LogicalGridRectToBlock(const wxRect &rect, bool wholeCell) const { const int numRows = GetNumberRows(); const int numCols = GetNumberCols(); if (!numRows || !numCols) return wxNullSheetBlock; int leftCol = XToGridCol(rect.GetLeft(), true); int topRow = YToGridRow(rect.GetTop(), true); int rightCol = XToGridCol(rect.GetRight(), true); int bottomRow = YToGridRow(rect.GetBottom(), true); if (wholeCell) { if (GetColLeft(leftCol) < rect.GetLeft()) leftCol++; if (GetColRight(rightCol) > rect.GetRight()) rightCol--; if (GetRowTop(topRow) < rect.GetTop()) topRow++; if (GetRowBottom(bottomRow) > rect.GetBottom()) bottomRow--; } wxSheetBlock block(topRow, leftCol, bottomRow-topRow+1, rightCol-leftCol+1); return block.Intersect(wxSheetBlock(0, 0, numRows, numCols)); } wxSheetBlock wxSheet::GetVisibleGridCellsBlock(bool wholeCellVisible) const { wxRect rect(CalcUnscrolledRect(wxRect(wxPoint(0,0), m_gridWin->GetClientSize()))); return LogicalGridRectToBlock(rect, wholeCellVisible); } wxPoint wxSheet::AlignInRect( int align, const wxRect& rect, const wxSize& size, bool inside ) const { wxPoint origin(rect.x, rect.y); // if it won't fit horizontally, then it must be aligned left if (inside && (size.x > rect.width)) { align &= ~wxALIGN_RIGHT; align &= ~wxALIGN_CENTRE_HORIZONTAL; } // if it won't fit vertically, then it must be aligned to the top if (inside && (size.y > rect.height)) { align &= ~wxALIGN_BOTTOM; align &= ~wxALIGN_CENTRE_VERTICAL; } if ((align & wxALIGN_RIGHT) != 0) origin.x += rect.width - size.x - 1; else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) origin.x += (rect.width - size.x)/2; //else // wxALIGN_LEFT if ((align & wxALIGN_BOTTOM) != 0) origin.y += rect.height - size.y - 1; else if ((align & wxALIGN_CENTRE_VERTICAL) != 0) origin.y += (rect.height - size.y)/2; //else // wxALIGN_TOP return origin; } // ---------------------------------------------------------------------------- // Scrolling functions wxSize wxSheet::GetGridVirtualSize(bool add_margin) const { wxSize size; const int numRows = GetNumberRows(); const int numCols = GetNumberCols(); if ((numCols > 0) && (numRows > 0)) { size.x = GetColRight(numCols - 1); size.y = GetRowBottom(numRows - 1); } if (add_margin) { size.x += GetSheetRefData()->m_marginSize.x; size.y += GetSheetRefData()->m_marginSize.y; } return size; } wxSize wxSheet::GetGridExtent() const { wxSize s(GetGridVirtualSize(true)); if (GetGridWindow()) { wxSize winSize(GetGridWindow()->GetSize()); if (winSize.x > s.x) s.x = winSize.x; if (winSize.y > s.y) s.y = winSize.y; } return s; } void wxSheet::SetGridOrigin( int x, int y, bool adjustScrollBars, bool sendEvt ) { if (!m_gridWin) return; // normally -1 for don't change if (x == -1) x = m_gridOrigin.x; if (y == -1) y = m_gridOrigin.y; // during OnSize gridWin isn't resized yet int cw, ch; GetClientSize( &cw, &ch ); cw -= GetRowLabelWidth(); ch -= GetColLabelHeight(); if ( m_vertScrollBar->IsShown() ) cw -= m_vertScrollBar->GetSize().x; if ( m_horizScrollBar->IsShown() ) ch -= m_horizScrollBar->GetSize().y; // Force fitting, don't allow scrolling out of bounds wxSize virtSize(GetGridVirtualSize()); if ((x < 0) || (virtSize.x < cw)) x = 0; else if (x > virtSize.x-cw) x = virtSize.x - cw; if ((y < 0) || (virtSize.y < ch)) y = 0; else if (y > virtSize.y-ch) y = virtSize.y - ch; int dx = m_gridOrigin.x - x; int dy = m_gridOrigin.y - y; if ((dx == 0) && (dy == 0)) return; m_gridOrigin.x = x; m_gridOrigin.y = y; /* wxRect rect( (dx >= 0) ? 0 : cw+dx, (dy >= 0) ? 0 : ch+dy, dy != 0 ? cw : abs(dx), dx != 0 ? ch : abs(dy) ); */ if (adjustScrollBars) AdjustScrollbars(); // FIXME - or at least check, GTK calcs rect for you, does MSW? m_gridWin->ScrollWindow( dx, dy ); //, &rect ); if (dx != 0) m_colLabelWin->ScrollWindow( dx, 0 ); //, &rect ); if (dy != 0) m_rowLabelWin->ScrollWindow( 0, dy ); //, &rect ); // Let the windows refresh before next scroll event, otherwise windows // don't line up //wxYieldIfNeeded(); if (sendEvt) SendEvent(wxEVT_SHEET_VIEW_CHANGED, GetGridCursorCell()); } void wxSheet::OnScroll( wxScrollEvent &event ) { if (!m_gridWin) return; event.Skip(); int pos = event.GetPosition(); //wxPrintf(wxT("Pos %d %d Length %d Left %d Right %d\n"), pos, m_horizScrollBar->GetThumbPosition(), m_horizScrollBar->GetThumbSize(), pos*m_horizScrollBar->GetThumbSize(), pos*m_horizScrollBar->GetThumbSize()+GetGridWindow()->GetClientSize().x); if (event.GetId() == ID_HORIZ_SCROLLBAR) SetGridOrigin( pos*15, -1, false, true ); //SetGridOrigin( pos*m_horizScrollBar->GetThumbSize(), -1, false, true ); else if (event.GetId() == ID_VERT_SCROLLBAR) SetGridOrigin( -1, pos*15, false, true ); //SetGridOrigin( -1, pos*m_vertScrollBar->GetThumbSize(), false, true ); } void wxSheet::AdjustScrollbars(bool calc_win_sizes) { if (!m_gridWin || m_resizing) return; m_resizing = true; bool horizSbShown = m_horizScrollBar->IsShown(); bool vertSbShown = m_vertScrollBar->IsShown(); int sb_width = m_vertScrollBar->GetSize().x; int sb_height = m_horizScrollBar->GetSize().y; int cw, ch; GetClientSize( &cw, &ch ); // Grid window width and height, may be in OnSize so not sized yet int gw = cw - GetRowLabelWidth(); int gh = ch - GetColLabelHeight(); // grid total size wxSize virtSize(GetGridVirtualSize()); /* // take into account editor if shown // FIXME what is this? if ( 0 && IsCellEditControlShown() ) { int w2, h2; int r = GetGridCursorRow(); int c = GetGridCursorCol(); int x = GetColLeft(c); int y = GetRowTop(r); // how big is the editor GetEditControl().GetControl()->GetSize(&w2, &h2); w2 += x; h2 += y; if( w2 > virtSize.x ) virtSize.x = w2; if( h2 > virtSize.y ) virtSize.y = h2; } */ // Figure out if we need the scrollbars at all bool need_Xscroll = (m_scrollBarMode & SB_HORIZ_NEVER) != 0 ? false : (((m_scrollBarMode & SB_HORIZ_ALWAYS) != 0) ? true : virtSize.x > gw); bool need_Yscroll = (m_scrollBarMode & SB_VERT_NEVER ) != 0 ? false : (((m_scrollBarMode & SB_VERT_ALWAYS ) != 0) ? true : virtSize.y > gh); // Now cut down size due to the scrollbars if shown if (need_Xscroll) gh -= sb_height; if (need_Yscroll) gw -= sb_width; // Maybe now that it's smaller we need the other scrollbar need_Xscroll = (m_scrollBarMode & SB_HORIZ_NEVER) != 0 ? false : (((m_scrollBarMode & SB_HORIZ_ALWAYS) != 0) ? true : virtSize.x > gw); need_Yscroll = (m_scrollBarMode & SB_VERT_NEVER ) != 0 ? false : (((m_scrollBarMode & SB_VERT_ALWAYS ) != 0) ? true : virtSize.y > gh); //if (need_Xscroll) ch -= sb_height; //if (need_Yscroll) cw -= sb_width; //bool horiz_splitter = need_Xscroll && m_enable_split_horiz; //bool vert_splitter = need_Yscroll && m_enable_split_vert; // width and height of the horiz and vert scrollbars //int sw = cw - (vert_splitter ? SPLIT_BUTTON_WIDTH : 0); //int sh = ch - (horiz_splitter ? SPLIT_BUTTON_WIDTH : 0); // set scrollbar parameters int thumbX = SHEET_SCROLL_LINE_X; int thumbY = SHEET_SCROLL_LINE_Y; //virtSize.x += sw - gw; //virtSize.y += sh - gh; // FIXME this is wrong for GTK and MSW, but why? int rangeX = !need_Xscroll ? 0 : 1 + (virtSize.x - gw + thumbX - 1)/thumbX; int rangeY = !need_Yscroll ? 0 : 1 + (virtSize.y - gh + thumbY - 1)/thumbY; int pageX = int((gw * 0.9) / thumbX); int pageY = int((gh * 0.9) / thumbY); int posX = m_gridOrigin.x/thumbX; int posY = m_gridOrigin.y/thumbY; thumbX = 1; thumbY = 1; //wxPrintf(wxT("Pos %d %d, virtSize %d %d, range %d %d, thumb %d %d page %d %d, win %d %d \n"), // posX, posY, virtSize.x, virtSize.y, rangeX, rangeY, thumbX, thumbY, pageX, pageY, gw, gh); if (need_Xscroll) m_horizScrollBar->SetScrollbar(posX, thumbX, rangeX, pageX); if (need_Yscroll) m_vertScrollBar->SetScrollbar(posY, thumbY, rangeY, pageY); //wxPrintf(wxT("Set pos %d range %d, thumb %d, page %d\n"), // m_horizScrollBar->GetThumbPosition(), m_horizScrollBar->GetRange(), m_horizScrollBar->GetThumbSize(), m_horizScrollBar->GetPageSize()); // recalculate the windows sizes and positions if we added/removed scrollbar bool calcSizes = false; if (need_Xscroll != horizSbShown) { calcSizes = true; m_horizScrollBar->Show(need_Xscroll); } if (need_Yscroll != vertSbShown) { calcSizes = true; m_vertScrollBar->Show(need_Yscroll); } m_resizing = false; if (calcSizes && calc_win_sizes) CalcWindowSizes(false); } void wxSheet::PrepareGridDC( wxDC& dc ) { dc.SetDeviceOrigin( -m_gridOrigin.x, -m_gridOrigin.y ); } void wxSheet::PrepareRowLabelDC( wxDC& dc ) { dc.SetDeviceOrigin( 0, -m_gridOrigin.y ); } void wxSheet::PrepareColLabelDC( wxDC& dc ) { dc.SetDeviceOrigin( -m_gridOrigin.x, 0 ); } // ---------------------------------------------------------------------------- // Checks and returns a suitable horiz or vert alignment, if invalid replaces // with wxSheetCellAttr::NoHorizAlign/NoVertAlign static int CheckAlignment(int align) { // note: it's a shame that wxALIGN_LEFT = wxALIGN_TOP = 0 int count = 0; if ((align & wxSHEET_AttrAlignRight) != 0) count++; if ((align & wxSHEET_AttrAlignCenterHoriz) != 0) count++; if ((align & wxSHEET_AttrAlignHorizUnset) != 0) count++; if (count > 1) { align &= ~wxSHEET_AttrAlignHoriz_Mask; // clear whatever is there align |= wxSHEET_AttrAlignHorizUnset; // set to no alignment } count = 0; if ((align & wxSHEET_AttrAlignBottom) != 0) count++; if ((align & wxSHEET_AttrAlignCenterVert) != 0) count++; if ((align & wxSHEET_AttrAlignVertUnset) != 0) count++; if (count > 1) { align &= ~wxSHEET_AttrAlignVert_Mask; // clear whatever is there align |= wxSHEET_AttrAlignVertUnset; // set to no alignment } return align; } int wxSheet::SetAlignment(int orig_align, int hAlign, int vAlign) { if (hAlign != -1) { orig_align &= ~wxSHEET_AttrAlignHoriz_Mask; // clear old orig_align |= (hAlign & wxSHEET_AttrAlignHoriz_Mask); // set new } if (vAlign != -1) { orig_align &= ~wxSHEET_AttrAlignVert_Mask; orig_align |= (vAlign & wxSHEET_AttrAlignVert_Mask); } return CheckAlignment(orig_align); } // ---------------------------------------------------------------------------- bool wxSheet::HasFocus() const { wxWindow *win = FindFocus(); return win && ((win==(wxSheet*)this) || (win==m_gridWin) || (win==m_rowLabelWin) || (win == m_colLabelWin) || (win == m_cornerLabelWin)); } // ---------------------------------------------------------------------------- // Event handlers void wxSheet::OnMouse( wxMouseEvent& event ) { wxWindow *win = (wxWindow*)event.GetEventObject(); if (win == this) ProcessSheetMouseEvent(event); else if (win == m_rowLabelWin) ProcessRowLabelMouseEvent(event); else if (win == m_colLabelWin) ProcessColLabelMouseEvent(event); else if (win == m_cornerLabelWin) ProcessCornerLabelMouseEvent(event); else if (win == m_gridWin) ProcessGridCellMouseEvent(event); else event.Skip(); } void wxSheet::OnMouseWheel( wxMouseEvent& event ) { wxWindow *win = (wxWindow*)event.GetEventObject(); // Scroll up and down by a 1/3 of the height of the window if ((win == m_rowLabelWin) || (win == m_gridWin)) { // GTK doesn't have good wheel events if (GetNumberRows() > 0) { wxPoint origin(GetGridOrigin()); wxSize size(GetGridWindow()->GetClientSize()); int dy = event.GetWheelRotation() < 0 ? 1 : -1; SetGridOrigin( origin.x, origin.y + dy * size.y/3, true, true ); } } // Scroll sideways by a 1/3 of the width of the window else if (win == m_colLabelWin) { if (GetNumberCols() > 0) { wxPoint origin(GetGridOrigin()); wxSize size(GetGridWindow()->GetClientSize()); int dx = event.GetWheelRotation() < 0 ? 1 : -1; SetGridOrigin( origin.x + dx * size.x/3, origin.y, true, true ); } } event.Skip(); } void wxSheet::ProcessSheetMouseEvent( wxMouseEvent& event ) { if (!m_enable_split_vert && !m_enable_split_horiz) return; wxPoint mousePos = event.GetPosition(); if (event.LeftDown()) { #if wxCHECK_VERSION(2,7,0) if (m_vertSplitRect.Contains(mousePos) || m_horizSplitRect.Contains(mousePos)) #else if (m_vertSplitRect.Inside(mousePos) || m_horizSplitRect.Inside(mousePos)) #endif SetCaptureWindow(this); } else if (event.LeftUp()) { SetCaptureWindow(NULL); } else if (event.Dragging() && HasCapture() && HasMouseCursorMode(WXSHEET_CURSOR_SPLITTING)) { wxSheetSplitterEvent splitEvent(GetId(), wxEVT_SHEET_SPLIT_BEGIN); splitEvent.SetEventObject(this); splitEvent.m_vert_split = HasMouseCursorMode(WXSHEET_CURSOR_SPLIT_VERTICAL); SetCaptureWindow(NULL); SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); GetEventHandler()->ProcessEvent(splitEvent); } else if ((event.Leaving() || event.Entering()) && !HasCapture()) { SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); } else if (event.Moving() && !HasCapture()) { #if wxCHECK_VERSION(2,7,0) if (m_vertSplitRect.Contains(mousePos)) SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_VERTICAL, this); else if (m_horizSplitRect.Contains(mousePos)) SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_HORIZONTAL, this); else SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); #else if (m_vertSplitRect.Inside(mousePos)) SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_VERTICAL, this); else if (m_horizSplitRect.Inside(mousePos)) SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_HORIZONTAL, this); else SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); #endif } } void wxSheet::ProcessRowLabelMouseEvent( wxMouseEvent& event ) { int x, y; m_mousePos = event.GetPosition(); CalcUnscrolledPosition( m_mousePos.x, m_mousePos.y, &x, &y ); wxSheetCoords coords(YToGridRow(y), -1); if ( event.Entering() || event.Leaving() ) { if (!event.Dragging() && !m_isDragging) SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_rowLabelWin); return; } if ( event.Dragging() && event.LeftIsDown() ) { if (!m_isDragging) { m_isDragging = true; SetCaptureWindow(m_rowLabelWin); } if ( event.LeftIsDown() ) { bool can_scroll = true; switch ( GetMouseCursorMode() ) { case WXSHEET_CURSOR_RESIZE_ROW: { y = wxMax( y, GetRowTop(m_dragRowOrCol) + GetMinimalRowHeight(m_dragRowOrCol)); can_scroll = false; // y != m_dragLastPos; DrawRowColResizingMarker( y ); break; } case WXSHEET_CURSOR_SELECT_ROW: { if (HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectCols)) break; // check for clearing here since we didn't if editing allowed bool add = event.ShiftDown() || event.ControlDown(); if (HasSelection(false) && !add) ClearSelection(true); if (ContainsGridCell(GetSelectingAnchor()) && ContainsRowLabelCell(coords)) { HighlightSelectingBlock(GetSelectingAnchor(), wxSheetCoords(coords.m_row, GetNumberCols()+1)); } break; } default: break; } if (can_scroll && ((m_mousePos.y < 0) || (m_mousePos.y > m_rowLabelWin->GetClientSize().GetHeight()))) { if (!m_mouseTimer) StartMouseTimer(); } else StopMouseTimer(); } return; } StopMouseTimer(); SetCaptureWindow(NULL); m_isDragging = false; if ( event.LeftDown() ) { if (IsCellEditControlShown()) DisableCellEditControl(true); // don't send a label click event for a hit on the edge of the row label // this is probably the user wanting to resize the row if ( YToEdgeOfGridRow(y) < 0 ) { if ( ContainsRowLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) && !HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectCols) ) { bool add = event.ShiftDown() || event.ControlDown(); wxSheetBlock block; if ( event.ShiftDown() ) { SetSelectingAnchor(wxSheetCoords(GetGridCursorRow(), 0)); block = wxSheetBlock(GetSelectingAnchor(), wxSheetCoords(coords.m_row, GetNumberCols()+1)); } else { SetSelectingAnchor(wxSheetCoords(coords.m_row, 0)); block = wxSheetBlock(GetSelectingAnchor(), 1, GetNumberCols()+1); } // if you can edit the row label then don't select row until drag bool can_edit = CanEnableCellControl(coords); if (!add && HasSelection() && (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, false, false, &event) != EVT_VETOED)) { ClearSelection(true); } if (!can_edit) HighlightSelectingBlock(block); SetMouseCursorMode(WXSHEET_CURSOR_SELECT_ROW, m_rowLabelWin); } } else { // starting to drag-resize a row if ( CanDragRowSize() ) { SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW, m_rowLabelWin); SetCaptureWindow(m_rowLabelWin); } } } else if ( event.LeftDClick() ) { int row = YToEdgeOfGridRow(y); if ( row < 0 ) { if ( ContainsRowLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED)) { if (CanEnableCellControl(coords)) { m_waitForSlowClick = false; ClearSelection(true); EnableCellEditControl(coords); if ( IsCellEditControlCreated() ) GetSheetRefData()->m_cellEditor.StartingClick(); } } } else { // adjust row height depending on label text if (CanDragRowSize()) AutoSizeRowLabelHeight( row ); SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); m_dragLastPos = -1; } } else if ( event.LeftUp() ) { StopMouseTimer(); SetCaptureWindow(NULL); if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW) ) { // Note: send event *after* doing default processing in this case if (DoEndDragResizeRowCol()) SendEvent( wxEVT_SHEET_ROW_SIZE, wxSheetCoords(m_dragRowOrCol, -1), &event ); } else if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_ROW) ) { if (!GetSelectingBlock().IsEmpty()) { bool add = event.ShiftDown() || event.ControlDown(); if (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, add, &event) != EVT_VETOED) { SelectRows(GetSelectingBlock().GetTop(), GetSelectingBlock().GetBottom(), add, true); SetSelectingBlock(wxNullSheetBlock); } } } SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_rowLabelWin); m_dragLastPos = -1; if (!m_keySelecting) SetSelectingAnchor(wxNullSheetCoords); // send after default processing, they can use own evt handler SendEvent(wxEVT_SHEET_LABEL_LEFT_UP, coords, &event); } else if ( event.RightDown() ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if ( ContainsRowLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED)) { // no default action at the moment } } else if ( event.RightDClick() ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if ( ContainsRowLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED)) { // no default action at the moment } } else if ( event.RightUp() ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if ( ContainsRowLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_RIGHT_UP, coords, &event) == EVT_SKIPPED)) { // no default action at the moment } } else if ( event.Moving() ) { m_dragRowOrCol = YToEdgeOfGridRow( y ); if ( m_dragRowOrCol >= 0 ) { if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) { // don't capture the mouse yet if ( CanDragRowSize() ) { SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW, m_rowLabelWin); } } } else if ( !HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) { SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_rowLabelWin); } } } void wxSheet::ProcessColLabelMouseEvent( wxMouseEvent& event ) { int x, y; m_mousePos = event.GetPosition(); CalcUnscrolledPosition( m_mousePos.x, m_mousePos.y, &x, &y ); wxSheetCoords coords(-1, XToGridCol(x)); if ( event.Entering() || event.Leaving() ) { if (!event.Dragging() && !m_isDragging) SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); return; } if ( event.Dragging() && event.LeftIsDown() ) { if (!m_isDragging) { m_isDragging = true; SetCaptureWindow(m_colLabelWin); } if ( event.LeftIsDown() ) { bool can_scroll = true; switch( GetMouseCursorMode() ) { case WXSHEET_CURSOR_RESIZE_COL : { x = wxMax( x, GetColLeft(m_dragRowOrCol) + GetMinimalColWidth(m_dragRowOrCol)); can_scroll = false; // x != m_dragLastPos; DrawRowColResizingMarker( x ); break; } case WXSHEET_CURSOR_SELECT_COL : { if (HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectRows)) break; // check for clearing here since we didn't if editing allowed bool add = event.ShiftDown() || event.ControlDown(); if (HasSelection(false) && !add) ClearSelection(true); if (ContainsGridCell(GetSelectingAnchor()) && ContainsColLabelCell(coords)) { HighlightSelectingBlock(GetSelectingAnchor(), wxSheetCoords(GetNumberRows()+1, coords.m_col)); } break; } default: break; } if (can_scroll && ((m_mousePos.x < 0) || (m_mousePos.x > m_colLabelWin->GetClientSize().GetWidth()))) { if (!m_mouseTimer) StartMouseTimer(); } else StopMouseTimer(); } return; } StopMouseTimer(); SetCaptureWindow(NULL); m_isDragging = false; if ( event.LeftDown() ) { if (IsCellEditControlShown()) DisableCellEditControl(true); // don't send a label click event for a hit on the edge of the col label // this is probably the user wanting to resize the col if ( XToEdgeOfGridCol(x) < 0 ) { if ( ContainsColLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) && !HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectRows) ) { bool add = event.ShiftDown() || event.ControlDown(); wxSheetBlock block; if ( event.ShiftDown() ) { SetSelectingAnchor(wxSheetCoords(0, GetGridCursorCol())); block = wxSheetBlock(GetSelectingAnchor(), wxSheetCoords(GetNumberRows()+1, coords.m_col)); } else { SetSelectingAnchor(wxSheetCoords(0, coords.m_col)); block = wxSheetBlock(GetSelectingAnchor(), GetNumberRows()+1, 1); } // if you can edit the row label then don't select row bool can_edit = CanEnableCellControl(coords); if (!add && HasSelection() && (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, false, false, &event) != EVT_VETOED)) { ClearSelection(true); } if (!can_edit) HighlightSelectingBlock(block); SetMouseCursorMode(WXSHEET_CURSOR_SELECT_COL, m_colLabelWin); } } else { // starting to drag-resize a col if ( CanDragColSize() ) { SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL, m_colLabelWin); SetCaptureWindow(m_colLabelWin); } } } if ( event.LeftDClick() ) { int col = XToEdgeOfGridCol(x); if ( col < 0 ) { if ( ContainsColLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED)) { if (CanEnableCellControl(coords)) { m_waitForSlowClick = false; ClearSelection(true); EnableCellEditControl(coords); if ( IsCellEditControlCreated() ) GetSheetRefData()->m_cellEditor.StartingClick(); } } } else { // adjust column width depending on label text if (CanDragColSize()) AutoSizeColLabelWidth( col ); SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); m_dragLastPos = -1; } } else if ( event.LeftUp() ) { StopMouseTimer(); SetCaptureWindow(NULL); if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL) ) { // Note: send event *after* doing default processing in this case if (DoEndDragResizeRowCol()) SendEvent( wxEVT_SHEET_COL_SIZE, wxSheetCoords(-1, m_dragRowOrCol), &event ); } else if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_COL) ) { if (!GetSelectingBlock().IsEmpty()) { bool add = event.ShiftDown() || event.ControlDown(); if (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, add, &event) != EVT_VETOED) { SelectCols(GetSelectingBlock().GetLeft(), GetSelectingBlock().GetRight(), add, true); SetSelectingBlock(wxNullSheetBlock); } } } SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); m_dragLastPos = -1; if (!m_keySelecting) SetSelectingAnchor(wxNullSheetCoords); // send after default processing, they can use own evt handler SendEvent(wxEVT_SHEET_LABEL_LEFT_UP, coords, &event); } else if ( event.RightDown() ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if (ContainsColLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED)) { // no default action at the moment } } else if ( event.RightDClick() ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if (ContainsColLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED)) { // no default action at the moment } } else if ( event.RightUp() ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if (ContainsColLabelCell(coords) && (SendEvent(wxEVT_SHEET_LABEL_RIGHT_UP, coords, &event) == EVT_SKIPPED)) { // no default action at the moment } } else if ( event.Moving() ) { m_dragRowOrCol = XToEdgeOfGridCol( x ); if ( m_dragRowOrCol >= 0 ) { if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) { // don't capture the cursor yet if ( CanDragColSize() ) SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL, m_colLabelWin); } } else if ( !HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); } } void wxSheet::ProcessCornerLabelMouseEvent( wxMouseEvent& event ) { wxSheetCoords coords(-1,-1); if ( event.Dragging() ) { if ( event.LeftIsDown() ) { if ((GetNumberRows() > 0) && (GetNumberCols() > 0) && !HasSelectionMode(wxSHEET_SelectNone)) { SetSelectingAnchor(wxSheetCoords(0, 0)); HighlightSelectingBlock(GetSelectingAnchor(), wxSheetCoords(GetNumberRows()+1, GetNumberCols()+1)); } } return; } if ( event.LeftDown() ) { SetSelectingBlock(wxNullSheetBlock); if ( SendEvent(wxEVT_SHEET_LABEL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) { wxSheetBlock block(0, 0, GetNumberRows()+1, GetNumberCols()+1); // if you can edit the corner label then don't select everything bool can_edit = CanEnableCellControl(coords); if (!can_edit && !HasSelectionMode(wxSHEET_SelectNone) && (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, true, false, &event) != EVT_VETOED)) { SelectAll(true); } } } else if ( event.LeftDClick() ) { if (SendEvent(wxEVT_SHEET_LABEL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED) { if (CanEnableCellControl(coords)) { ClearSelection(true); EnableCellEditControl(coords); if ( IsCellEditControlCreated() ) GetSheetRefData()->m_cellEditor.StartingClick(); m_waitForSlowClick = false; } } } else if ( event.LeftUp() ) { if (!GetSelectingBlock().IsEmpty()) { if (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, false, &event) != EVT_VETOED) { SelectAll(true); SetSelectingBlock(wxNullSheetBlock); } } // send after default processing, they can use own evt handler SendEvent(wxEVT_SHEET_LABEL_LEFT_UP, coords, &event); } else if ( event.RightDown() ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED) { // no default action at the moment } } else if ( event.RightDClick() ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED) { // no default action at the moment } } else if ( event.RightUp() ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if (SendEvent(wxEVT_SHEET_LABEL_RIGHT_UP, coords, &event) == EVT_SKIPPED) { // no default action at the moment } } } void wxSheet::ProcessGridCellMouseEvent( wxMouseEvent& event ) { int x, y; m_mousePos = event.GetPosition(); CalcUnscrolledPosition( m_mousePos.x, m_mousePos.y, &x, &y ); wxSheetCoords coords(XYToGridCell( x, y )); //wxPrintf("Mouse %d %d, %d %d\n", x, y, m_mousePos.x, m_mousePos.y); // VZ: if we do this, the mode is reset to WXSHEET_CURSOR_SELECT_CELL // immediately after it becomes WXSHEET_CURSOR_RESIZE_ROW/COL under wxGTK if ( event.Entering() || event.Leaving() ) { //SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); //m_gridWin->SetCursor( *wxSTANDARD_CURSOR ); return; } if ( event.Dragging() && event.LeftIsDown() ) { //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); // Don't start doing anything until the mouse has been dragged at // least 3 pixels in any direction... if (!m_isDragging) { SetCaptureWindow(m_gridWin); if (m_startDragPos == wxDefaultPosition) { m_startDragPos = m_mousePos; return; } if ((abs(m_startDragPos.x - m_mousePos.x) < 4) && (abs(m_startDragPos.y - m_mousePos.y) < 4)) return; } bool can_scroll = true; m_isDragging = true; if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) { // Hide the edit control, so it won't interfer with drag-shrinking. if ( IsCellEditControlShown() ) DisableCellEditControl(true); if ( ContainsGridCell(coords) && !HasSelectionMode(wxSHEET_SelectNone) ) { HighlightSelectingBlock( GetSelectingAnchor(), coords ); } } else if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW) ) { y = wxMax( y, GetRowTop(m_dragRowOrCol) + GetMinimalRowHeight(m_dragRowOrCol) ); can_scroll = false; // y != m_dragLastPos; DrawRowColResizingMarker( y ); } else if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL) ) { x = wxMax( x, GetColLeft(m_dragRowOrCol) + GetMinimalColWidth(m_dragRowOrCol)); can_scroll = false; // x != m_dragLastPos; DrawRowColResizingMarker( x ); } if (can_scroll && #if wxCHECK_VERSION(2,7,0) !wxRect(wxPoint(0,0), m_gridWin->GetClientSize()).Contains(m_mousePos)) #else !wxRect(wxPoint(0,0), m_gridWin->GetClientSize()).Inside(m_mousePos)) #endif { if (!m_mouseTimer) StartMouseTimer(); } else StopMouseTimer(); return; } StopMouseTimer(); SetCaptureWindow(NULL); m_isDragging = false; m_startDragPos = wxDefaultPosition; if ( event.LeftDown() && ContainsGridCell(coords) ) { if ( SendEvent(wxEVT_SHEET_CELL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) { if ( !event.ControlDown() && HasSelection() ) { wxSheetBlock block(0, 0, GetNumberRows()-1, GetNumberCols()-1); if (!HasSelectionMode(wxSHEET_SelectNone) && SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, false, false, &event) != EVT_VETOED) { ClearSelection(true); } } if ( event.ShiftDown() ) { wxSheetBlock block(GetGridCursorCell(), coords); if (!HasSelectionMode(wxSHEET_SelectNone) && SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, true, true, &event) != EVT_VETOED) { SelectBlock(block, event.ControlDown(), true); } } else if ( (XToEdgeOfGridCol(x) < 0) && (YToEdgeOfGridRow(y) < 0) ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); MakeCellVisible( coords ); if ( !ContainsGridCell(GetSelectingAnchor()) ) SetSelectingAnchor(coords); if ( event.ControlDown() ) { // toggle cell selection int sel = IsCellSelected(coords); wxSheetBlock block(coords, 1, 1); if (!HasSelectionMode(wxSHEET_SelectNone) && SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, !sel, !sel, &event) != EVT_VETOED) { ToggleCellSelection(coords, !sel, true); SetSelectingBlock(wxNullSheetBlock); } } else { if (GetGridCursorCell() == coords) m_waitForSlowClick = true; SetGridCursorCell( coords ); // FIXME weird? Highlight a whole row/col when not in select cells? if ( !HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectCells) ) HighlightSelectingBlock( coords, coords ); } } } } else if ( event.LeftDClick() && ContainsGridCell(coords) ) { if ((XToEdgeOfGridCol(x) < 0) && (YToEdgeOfGridRow(y) < 0) && (SendEvent(wxEVT_SHEET_CELL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED)) { if ((coords == GetGridCursorCell()) && CanEnableCellControl(GetGridCursorCell())) { ClearSelection(true); EnableCellEditControl(GetGridCursorCell()); if ( IsCellEditControlCreated() ) GetSheetRefData()->m_cellEditor.StartingClick(); m_waitForSlowClick = false; } } } else if ( event.LeftUp() ) { StopMouseTimer(); SetCaptureWindow(NULL); if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) { if ((coords == GetGridCursorCell()) && m_waitForSlowClick && CanEnableCellControl(GetGridCursorCell())) { ClearSelection(true); EnableCellEditControl(GetGridCursorCell()); if ( IsCellEditControlCreated() ) GetSheetRefData()->m_cellEditor.StartingClick(); m_waitForSlowClick = false; } else if ( !GetSelectingBlock().IsEmpty() ) { if (!HasSelectionMode(wxSHEET_SelectNone) && SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, true, &event) != EVT_VETOED) { SelectBlock(GetSelectingBlock(), true, true); SetSelectingBlock(wxNullSheetBlock); } } } else if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW) ) { // Note: send event *after* doing default processing in this case if (DoEndDragResizeRowCol()) SendEvent( wxEVT_SHEET_ROW_SIZE, wxSheetCoords(m_dragRowOrCol, -1), &event ); SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); } else if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL) ) { // Note: send event *after* doing default processing in this case if (DoEndDragResizeRowCol()) SendEvent( wxEVT_SHEET_COL_SIZE, wxSheetCoords(-1, m_dragRowOrCol), &event ); SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); } // Show edit control, if it has been hidden for drag-shrinking. if (IsCellEditControlCreated() && !IsCellEditControlShown()) ShowCellEditControl(); if (!m_keySelecting) SetSelectingAnchor(wxNullSheetCoords); m_dragLastPos = -1; // send after default processing, they can use own evt handler SendEvent(wxEVT_SHEET_CELL_LEFT_UP, coords, &event); } else if ( event.RightDown() && ContainsGridCell(coords) ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if (SendEvent(wxEVT_SHEET_CELL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED) { // no default action at the moment } } else if ( event.RightDClick() && ContainsGridCell(coords) ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if (SendEvent(wxEVT_SHEET_CELL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED) { // no default action at the moment } } else if ( event.RightUp() && ContainsGridCell(coords) ) { if (IsCellEditControlCreated()) DisableCellEditControl(true); if (SendEvent(wxEVT_SHEET_CELL_RIGHT_UP, coords, &event) == EVT_SKIPPED) { // no default action at the moment } } else if ( event.Moving() && !event.IsButton() ) { if ( (coords.GetRow() < 0) || (coords.GetCol() < 0) ) { // out of grid cell area SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); return; } int dragRow = YToEdgeOfGridRow( y ); int dragCol = XToEdgeOfGridCol( x ); // check if this is inside a spanned cell, if so don't drag if ( (dragRow >= 0) || (dragCol >= 0) ) { const wxSheetBlock cellBlock(GetCellBlock(coords)); if (!cellBlock.IsOneCell() && ((dragRow != cellBlock.GetBottom()) || (dragCol != cellBlock.GetRight()))) dragRow = dragCol = -1; } // Dragging on the corner of a cell to resize in both // directions is not implemented yet... if ( (dragRow >= 0) && (dragCol >= 0) ) { SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); } else if ( dragRow >= 0 ) { m_dragRowOrCol = dragRow; if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) { if ( CanDragRowSize() && CanDragGridSize() ) { SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW, m_gridWin); SetCaptureWindow(m_gridWin); } } if ( dragCol >= 0 ) m_dragRowOrCol = dragCol; } else if ( dragCol >= 0 ) { m_dragRowOrCol = dragCol; if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) { if ( CanDragColSize() && CanDragGridSize() ) { SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL, m_gridWin); SetCaptureWindow(m_gridWin); } } } // Neither on a row or col edge else if ( !HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); } } void wxSheet::OnKeyDown( wxKeyEvent& event ) { //wxCHECK_RET(!m_inOnKeyDown, wxT("wxSheet::OnKeyDown called while already active")); // yield called from SetGridOrigin causes this in MSW if (m_inOnKeyDown) return; m_inOnKeyDown = true; // FIXME - is this really a good idea? probably not, should make own "key" event // propagate the event up and see if it gets processed //wxWindow *parent = GetParent(); //wxKeyEvent keyEvt( event ); //keyEvt.SetEventObject( parent ); //!parent->GetEventHandler()->ProcessEvent(keyEvt) && if ( GetNumberRows() && GetNumberCols() ) { // try local handlers switch ( event.GetKeyCode() ) { case WXK_RETURN: case WXK_NUMPAD_ENTER: { if ( event.ControlDown() ) event.Skip(); // to let the edit control have the return else { if ( IsCellEditControlCreated() ) DisableCellEditControl(true); if ( GetGridCursorRow() < GetNumberRows()-1 ) MoveCursorDown( event.ShiftDown() ); } break; } case WXK_ESCAPE: { ClearSelection(); break; } case WXK_TAB: { if (event.ShiftDown()) { if ( IsCellEditControlCreated() ) DisableCellEditControl(true); if ( GetGridCursorCol() > 0 ) MoveCursorLeft( false ); } else { if ( IsCellEditControlCreated() ) DisableCellEditControl(true); if ( GetGridCursorCol() < GetNumberCols()-1 ) MoveCursorRight( false ); } break; } case WXK_SPACE: { if ( event.ShiftDown() && ContainsGridCell(GetGridCursorCell()) ) { wxSheetBlock block(GetGridCursorRow(), 0, 1, GetNumberCols()+1); if (!GetSelectingBlock().IsEmpty() && GetSelectingBlock().Contains(GetGridCursorCell())) { block.SetTop(GetSelectingBlock().GetTop()); block.SetBottom(GetSelectingBlock().GetBottom()); } if (!HasSelectionMode(wxSHEET_SelectNone) && SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, true, false, &event) != EVT_VETOED) { SelectRows(block.GetTop(), block.GetBottom(), false, true); } break; } if ( event.ControlDown() && ContainsGridCell(GetGridCursorCell()) ) { wxSheetBlock block(0, GetGridCursorCol(), GetNumberRows()+1, 1); if (!GetSelectingBlock().IsEmpty() && GetSelectingBlock().Contains(GetGridCursorCell())) { block.SetLeft(GetSelectingBlock().GetLeft()); block.SetRight(GetSelectingBlock().GetRight()); } if (!HasSelectionMode(wxSHEET_SelectNone) && SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, true, false, &event) != EVT_VETOED) { SelectCols(block.GetLeft(), block.GetRight(), false, true); } break; } if ( event.AltDown() && ContainsGridCell(GetGridCursorCell()) ) { // Toggle cell selection FIXME not sure how useful this is bool sel = IsCellSelected(GetGridCursorCell()); wxSheetBlock block(GetGridCursorCell(), 1, 1); if (!HasSelectionMode(wxSHEET_SelectNone) && SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, !sel, !sel, &event) != EVT_VETOED) { ToggleCellSelection(GetGridCursorCell(), !sel, true); } break; } if ( !IsEditable() ) { MoveCursorRight( false ); break; } // Otherwise fall through to default } default: { // is it possible to edit the current cell at all? if ( !IsCellEditControlCreated() && CanEnableCellControl(GetGridCursorCell()) ) { // yes, now check whether the cells editor accepts the key wxSheetCellEditor editor(GetAttr(GetGridCursorCell()).GetEditor(this, GetGridCursorCell())); // is special and will always start editing, for // other keys - ask the editor itself if ( ((event.GetKeyCode() == WXK_F2) && !event.HasModifiers()) || editor.IsAcceptedKey(event) ) { // ensure cell is visble MakeCellVisible(GetGridCursorCell()); EnableCellEditControl(GetGridCursorCell()); // a problem can arise if the cell is not completely // visible (even after calling MakeCellVisible the // control is not created and calling StartingKey will // crash the app if ( IsCellEditControlCreated() ) GetSheetRefData()->m_cellEditor.StartingKey(event); } else event.Skip(); } else { // let others process char events with modifiers or all // char events for readonly cells event.Skip(); } break; } } } m_inOnKeyDown = false; } void wxSheet::OnKeyUp( wxKeyEvent& event ) { if ( m_keySelecting && (event.GetKeyCode() == WXK_SHIFT) ) { if ( !GetSelectingBlock().IsEmpty() ) { if (!HasSelectionMode(wxSHEET_SelectNone) && SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, true, &event) != EVT_VETOED) { SelectBlock(GetSelectingBlock(), true, true); SetSelectingBlock(wxNullSheetBlock); } SetSelectingAnchor(wxNullSheetCoords); } m_keySelecting = false; } event.Skip(); } void wxSheet::OnChar( wxKeyEvent& event ) { //wxCHECK_RET(!m_inOnKeyDown, wxT("wxSheet::OnKeyDown called while already active")); // yield called from SetGridOrigin causes this in MSW if (m_inOnKeyDown) return; if ( !GetNumberRows() || !GetNumberCols() ) { event.Skip(); return; } m_inOnKeyDown = true; int keyMods = GetKeyModifiers(&event); // try local handlers switch ( event.GetKeyCode() ) { case WXK_UP: { if (!ContainsGridCell(GetGridCursorCell())) break; if ( event.ControlDown() ) MoveCursorUpBlock( event.ShiftDown() ); else if ( keyMods == ALT_DOWN ) SetRowHeight(GetGridCursorRow(), GetRowHeight(GetGridCursorRow())-5); else MoveCursorUp( event.ShiftDown() ); break; } case WXK_DOWN: { if (!ContainsGridCell(GetGridCursorCell())) break; if ( event.ControlDown() ) MoveCursorDownBlock( event.ShiftDown() ); else if ( keyMods == ALT_DOWN ) SetRowHeight(GetGridCursorRow(), GetRowHeight(GetGridCursorRow())+5); else MoveCursorDown( event.ShiftDown() ); break; } case WXK_LEFT: { if (!ContainsGridCell(GetGridCursorCell())) break; if ( event.ControlDown() ) MoveCursorLeftBlock( event.ShiftDown() ); else if ( keyMods == ALT_DOWN ) SetColWidth(GetGridCursorCol(), GetColWidth(GetGridCursorCol())-5); else MoveCursorLeft( event.ShiftDown() ); break; } case WXK_RIGHT: { if (!ContainsGridCell(GetGridCursorCell())) break; if ( event.ControlDown() ) MoveCursorRightBlock( event.ShiftDown() ); else if ( keyMods == ALT_DOWN ) SetColWidth(GetGridCursorCol(), GetColWidth(GetGridCursorCol())+5); else MoveCursorRight( event.ShiftDown() ); break; } case WXK_PRIOR: { MoveCursorUpPage( event.ShiftDown() ); break; } case WXK_NEXT: { MoveCursorDownPage( event.ShiftDown() ); break; } case WXK_HOME : { if ( event.ControlDown() ) { wxSheetCoords coords( 0, 0 ); if ( ContainsGridCell(coords) ) { wxSheetCoords lastCoords(GetGridCursorCell()); MakeCellVisible( coords ); SetGridCursorCell( coords ); if ( event.ShiftDown() && ContainsGridCell(lastCoords) ) { m_keySelecting = true; if ( !ContainsGridCell(GetSelectingAnchor()) ) SetSelectingAnchor(lastCoords); HighlightSelectingBlock(GetSelectingAnchor(), GetGridCursorCell()); } } } else event.Skip(); break; } case WXK_END: { if ( event.ControlDown() ) { wxSheetCoords coords(GetNumberRows()-1, GetNumberCols()-1); if ( ContainsGridCell(coords) ) { wxSheetCoords lastCoords(GetGridCursorCell()); MakeCellVisible( coords ); SetGridCursorCell( coords ); if ( event.ShiftDown() && ContainsGridCell(lastCoords) ) { m_keySelecting = true; if ( !ContainsGridCell(GetSelectingAnchor()) ) SetSelectingAnchor(lastCoords); HighlightSelectingBlock(GetSelectingAnchor(), GetGridCursorCell()); } } } else event.Skip(); break; } default : event.Skip(); } m_inOnKeyDown = false; } void wxSheet::StopMouseTimer() { if (m_mouseTimer) { if (m_mouseTimer->IsRunning()) m_mouseTimer->Stop(); delete m_mouseTimer; m_mouseTimer = NULL; } } void wxSheet::StartMouseTimer() { if (!m_mouseTimer) m_mouseTimer = new wxTimer(this, ID_MOUSE_DRAG_TIMER); if (!m_mouseTimer->IsRunning()) m_mouseTimer->Start(100, true); // one shot } void wxSheet::OnMouseTimer( wxTimerEvent &WXUNUSED(event) ) { // the window must be captured and thus m_mousePos is for that window wxWindow *win = GetCaptureWindow(); if (!win || (GetNumberCols() < 1) || (GetNumberRows() < 1)) { StopMouseTimer(); return; } wxSize clientSize(win->GetClientSize()); int dx = (m_mousePos.x < 0) ? -1 : ((m_mousePos.x > clientSize.x) ? 1 : 0); int dy = (m_mousePos.y < 0) ? -1 : ((m_mousePos.y > clientSize.y) ? 1 : 0); if (win == m_rowLabelWin) dx = 0; else if (win == m_colLabelWin) dy = 0; if ((dx == 0) && (dy == 0)) // mouse is back in the window { StopMouseTimer(); return; } wxSize cSize = m_gridWin->GetClientSize(); SetGridOrigin( m_gridOrigin.x + dx*SHEET_SCROLL_LINE_X, m_gridOrigin.y + dy*SHEET_SCROLL_LINE_Y, true, true ); // send fake mouse event to process, assume left down and we're dragging wxMouseEvent mEvt(wxEVT_MOTION); mEvt.SetEventObject(win); mEvt.m_leftDown = true; mEvt.m_x = m_mousePos.x; mEvt.m_y = m_mousePos.y; win->ProcessEvent(mEvt); StartMouseTimer(); } bool wxSheet::DoEndDragResizeRowCol() { if ( m_dragLastPos < 0 ) return false; if (IsCellEditControlCreated()) DisableCellEditControl(true); // erase the last line and resize the row/col DrawRowColResizingMarker(); if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW)) { int height = m_dragLastPos - GetRowTop(m_dragRowOrCol); const int minHeight = GetMinimalRowHeight(m_dragRowOrCol); if (minHeight > height) height = minHeight; if (height != GetRowHeight(m_dragRowOrCol)) { SetRowHeight( m_dragRowOrCol, height ); return true; } } else if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL)) { int width = m_dragLastPos - GetColLeft(m_dragRowOrCol); const int minWidth = GetMinimalColWidth(m_dragRowOrCol); if (minWidth > width) width = minWidth; if (width != GetColWidth(m_dragRowOrCol)) { SetColWidth( m_dragRowOrCol, width ); return true; } } return false; } void wxSheet::SetMouseCursorMode(MouseCursorMode mode, wxWindow *win) { wxCHECK_RET(win, wxT("Invalid window")); m_mouseCursorMode = mode; if (win == m_gridWin) { if (m_gridWin->m_mouseCursor == mode) return; m_gridWin->m_mouseCursor = mode; } else if (win == m_cornerLabelWin) { if (m_cornerLabelWin->m_mouseCursor == mode) return; m_cornerLabelWin->m_mouseCursor = mode; } else if (win == m_rowLabelWin) { if (m_rowLabelWin->m_mouseCursor == mode) return; m_rowLabelWin->m_mouseCursor = mode; } else if (win == m_colLabelWin) { if (m_colLabelWin->m_mouseCursor == mode) return; m_colLabelWin->m_mouseCursor = mode; } else if (win == this) { if (m_mouseCursor == mode) return; m_mouseCursor = mode; } switch ( mode ) { case WXSHEET_CURSOR_RESIZE_ROW : case WXSHEET_CURSOR_SPLIT_VERTICAL : { win->SetCursor( GetSheetRefData()->m_rowResizeCursor ); break; } case WXSHEET_CURSOR_RESIZE_COL : case WXSHEET_CURSOR_SPLIT_HORIZONTAL : { win->SetCursor( GetSheetRefData()->m_colResizeCursor ); break; } default: win->SetCursor( *wxSTANDARD_CURSOR ); } } void wxSheet::SetCaptureWindow(wxWindow *win) { if (m_winCapture && (m_winCapture != win) && m_winCapture->HasCapture()) m_winCapture->ReleaseMouse(); m_winCapture = win; if (m_winCapture && (!m_winCapture->HasCapture())) m_winCapture->CaptureMouse(); } wxWindow* wxSheet::GetWindowForCoords( const wxSheetCoords& coords ) const { if (IsGridCell(coords)) return m_gridWin; if (IsRowLabelCell(coords)) return m_rowLabelWin; if (IsColLabelCell(coords)) return m_colLabelWin; if (IsCornerLabelCell(coords)) return m_cornerLabelWin; wxFAIL_MSG(wxString::Format(wxT("Unable to get window for coords (%d,%d)"), coords.m_row, coords.m_col)); return NULL; } // ----- event handlers // Generate a grid event based on a mouse/key event and // return the result of ProcessEvent() int wxSheet::SendEvent( const wxEventType type, const wxSheetCoords& coords, wxEvent *mouseOrKeyEvt ) { //wxMouseEvent *mouseEvt = wxDynamicCast(mouseOrKeyEvt, wxMouseEvent); //wxPoint pos = mouseEvt ? mouseEvt->GetPosition() : wxPoint(-1, -1); //pos += wxPoint(GetRowLabelWidth(), GetColLabelHeight()); wxSheetEvent sheetEvt(GetId(), type, this, coords, wxPoint(-1,-1), IsSelecting()); sheetEvt.SetKeysDownMousePos(mouseOrKeyEvt); return DoSendEvent(&sheetEvt); } int wxSheet::SendRangeEvent( const wxEventType type, const wxSheetBlock& block, bool selecting, bool add, wxEvent *mouseOrKeyEvt ) { if ( type == wxEVT_SHEET_RANGE_SELECTED ) { wxSheetRangeSelectEvent sheetEvt(GetId(), type, this, block, selecting, add ); sheetEvt.SetKeysDownMousePos(mouseOrKeyEvt); sheetEvt.m_coords = GetGridCursorCell(); return DoSendEvent(&sheetEvt); } return 0; } int wxSheet::DoSendEvent(wxSheetEvent *event) { wxCHECK_MSG(event, 0, wxT("invalid event in wxSheet::DoSendEvent")); bool claimed = GetEventHandler()->ProcessEvent(*event); bool vetoed = !event->IsAllowed(); // A Veto'd event may not be claimed, test this first if (vetoed) return EVT_VETOED; return claimed ? EVT_CLAIMED : EVT_SKIPPED; } void wxSheet::HighlightSelectingBlock( const wxSheetBlock &block_ ) { wxSheetBlock block(block_.GetAligned()); if (block == GetSelectingBlock()) return; if ( GetSelection() && !block.IsEmpty() ) { // make sure block that's selected goes full width/height if ( HasSelectionMode(wxSHEET_SelectRows) ) { block.SetLeft(0); block.SetWidth(GetNumberCols() - 1); } else if ( HasSelectionMode(wxSHEET_SelectCols) ) { block.SetTop(0); block.SetHeight(GetNumberRows() - 1); } } wxSheetBlock oldSelBlock(GetSelectingBlock()); SetSelectingBlock(block.IsEmpty() ? wxNullSheetBlock : block); // First the case that we selected a completely new area if ( oldSelBlock.IsEmpty() ) { RefreshGridCellBlock(block); } // New selection is empty, erase old one else if ( block.IsEmpty() ) { RefreshGridCellBlock(oldSelBlock); } // two selections don't intersect at all, not expected, but ok I guess else if ( !block.Intersects(oldSelBlock) ) { RefreshGridCellBlock(block.Union(oldSelBlock)); } // Now handle changing an existing selection area. else if ( oldSelBlock != block ) { // FIXME - this is not great wxSheetBlock changed[8]; wxSheetBlock bounds; oldSelBlock.Delete(block, changed[0], changed[1], changed[2], changed[3]); block.Delete(oldSelBlock, changed[4], changed[5], changed[6], changed[7]); { for (int n=0; n<8; n++) bounds = bounds.ExpandUnion(changed[n]); RefreshGridCellBlock(bounds); } } } // ------ functions to get/send data (see also public functions) bool wxSheet::GetModelValues() { // Hide the editor, so it won't hide a changed value. if (IsCellEditControlShown()) HideCellEditControl(); if ( GetTable() ) { RefreshGridWindow(); // all we need to do is repaint the grid return true; } return false; } bool wxSheet::SetModelValues() { // Disable the editor, so it won't hide a changed value. // FIXME: Do we also want to save the current value of the editor first? yes? if (IsCellEditControlCreated()) DisableCellEditControl(true); if ( GetTable() ) { wxSheetCoords coords; int numRows = GetNumberRows(); int numCols = GetNumberCols(); for ( coords.m_row = 0; coords.m_row < numRows; coords.m_row++ ) { for ( coords.m_col = 0; coords.m_col < numCols; coords.m_col++ ) GetTable()->SetValue( coords, GetCellValue(coords) ); } return true; } return false; } // ---------------------------------------------------------------------------- // Attrbitute cache void wxSheet::ClearAttrCache() { if ( m_cacheAttrType != -1 ) { m_cacheAttr.Destroy(); m_cacheAttrCoords = wxNullSheetCoords; m_cacheAttrType = -1; } } void wxSheet::CacheAttr(const wxSheetCoords& coords, const wxSheetCellAttr &attr, wxSheetAttr_Type type ) const { if ( attr.Ok() ) { wxSheet *self = (wxSheet *)this; // const_cast self->m_cacheAttr = attr; self->m_cacheAttrCoords = coords; self->m_cacheAttrType = type; } } bool wxSheet::LookupAttr(const wxSheetCoords& coords, wxSheetAttr_Type type, wxSheetCellAttr &attr ) const { if ( (type == m_cacheAttrType) && (coords == m_cacheAttrCoords) ) { attr = m_cacheAttr; #ifdef DEBUG_ATTR_CACHE gs_nAttrCacheHits++; #endif return true; } #ifdef DEBUG_ATTR_CACHE gs_nAttrCacheMisses++; #endif return false; } // ---------------------------------------------------------------------------- // Gui Sizing functions void wxSheet::CalcWindowSizes(bool adjustScrollBars) { if (!m_gridWin || m_resizing) return; if (adjustScrollBars) AdjustScrollbars(false); m_resizing = true; int cw, ch; GetClientSize( &cw, &ch ); wxRect rect; const int rowLabelWidth = GetRowLabelWidth(); const int colLabelHeight = GetColLabelHeight(); int sb_width = m_vertScrollBar->GetSize().x; int sb_height = m_horizScrollBar->GetSize().y; bool horiz_sb = m_horizScrollBar->IsShown(); bool vert_sb = m_vertScrollBar->IsShown(); if (horiz_sb) ch -= sb_width; if (vert_sb ) cw -= sb_width; bool horiz_splitter = horiz_sb && m_enable_split_horiz; bool vert_splitter = vert_sb && m_enable_split_vert; if ( horiz_sb ) { rect = wxRect(0, ch, cw, sb_height); if (horiz_splitter) { rect.width -= SPLIT_BUTTON_WIDTH; m_horizSplitRect = wxRect(rect.GetRight(), rect.GetTop(), SPLIT_BUTTON_WIDTH, rect.GetHeight()); } else m_horizSplitRect = wxRect(0,0,0,0); if (rect != m_horizScrollBar->GetRect()) m_horizScrollBar->SetSize( rect ); } if ( vert_sb ) { rect = wxRect(cw, 0, sb_width, ch); if (vert_splitter) { rect.height -= SPLIT_BUTTON_WIDTH; m_vertSplitRect = wxRect(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), SPLIT_BUTTON_WIDTH); rect.y += SPLIT_BUTTON_WIDTH; } else m_vertSplitRect = wxRect(0,0,0,0); if (rect != m_vertScrollBar->GetRect()) m_vertScrollBar->SetSize( rect ); } if ( m_cornerLabelWin->IsShown() ) { rect = wxRect(0, 0, rowLabelWidth, colLabelHeight); if (rect != m_cornerLabelWin->GetRect()) m_cornerLabelWin->SetSize( rect ); } if ( m_colLabelWin->IsShown() ) { rect = wxRect(rowLabelWidth, 0, cw-rowLabelWidth, colLabelHeight); if (rect != m_colLabelWin->GetRect()) m_colLabelWin->SetSize( rect ); } if ( m_rowLabelWin->IsShown() ) { rect = wxRect(0, colLabelHeight, rowLabelWidth, ch-colLabelHeight); if (rect != m_rowLabelWin->GetRect()) m_rowLabelWin->SetSize( rect ); } if ( m_gridWin->IsShown() ) { rect = wxRect(rowLabelWidth, colLabelHeight, cw-rowLabelWidth, ch-colLabelHeight); if (rect != m_gridWin->GetRect()) m_gridWin->SetSize( rect ); //PRINT_RECT("Set grid rect ", rect); //PRINT_RECT("Get grid rect ", wxRect(wxPoint(0,0), m_gridWin->GetSize())); } m_resizing = false; #ifdef __WXMSW__ // MSW at least needs a little help making sure that the corner and // the splitter rects get painted wxClientDC dc(this); PaintSheetWindow(dc, wxRect(0, 0, cw, ch)); #endif // __WXMSW__ } void wxSheet::OnSize(wxSizeEvent& event) { //PRINT_RECT(wxT("SheetRect"), GetRect()); CalcWindowSizes(true); SetGridOrigin(m_gridOrigin.x, m_gridOrigin.y, true, true); SetEqualColWidths(GetSheetRefData()->m_equal_col_widths); event.Skip(); } wxSize wxSheet::DoGetBestSize() const { wxSize displaySize(wxGetClientDisplayRect().GetSize()); wxSize size(GetGridVirtualSize(true)); size.x += GetRowLabelWidth(); size.y += GetColLabelHeight(); if ( size.x > displaySize.x/2 ) size.x = displaySize.x/2; if ( size.y > displaySize.y/2 ) size.y = displaySize.y/2; // NOTE: This size should be cached, but first we need to add calls to // InvalidateBestSize everywhere that could change the results of this // calculation. // CacheBestSize(size); return size; } int wxSheet::GetKeyModifiers(wxEvent *mouseOrKeyEvent) const { // In GTK meta is the numLock key int mods = NO_MODIFIERS; wxMouseEvent *mouseEvt = wxDynamicCast(mouseOrKeyEvent, wxMouseEvent); if (mouseEvt) { if (mouseEvt->ControlDown()) mods |= CTRL_DOWN; if (mouseEvt->ShiftDown()) mods |= SHIFT_DOWN; if (mouseEvt->AltDown()) mods |= ALT_DOWN; //if (mouseEvt->MetaDown()) // meta is numlock in GTK // mods |= META_DOWN; } else { wxKeyEvent *keyEvt = wxDynamicCast(mouseOrKeyEvent, wxKeyEvent); if (keyEvt) { if (keyEvt->ControlDown()) mods |= CTRL_DOWN; if (keyEvt->ShiftDown()) mods |= SHIFT_DOWN; if (keyEvt->AltDown()) mods |= ALT_DOWN; //if (keyEvt->MetaDown()) // mods |= META_DOWN; } } //wxPrintf("Mods c%d s%d a%d m%d, %d\n", CTRL_DOWN, SHIFT_DOWN, ALT_DOWN, META_DOWN, mods); return mods; } // ---------------------------------------------------------------------------- // events // ---------------------------------------------------------------------------- DEFINE_EVENT_TYPE(wxEVT_SHEET_VIEW_CHANGED) DEFINE_EVENT_TYPE(wxEVT_SHEET_SELECTING_CELL) DEFINE_EVENT_TYPE(wxEVT_SHEET_SELECTED_CELL) DEFINE_EVENT_TYPE(wxEVT_SHEET_CELL_LEFT_DOWN) DEFINE_EVENT_TYPE(wxEVT_SHEET_CELL_RIGHT_DOWN) DEFINE_EVENT_TYPE(wxEVT_SHEET_CELL_LEFT_UP) DEFINE_EVENT_TYPE(wxEVT_SHEET_CELL_RIGHT_UP) DEFINE_EVENT_TYPE(wxEVT_SHEET_CELL_LEFT_DCLICK) DEFINE_EVENT_TYPE(wxEVT_SHEET_CELL_RIGHT_DCLICK) DEFINE_EVENT_TYPE(wxEVT_SHEET_LABEL_LEFT_DOWN) DEFINE_EVENT_TYPE(wxEVT_SHEET_LABEL_RIGHT_DOWN) DEFINE_EVENT_TYPE(wxEVT_SHEET_LABEL_LEFT_UP) DEFINE_EVENT_TYPE(wxEVT_SHEET_LABEL_RIGHT_UP) DEFINE_EVENT_TYPE(wxEVT_SHEET_LABEL_LEFT_DCLICK) DEFINE_EVENT_TYPE(wxEVT_SHEET_LABEL_RIGHT_DCLICK) DEFINE_EVENT_TYPE(wxEVT_SHEET_ROW_SIZE) DEFINE_EVENT_TYPE(wxEVT_SHEET_COL_SIZE) DEFINE_EVENT_TYPE(wxEVT_SHEET_RANGE_SELECTING) DEFINE_EVENT_TYPE(wxEVT_SHEET_RANGE_SELECTED) DEFINE_EVENT_TYPE(wxEVT_SHEET_CELL_VALUE_CHANGING) DEFINE_EVENT_TYPE(wxEVT_SHEET_CELL_VALUE_CHANGED) DEFINE_EVENT_TYPE(wxEVT_SHEET_EDITOR_ENABLED) DEFINE_EVENT_TYPE(wxEVT_SHEET_EDITOR_DISABLED) DEFINE_EVENT_TYPE(wxEVT_SHEET_EDITOR_CREATED) // ---------------------------------------------------------------------------- // wxSheetEvent // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS( wxSheetEvent, wxNotifyEvent ) wxSheetEvent::wxSheetEvent(int id, wxEventType type, wxObject* obj, const wxSheetCoords& coords, const wxPoint &pos, bool sel ) : wxNotifyEvent(type, id), m_coords(coords), m_pos(pos), m_selecting(sel), m_control(false), m_shift(false), m_alt(false), m_meta(false) { SetEventObject(obj); } void wxSheetEvent::SetKeysDownMousePos(wxEvent *mouseOrKeyEvent) { wxMouseEvent *mouseEvt = wxDynamicCast(mouseOrKeyEvent, wxMouseEvent); if (mouseEvt) { m_control = mouseEvt->ControlDown(); m_shift = mouseEvt->ShiftDown(); m_alt = mouseEvt->AltDown(); m_meta = mouseEvt->MetaDown(); m_pos = mouseEvt->GetPosition(); } else { wxKeyEvent *keyEvt = wxDynamicCast(mouseOrKeyEvent, wxKeyEvent); if (keyEvt) { m_control = keyEvt->ControlDown(); m_shift = keyEvt->ShiftDown(); m_alt = keyEvt->AltDown(); m_meta = keyEvt->MetaDown(); m_pos = keyEvt->GetPosition(); } else return; // neither mouse nor key event } // FIXME - do I really want to scroll the position? or leave it as is // we've set the position from the event, now scroll it wxSheet *sheet = wxDynamicCast(GetEventObject(), wxSheet); wxWindow *win = wxDynamicCast(mouseOrKeyEvent->GetEventObject(), wxWindow); if (sheet && win) { if ( win == sheet->GetGridWindow()) m_pos = sheet->CalcUnscrolledPosition(m_pos); else if (win == sheet->GetRowLabelWindow()) sheet->CalcUnscrolledPosition(0, m_pos.y, NULL, &m_pos.y); else if (win == sheet->GetColLabelWindow()) sheet->CalcUnscrolledPosition(m_pos.x, 0, &m_pos.x, NULL); } } // ---------------------------------------------------------------------------- // wxSheetRangeSelectEvent // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS( wxSheetRangeSelectEvent, wxSheetEvent ) wxSheetRangeSelectEvent::wxSheetRangeSelectEvent(int id, wxEventType type, wxObject* obj, const wxSheetBlock& block, bool sel, bool add ) : wxSheetEvent(id, type, obj, wxNullSheetCoords, wxPoint(-1, -1), sel), m_block(block), m_add(add) { } // ---------------------------------------------------------------------------- // wxSheetEditorCreatedEvent // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxSheetEditorCreatedEvent, wxCommandEvent) wxSheetEditorCreatedEvent::wxSheetEditorCreatedEvent(int id, wxEventType type, wxObject* obj, const wxSheetCoords& coords, wxWindow* ctrl) : wxCommandEvent(type, id), m_coords(coords), m_ctrl(ctrl) { SetEventObject(obj); } // Notes: // Regex to CSV // http://dotnetjunkies.com/WebLog/chris.taylor/archive/2004/04/09/11039.aspx // ((?[^\",\\r\\n]+)|\"(?([^\"]|\"\")+)\")(,|(?\\r\\n|\\n|$)) // // http://www.codeguru.com/Cpp/Cpp/string/net/article.php/c8153/ // String* pattern = S",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))" /* http://www.xbeat.net/vbspeed/c_ParseCSV.php Private Sub Class_Initialize() Set regEx = New VBScript_RegExp_55.RegExp regEx.Global = True regEx.IgnoreCase = True regEx.Pattern = "(\s*""[^""]*""\s*,)|(\s*[^,]*\s*,)" 'The magic... End Sub Friend Function ParseCSV02(sExpr$, arVals$()) As Long Dim lCnt& Set mc = regEx.Execute(sExpr & ",") ReDim arVals(mc.Count - 1) As String For Each m In mc arVals(lCnt) = Trim$(Left$(m.Value, m.Length - 1)) If Left$(arVals(lCnt), 1) = """" And Right$(arVals(lCnt), 1) = """" Then arVals(lCnt) = Mid$(arVals(lCnt), 2, Len(arVals(lCnt)) - 2) End If lCnt = lCnt + 1 Next m ParseCSV02 = mc.Count End Function */ #include "wx/regex.h" class wxCSV_IO { public : wxCSV_IO( bool t=false ); wxArrayString ParseLine(const wxString& line); bool Test(); wxRegEx m_regex; }; wxCSV_IO::wxCSV_IO(bool t) { // "(\s*""[^""]*""\s*,)|(\s*[^,]*\s*,)" 'The magic... // m_regex.Compile(wxT("(\\s*\"[^\"]*\"\\s*,)|(\\s*[^,]*\\s*,)"), wxRE_ICASE); m_regex.Compile(wxT("(\\s*\"[^\"]*\"\\s*,)|(\\s*[^,]*\\s*,)"), wxRE_ICASE); //m_regex.Compile(wxT(",(?=([^\"]*"[^\"]*\")*(?![^\"]*\"))"), wxRE_ICASE); //m_regex.Compile(wxT(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"), wxRE_ICASE); if (t) Test(); } wxArrayString wxCSV_IO::ParseLine(const wxString& line_) { wxArrayString values; wxString line(line_ + wxT(",")); // add trailing ',' for "a,b" case // See if there is a match at all while ( m_regex.Matches(line) ) { // Get the first match (BUG? can't use GetMatch(line, n)) wxString val(m_regex.GetMatch(line, 0)); size_t len = val.Length(); if ((len > 0u) && val.Last() == wxT(',')) // GetMatch returns "val," val = val.Mid(0, len-1); //wxPrintf(wxT("VALUE '")+val+wxT("' LINE '")+line+wxT("'\n")); line = line.Mid(len); // remove the value from the line val = val.Strip(wxString::both); // strip blank spaces from value // should've quoted ie. " a a " len = val.Length(); // remove the leading and trailing quotes if ((len > 1u) && (val.GetChar(0) == wxT('\"')) && (val.GetChar(len-1) == wxT('\"'))) val = val.AfterFirst(wxT('\"')).BeforeLast(wxT('\"')); values.Add(val); } return values; } wxString Joint(const wxArrayString& a) { if (a.GetCount() == 0u) return wxEmptyString; wxString s = wxT("'")+ a[0] + wxT("'\t "); for (size_t n = 1u; n < a.GetCount(); n++) s += wxT("'")+ a[n] + wxT("'\t "); return s; } void CSV_TEST(const wxString& instr, const wxArrayString& ans, const wxArrayString &res) { wxString msg(wxT("'") + instr + wxT("'\t ") + Joint(ans) + wxT(" ** \t ") + Joint(res)); if ( ans.GetCount() != res.GetCount() ) wxPrintf(wxT("COUNT MISMATCH ERROR! \n")); for (size_t n = 0; n < wxMin(ans.GetCount(), res.GetCount()); n++) if (ans[n] != res[n]) wxPrintf(wxT("Error in item %u\n"), n); wxPrintf(msg + wxT("\n")); } #define CSVT1(str, a1) { wxArrayString ar; ar.Add(wxT(a1)); CSV_TEST(wxT(str), ar, ParseLine(wxT(str))); } #define CSVT2(str, a1, a2) { wxArrayString ar; ar.Add(wxT(a1)); ar.Add(wxT(a2)); CSV_TEST(wxT(str), ar, ParseLine(wxT(str))); } #define CSVT3(str, a1, a2, a3) { wxArrayString ar; ar.Add(wxT(a1)); ar.Add(wxT(a2)); ar.Add(wxT(a3)); CSV_TEST(wxT(str), ar, ParseLine(wxT(str))); } bool wxCSV_IO::Test() { CSVT3("a,b,c", "a", "b", "c") CSVT3("\"a\",b,c", "a", "b", "c") CSVT3("'a',b,c", "'a'", "b", "c") CSVT3(" a , b , c ", "a", "b", "c") CSVT2("aa,bb;cc", "aa", "bb;cc") CSVT1("", "") CSVT1("a", "a") CSVT3(",b,", "", "b", "") CSVT3(",,c", "", "", "c") CSVT3(",,", "", "", "") CSVT2("\"\",b", "", "b") CSVT2("\" \",b", " ", "b") CSVT1("\"a,b\"", "a,b") CSVT2("\"a,b\",c", "a,b", "c") CSVT2("\" a , b \", c", " a , b ", "c") CSVT2("a b,c", "a b", "c") CSVT2("a\"b,c", "a\"b", "c") CSVT2("\"a\"\"b\",c", "a\"b", "c") CSVT2("a\"\"b,c", "a\"\"b", "c") // BROKEN CSVT3("a,b\",c", "a", "b\"", "c") CSVT3("a,b\"\",c", "a", "b\"\"", "c") CSVT3("a,\"B: \"\"Hi, I'm B\"\"\",c", "a", "B: \"Hi, I'm B\"", "c") return true; } //wxCSV_IO csvTest(true); gambit-0.2010.09.01/src/labenski/src/sheetatr.cpp0000644000076500007650000007054411350032206016133 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetatr.cpp // Purpose: wxSheet and related classes // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) // Modified by: John Labenski, Robin Dunn, Vadim Zeitlin // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski, Michael Bedward (mbedward@ozemail.com.au) // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "sheetatr.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #include "wx/sheet/sheetatr.h" #include "wx/sheet/sheet.h" #ifndef WX_PRECOMP #endif // WX_PRECOMP #define PRINT_BLOCK(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); #define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- const wxSheetCellAttr wxNullSheetCellAttr(false); #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArraySheetCellAttr) DEFINE_PAIREDSHEETCOORDS_DATA_ARRAYS(wxSheetCellAttr, wxPairArraySheetCoordsCellAttr) DEFINE_PAIRED_INT_DATA_ARRAYS(wxSheetCellAttr, wxPairArrayIntSheetCellAttr) // ---------------------------------------------------------------------------- // wxSheetCellAttrRefData // ---------------------------------------------------------------------------- #define M_CELLATTRDATA ((wxSheetCellAttrRefData*)m_refData) wxSheetCellAttrRefData::wxSheetCellAttrRefData() : wxObjectRefData(), // other m_attrTypes unset values are 0 m_attrTypes(wxSHEET_AttrCell|wxSHEET_AttrAlignUnset), m_renderer(NULL), m_editor(NULL), m_defaultAttr(NULL) { } wxSheetCellAttrRefData::wxSheetCellAttrRefData( const wxSheetCellAttrRefData& data ) : wxObjectRefData(), m_foreColour(data.m_foreColour), m_backColour(data.m_backColour), m_font(data.m_font), m_attrTypes(data.m_attrTypes) { m_renderer = !data.m_renderer ? NULL : new wxSheetCellRenderer(*data.m_renderer); m_editor = !data.m_editor ? NULL : new wxSheetCellEditor(*data.m_editor); m_defaultAttr = !data.m_defaultAttr ? NULL : new wxSheetCellAttr(*data.m_defaultAttr); } wxSheetCellAttrRefData::~wxSheetCellAttrRefData() { delete m_renderer; delete m_editor; delete m_defaultAttr; } // ---------------------------------------------------------------------------- // wxSheetCellAttr // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxSheetCellAttr, wxObject) wxSheetCellAttr::wxSheetCellAttr(bool create) : wxObject() { if (create) m_refData = new wxSheetCellAttrRefData; } bool wxSheetCellAttr::Create() { UnRef(); m_refData = new wxSheetCellAttrRefData; return m_refData != NULL; } wxObjectRefData *wxSheetCellAttr::CreateRefData() const { return new wxSheetCellAttrRefData; } wxObjectRefData *wxSheetCellAttr::CloneRefData(const wxObjectRefData *data) const { wxCHECK_MSG(data, new wxSheetCellAttrRefData, wxT("Invalid data for CloneRefData")); return new wxSheetCellAttrRefData(*(const wxSheetCellAttrRefData *)data); } bool wxSheetCellAttr::Copy(const wxSheetCellAttr& other) { wxCHECK_MSG(other.Ok(), false, wxT("Attr to copy from is not created")); if (!Create()) return false; M_CELLATTRDATA->m_foreColour = ((wxSheetCellAttrRefData*)other.GetRefData())->m_foreColour; M_CELLATTRDATA->m_backColour = ((wxSheetCellAttrRefData*)other.GetRefData())->m_backColour; M_CELLATTRDATA->m_font = ((wxSheetCellAttrRefData*)other.GetRefData())->m_font; M_CELLATTRDATA->m_attrTypes = ((wxSheetCellAttrRefData*)other.GetRefData())->m_attrTypes; if (other.HasEditor()) SetEditor(((wxSheetCellAttrRefData*)other.m_refData)->m_editor->Clone()); if (other.HasRenderer()) SetRenderer(((wxSheetCellAttrRefData*)other.m_refData)->m_renderer->Clone()); SetDefaultAttr(other.GetDefaultAttr()); return true; } bool wxSheetCellAttr::UpdateWith(const wxSheetCellAttr& other) { wxCHECK_MSG(Ok() && other.Ok(), false, wxT("this or Attr to UpdateWith from is not created")); if ( other.HasForegoundColour() ) SetForegroundColour(other.GetForegroundColour()); if ( other.HasBackgroundColour() ) SetBackgroundColour(other.GetBackgroundColour()); if ( other.HasFont() ) SetFont(other.GetFont()); if ( other.HasAlignment() ) SetAlignment(other.GetAlignment()); if ( other.HasOrientation() ) SetOrientation(other.GetOrientation()); if ( other.HasLevel() ) SetLevel(other.GetLevel()); if ( other.HasReadWriteMode() ) SetReadOnly(other.GetReadOnly()); if ( other.HasOverflowMode() ) SetOverflow(other.GetOverflow()); if ( other.HasOverflowMarkerMode() ) SetOverflowMarker(other.GetOverflowMarker()); if ( other.HasShowEditorMode() ) SetShowEditor(other.GetShowEditor()); // Directly access m_renderer/m_editor as GetRender/Editor may return different one // Maybe add support for merge of Render and Editor? if ( other.HasRenderer() ) SetRenderer(((wxSheetCellAttrRefData*)other.m_refData)->m_renderer->Clone()); if ( other.HasEditor() ) SetEditor(((wxSheetCellAttrRefData*)other.m_refData)->m_editor->Clone()); if ( other.HasDefaultAttr() ) SetDefaultAttr(other.GetDefaultAttr()); return true; } bool wxSheetCellAttr::MergeWith(const wxSheetCellAttr &other) { wxCHECK_MSG(Ok() && other.Ok(), false, wxT("this or Attr to MergeWith from is not created")); if ( !HasForegoundColour() && other.HasForegoundColour() ) SetForegroundColour(other.GetForegroundColour()); if ( !HasBackgroundColour() && other.HasBackgroundColour() ) SetBackgroundColour(other.GetBackgroundColour()); if ( !HasFont() && other.HasFont() ) SetFont(other.GetFont()); if ( !HasAlignment() && other.HasAlignment() ) SetAlignment(other.GetAlignment()); if ( !HasOrientation() && other.HasOrientation() ) SetOrientation(other.GetOrientation()); if ( !HasLevel() && other.HasLevel() ) SetLevel(other.GetLevel()); if ( !HasReadWriteMode() && other.HasReadWriteMode() ) SetReadOnly(other.GetReadOnly()); if ( !HasOverflowMode() && other.HasOverflowMode() ) SetOverflow(other.GetOverflow()); if ( !HasOverflowMarkerMode() && other.HasOverflowMarkerMode() ) SetOverflowMarker(other.GetOverflowMarker()); if ( !HasShowEditorMode() && other.HasShowEditorMode() ) SetShowEditor(other.GetShowEditor()); // Directly access m_renderer/m_editor as GetRender/Editor may return different one // Maybe add support for merge of Render and Editor? if ( !HasRenderer() && other.HasRenderer() ) SetRenderer(((wxSheetCellAttrRefData*)other.m_refData)->m_renderer->Clone()); if ( !HasEditor() && other.HasEditor() ) SetEditor(((wxSheetCellAttrRefData*)other.m_refData)->m_editor->Clone()); if ( !HasDefaultAttr() && other.HasDefaultAttr() ) SetDefaultAttr(other.GetDefaultAttr()); return true; } void wxSheetCellAttr::SetForegroundColour(const wxColour& foreColour) { wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); M_CELLATTRDATA->m_foreColour = foreColour; } void wxSheetCellAttr::SetBackgroundColour(const wxColour& backColour) { wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); M_CELLATTRDATA->m_backColour = backColour; } void wxSheetCellAttr::SetFont(const wxFont& font) { wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); M_CELLATTRDATA->m_font = font; } void wxSheetCellAttr::SetAlignment(int align) { SetType(align, wxSHEET_AttrAlignType_Mask); } void wxSheetCellAttr::SetAlignment(int horizAlign, int vertAlign) { SetType(wxSheet::SetAlignment(M_CELLATTRDATA->m_attrTypes, horizAlign, vertAlign), wxSHEET_AttrAlignType_Mask); } void wxSheetCellAttr::SetOrientation(int orientation) { SetType(orientation, wxSHEET_AttrOrientType_Mask); } void wxSheetCellAttr::SetLevel(wxSheetAttrLevel_Type level) { SetType(level, wxSHEET_AttrLevelType_Mask); } void wxSheetCellAttr::SetOverflow(bool allow) { SetType(allow ? wxSHEET_AttrOverflow : wxSHEET_AttrOverflowNot, wxSHEET_AttrOverflowType_Mask); } void wxSheetCellAttr::SetOverflowMarker(bool draw_marker) { SetType(draw_marker ? wxSHEET_AttrOverflowMarker : wxSHEET_AttrOverflowMarkerNot, wxSHEET_AttrOverflowMarkerType_Mask); } void wxSheetCellAttr::SetShowEditor(bool show_editor) { SetType(show_editor ? wxSHEET_AttrShowEditor : wxSHEET_AttrShowEditorNot, wxSHEET_AttrShowEditorType_Mask); } void wxSheetCellAttr::SetReadOnly(bool isReadOnly) { SetType(isReadOnly ? wxSHEET_AttrReadOnly : wxSHEET_AttrReadWrite, wxSHEET_AttrReadType_Mask); } void wxSheetCellAttr::SetRenderer(const wxSheetCellRenderer& renderer) { wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); if (M_CELLATTRDATA->m_renderer) { delete M_CELLATTRDATA->m_renderer; M_CELLATTRDATA->m_renderer = NULL; } if (renderer.Ok()) M_CELLATTRDATA->m_renderer = new wxSheetCellRenderer(renderer); } void wxSheetCellAttr::SetEditor(const wxSheetCellEditor& editor) { wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); if (M_CELLATTRDATA->m_editor) { delete M_CELLATTRDATA->m_editor; M_CELLATTRDATA->m_editor = NULL; } if (editor.Ok()) M_CELLATTRDATA->m_editor = new wxSheetCellEditor(editor); } void wxSheetCellAttr::SetKind(wxSheetAttr_Type kind) { SetType(kind, wxSHEET_AttrAny); } bool wxSheetCellAttr::HasForegoundColour() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); return M_CELLATTRDATA->m_foreColour.Ok(); } bool wxSheetCellAttr::HasBackgroundColour() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); return M_CELLATTRDATA->m_backColour.Ok(); } bool wxSheetCellAttr::HasFont() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); return M_CELLATTRDATA->m_font.Ok(); } bool wxSheetCellAttr::HasAlignment() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); // note: Left and Top is 0 return (((M_CELLATTRDATA->m_attrTypes) & wxSHEET_AttrAlignHorizUnset) == 0) && (((M_CELLATTRDATA->m_attrTypes) & wxSHEET_AttrAlignVertUnset ) == 0); } bool wxSheetCellAttr::HasOrientation() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); return ((M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOrientHoriz) != 0) || ((M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOrientVert ) != 0); } bool wxSheetCellAttr::HasLevel() const { return HasType(wxSHEET_AttrLevelType_Mask); } bool wxSheetCellAttr::HasOverflowMode() const { return HasType(wxSHEET_AttrOverflowType_Mask); } bool wxSheetCellAttr::HasOverflowMarkerMode() const { return HasType(wxSHEET_AttrOverflowMarkerType_Mask); } bool wxSheetCellAttr::HasShowEditorMode() const { return HasType(wxSHEET_AttrShowEditorType_Mask); } bool wxSheetCellAttr::HasReadWriteMode() const { return HasType(wxSHEET_AttrReadType_Mask); } bool wxSheetCellAttr::HasRenderer() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); return M_CELLATTRDATA->m_renderer && M_CELLATTRDATA->m_renderer->Ok(); } bool wxSheetCellAttr::HasEditor() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); return M_CELLATTRDATA->m_editor && M_CELLATTRDATA->m_editor->Ok(); } bool wxSheetCellAttr::HasDefaultAttr() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); return M_CELLATTRDATA->m_defaultAttr && M_CELLATTRDATA->m_defaultAttr->Ok(); } bool wxSheetCellAttr::IsComplete() const { return Ok() && HasForegoundColour() && HasBackgroundColour() && HasFont() && HasAlignment() && HasOverflowMode() && HasLevel() && HasReadWriteMode() && HasRenderer() && HasEditor(); } const wxColour& wxSheetCellAttr::GetForegroundColour() const { wxCHECK_MSG(m_refData, *wxBLACK, wxT("wxSheetCellAttr not initializied")); if (HasForegoundColour()) return M_CELLATTRDATA->m_foreColour; else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasForegoundColour()) return GetDefaultAttr().GetForegroundColour(); wxFAIL_MSG(wxT("Missing default cell attribute")); return *wxBLACK; } const wxColour& wxSheetCellAttr::GetBackgroundColour() const { wxCHECK_MSG(m_refData, *wxWHITE, wxT("wxSheetCellAttr not initializied")); if (HasBackgroundColour()) return M_CELLATTRDATA->m_backColour; else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasBackgroundColour()) return GetDefaultAttr().GetBackgroundColour(); wxFAIL_MSG(wxT("Missing default cell attribute")); return *wxWHITE; } const wxFont& wxSheetCellAttr::GetFont() const { wxCHECK_MSG(m_refData, *wxNORMAL_FONT, wxT("wxSheetCellAttr not initializied")); if (HasFont()) return M_CELLATTRDATA->m_font; else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasFont()) return GetDefaultAttr().GetFont(); wxFAIL_MSG(wxT("Missing default cell attribute")); return *wxNORMAL_FONT; } int wxSheetCellAttr::GetAlignment() const { wxCHECK_MSG(m_refData, wxSHEET_AttrAlignLeft|wxSHEET_AttrAlignCenterVert, wxT("wxSheetCellAttr not initializied")); if (HasAlignment()) return M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrAlignType_Mask; else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasAlignment()) return GetDefaultAttr().GetAlignment(); wxFAIL_MSG(wxT("Missing default cell attribute")); return wxSHEET_AttrAlignLeft|wxSHEET_AttrAlignCenterVert; } wxOrientation wxSheetCellAttr::GetOrientation() const { wxCHECK_MSG(m_refData, wxHORIZONTAL, wxT("wxSheetCellAttr not initializied")); if (HasOrientation()) return wxOrientation(M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOrientType_Mask); else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasOrientation()) return GetDefaultAttr().GetOrientation(); wxFAIL_MSG(wxT("Missing default cell attribute")); return wxHORIZONTAL; } wxSheetAttrLevel_Type wxSheetCellAttr::GetLevel() const { wxCHECK_MSG(m_refData, wxSHEET_AttrLevelTop, wxT("wxSheetCellAttr not initializied")); if (HasLevel()) return wxSheetAttrLevel_Type(M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrLevelType_Mask); else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasLevel()) return GetDefaultAttr().GetLevel(); wxFAIL_MSG(wxT("Missing default cell attribute")); return wxSHEET_AttrLevelTop; } bool wxSheetCellAttr::GetOverflow() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); if (HasOverflowMode()) return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOverflow) != 0; else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasOverflowMode()) return GetDefaultAttr().GetOverflow(); wxFAIL_MSG(wxT("Missing default cell attribute")); return false; } bool wxSheetCellAttr::GetOverflowMarker() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); if (HasOverflowMarkerMode()) return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOverflowMarker) != 0; else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasOverflowMarkerMode()) return GetDefaultAttr().GetOverflowMarker(); wxFAIL_MSG(wxT("Missing default cell attribute")); return false; } bool wxSheetCellAttr::GetShowEditor() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); if (HasShowEditorMode()) return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrShowEditor) != 0; else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasShowEditorMode()) return GetDefaultAttr().GetShowEditor(); wxFAIL_MSG(wxT("Missing default cell attribute")); return false; } bool wxSheetCellAttr::GetReadOnly() const { wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); if (HasReadWriteMode()) return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrReadOnly) != 0; else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasReadWriteMode()) return GetDefaultAttr().GetReadOnly(); wxFAIL_MSG(wxT("Missing default cell attribute")); return false; } // Labenski - the logic is now different, I didn't understand what it was // trying to do and setting the default editor/renderer was broken. // Old wxGrid logic which didn't allow you to set a default anything // "GetRenderer and GetEditor use a slightly different decision path about // which attribute to use. If a non-default attr object has one then it is // used, otherwise the default editor or renderer is fetched from the sheet and // used. It should be the default for the data type of the cell. If it is // NULL (because the table has a type that the sheet does not have in its // registry,) then the sheet's default editor or renderer is used." wxSheetCellRenderer wxSheetCellAttr::GetRenderer(wxSheet* sheet, const wxSheetCoords& coords) const { wxCHECK_MSG(m_refData, wxNullSheetCellRenderer, wxT("wxSheetCellAttr not initializied")); wxSheetCellRenderer renderer; // first try to get the renderer for the cell from the sheet, if this is default if (sheet && (sheet->GetDefaultAttr(coords) == *this)) renderer = sheet->GetDefaultRendererForCell(coords); // then see if this has a renderer and return it if valid if ( !renderer.Ok() ) { if ( M_CELLATTRDATA->m_renderer && M_CELLATTRDATA->m_renderer->Ok() ) renderer = *M_CELLATTRDATA->m_renderer; else { // couldn't get it from the sheet try attr default wxSheetCellAttr defAttr(GetDefaultAttr()); if ( defAttr.Ok() ) renderer = defAttr.GetRenderer(sheet, coords); } } // we're supposed to always find something wxASSERT_MSG(renderer.Ok(), wxT("Missing default cell renderer")); return renderer; } wxSheetCellEditor wxSheetCellAttr::GetEditor(wxSheet* sheet, const wxSheetCoords& coords) const { wxCHECK_MSG(m_refData, wxNullSheetCellEditor, wxT("wxSheetCellAttr not initializied")); wxSheetCellEditor editor; // first try to get the editor for the cell from the sheet, if this is default if (sheet && (sheet->GetDefaultAttr(coords) == *this)) editor = sheet->GetDefaultEditorForCell(coords); // then see if this has a editor and return it if valid if ( !editor.Ok() ) { if ( M_CELLATTRDATA->m_editor && M_CELLATTRDATA->m_editor->Ok() ) editor = *M_CELLATTRDATA->m_editor; else { // couldn't get it from the sheet try attr default wxSheetCellAttr defAttr(GetDefaultAttr()); if ( defAttr.Ok() ) editor = defAttr.GetEditor(sheet, coords); } } // we're supposed to always find something wxASSERT_MSG(editor.Ok(), wxT("Missing default cell editor")); return editor; } wxSheetAttr_Type wxSheetCellAttr::GetKind() const { wxCHECK_MSG(m_refData, wxSHEET_AttrCell, wxT("wxSheetCellAttr not initializied")); return wxSheetAttr_Type(M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrAny); } const wxSheetCellAttr& wxSheetCellAttr::GetDefaultAttr() const { wxCHECK_MSG(m_refData, wxNullSheetCellAttr, wxT("wxSheetCellAttr not initializied")); if (M_CELLATTRDATA->m_defaultAttr != NULL) return *M_CELLATTRDATA->m_defaultAttr; return wxNullSheetCellAttr; } void wxSheetCellAttr::SetDefaultAttr(const wxSheetCellAttr& defAttr) { wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); if (M_CELLATTRDATA->m_defaultAttr) { delete M_CELLATTRDATA->m_defaultAttr; M_CELLATTRDATA->m_defaultAttr = NULL; } // don't set defAttr to this, you don't gain anything, but a memory leak //if (defAttr.Ok() && (defAttr.m_refData != m_refData)) // M_CELLATTRDATA->m_defaultAttr = new wxSheetCellAttr(defAttr); if (defAttr.Ok()) { wxSheetCellAttr attr(defAttr); while (attr.Ok()) { wxCHECK_RET((*this) != attr, wxT("wxSheet attributes are linked recursively")); attr = attr.GetDefaultAttr(); } M_CELLATTRDATA->m_defaultAttr = new wxSheetCellAttr(defAttr); } } void wxSheetCellAttr::SetType(int type, int mask) { wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); M_CELLATTRDATA->m_attrTypes &= ~mask; // clear old M_CELLATTRDATA->m_attrTypes |= (mask ? (type & mask) : type); // set new } int wxSheetCellAttr::GetType(int mask) const { wxCHECK_MSG(m_refData, 0, wxT("wxSheetCellAttr not initializied")); return (M_CELLATTRDATA->m_attrTypes & mask); } // ---------------------------------------------------------------------------- // wxSheetCellAttrProvider // ---------------------------------------------------------------------------- wxSheetCellAttr wxSheetCellAttrProvider::GetAttr(const wxSheetCoords& coords, wxSheetAttr_Type type ) { switch (wxSheet::GetCellCoordsType(coords)) { case wxSHEET_CELL_GRID : { switch (type) { case wxSHEET_AttrAny: { wxSheetCellAttr attrCell(m_cellAttrs.GetValue(coords)); wxSheetCellAttr attrRow(m_rowAttrs.GetValue(coords.GetRow())); wxSheetCellAttr attrCol(m_colAttrs.GetValue(coords.GetCol())); // points system, greater the level you get added last // if two levels match use ordering col, row, cell on top. wxPairArrayIntSheetCellAttr data; if (attrCol.Ok()) data.SetValue(attrCol.GetLevel()+2, attrCol); if (attrRow.Ok()) data.SetValue(attrRow.GetLevel()+1, attrRow); if (attrCell.Ok()) data.SetValue(attrCell.GetLevel()+0, attrCell); // the attr are sorted from low priority to high const int count = data.GetCount(); switch (count) { case 0 : return wxNullSheetCellAttr; case 1 : return data.GetItemValue(0); default : break; } // This is the preferred way - link them together // but you must make sure that it doesn't loop // see check in wxSheetCellAttr::SetDefaultAttr wxSheetCellAttr attr; attr.Copy(data.GetItemValue(0)); attr.SetDefaultAttr(data.GetItemValue(1)); if (count > 2) data.GetItemValue(1).SetDefaultAttr(data.GetItemValue(2)); /* // This is the old way of copying the values to a single attr wxSheetCellAttr attr; attr.Copy(data.GetItemValue(0)); attr.MergeWith(data.GetItemValue(1)); if (count > 2) attr.MergeWith(data.GetItemValue(2)); */ // This is not a "real" attr but created attr.SetKind(wxSHEET_AttrAny); return attr; } case wxSHEET_AttrCell : return m_cellAttrs.GetValue(coords); case wxSHEET_AttrRow : return m_rowAttrs.GetValue(coords.GetRow()); case wxSHEET_AttrCol : return m_colAttrs.GetValue(coords.GetCol()); default: // unused as yet... // (wxSheetCellAttr::Default): // (wxSheetCellAttr::Merged): break; } break; } case wxSHEET_CELL_ROWLABEL : return m_rowLabelAttrs.GetValue(coords.m_row); case wxSHEET_CELL_COLLABEL : return m_colLabelAttrs.GetValue(coords.m_col); default : wxFAIL_MSG(wxString::Format(wxT("Unhandled coords (%d, %d) in wxSheetCellAttrProvider::GetAttr"), coords.m_row, coords.m_col)); break; } return wxNullSheetCellAttr; } void wxSheetCellAttrProvider::SetAttr(const wxSheetCoords& coords, const wxSheetCellAttr &attr, wxSheetAttr_Type type) { switch (wxSheet::GetCellCoordsType(coords)) { case wxSHEET_CELL_GRID : { switch (type) { case wxSHEET_AttrCell : { if (attr.Ok()) m_cellAttrs.SetValue(coords, attr); else m_cellAttrs.RemoveValue(coords); return; } case wxSHEET_AttrRow : { if (attr.Ok()) m_rowAttrs.SetValue(coords.m_row, attr); else m_rowAttrs.RemoveValue(coords.m_row); return; } case wxSHEET_AttrCol : { if (attr.Ok()) m_colAttrs.SetValue(coords.m_col, attr); else m_colAttrs.RemoveValue(coords.m_col); return; } default : { wxFAIL_MSG(wxT("Unhandled attr type for grid coords")); return; } } break; } case wxSHEET_CELL_ROWLABEL : { switch (type) { case wxSHEET_AttrCell : { if (attr.Ok()) m_rowLabelAttrs.SetValue(coords.m_row, attr); else m_rowLabelAttrs.RemoveValue(coords.m_row); return; } default : { wxFAIL_MSG(wxT("Unhandled attr type for row label coords")); return; } } break; } case wxSHEET_CELL_COLLABEL : { switch (type) { case wxSHEET_AttrCell : { if (attr.Ok()) m_colLabelAttrs.SetValue(coords.m_col, attr); else m_colLabelAttrs.RemoveValue(coords.m_col); return; } default : { wxFAIL_MSG(wxT("Unhandled attr type for col label coords")); return; } } break; } default : wxFAIL_MSG(wxString::Format(wxT("Unhandled coords (%d, %d) in wxSheetCellAttrProvider::SetAttr"), coords.m_row, coords.m_col)); break; } } void wxSheetCellAttrProvider::UpdateRows( size_t row, int numRows, int update ) { // no errors here since the pair arrays don't need to know about size if ((update & wxSHEET_UpdateGridCellAttrs) != 0) m_rowAttrs.UpdatePos( row, numRows ); if ((update & wxSHEET_UpdateGridCellAttrs) != 0) m_cellAttrs.UpdateRows( row, numRows ); if ((update & wxSHEET_UpdateRowLabelAttrs) != 0) m_rowLabelAttrs.UpdatePos( row, numRows ); } void wxSheetCellAttrProvider::UpdateCols( size_t col, int numCols, int update ) { if ((update & wxSHEET_UpdateGridCellAttrs) != 0) m_colAttrs.UpdatePos( col, numCols ); if ((update & wxSHEET_UpdateGridCellAttrs) != 0) m_cellAttrs.UpdateCols( col, numCols ); if ((update & wxSHEET_UpdateColLabelAttrs) != 0) m_colLabelAttrs.UpdatePos( col, numCols ); } gambit-0.2010.09.01/src/labenski/src/sheetedg.cpp0000644000076500007650000002145611350032206016102 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetedg.cpp // Purpose: wxSheetArrayEdge // Author: John Labenski // Modified by: // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "sheetedg.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/defs.h" #endif // WX_PRECOMP #include "wx/sheet/sheet.h" #include "wx/sheet/sheetedg.h" #include "wx/arrimpl.cpp" DEFINE_PAIRED_INT_DATA_ARRAYS(int, wxPairArrayIntInt) // ---------------------------------------------------------------------------- // wxSheetArrayEdge - a wxArrayInt container that sums its values // ---------------------------------------------------------------------------- wxSheetArrayEdge::wxSheetArrayEdge(size_t count, size_t default_size, size_t min_allowed_size) : m_count(count), m_default_size(default_size), m_min_allowed_size(min_allowed_size) {} int wxSheetArrayEdge::FindIndex(int coord, bool clipToMinMax) const { //wxCHECK_MSG(m_count != 0, -1, wxT("No edges to find index of")); if (m_count < 0) return -1; // < 0 is never valid, check for clip if (coord < 0) return clipToMinMax ? 0 : -1; // need default size to at least be 1 const int default_size = (m_default_size > 0) ? m_default_size : 1; const int count = m_data.GetCount(); int i_max = coord / default_size; int i_min = 0; // if no edges in array then they're all of the default size if (count == 0) return (i_max < m_count) ? i_max : (clipToMinMax ? m_count-1 : -1); // quick checks for past end and in first element if ( coord > m_data[count-1] ) return clipToMinMax ? (count-1) : -1; if ( coord <= m_data[0] ) return 0; // reset the values of max and min if necessary and trim range down if ( i_max >= count ) i_max = count - 1; if ( coord > m_data[i_max] ) { i_min = i_max; i_max = count - 1; } int median; while ( i_min < i_max ) { // no check for == since it's not very likely, at most 1 extra iteration median = (i_min + i_max)/2; if (m_data[median] > coord) i_max = median; else i_min = median + 1; } return i_min; } int wxSheetArrayEdge::FindMaxEdgeIndex(int val, int edge_size) const { const int index = FindIndex(val, true); if (index < 0) return -1; // we know we're inside the 'index' element (or above or below the array) // find which side is closer and if < edge_size return index const int diff = abs(GetMax(index) - val); const int diff_min = (index > 0) ? abs(GetMax(index-1) - val) : diff+edge_size+1; const int min_diff = wxMin(diff, diff_min); if (min_diff > edge_size) return -1; else if (min_diff == diff) return index; else if (min_diff == diff_min) return index - 1; return -1; /* // FIXME I wonder if this really makes complete sense? check it... // eg. what would happen if size of cell was only 1 pixel, you couldn't resize it? if ( GetSize(index) > edge_size ) { // We know that we are in index, test whether we are // close enough to lower or upper border, respectively. if ( abs(GetMax(index) - val) < edge_size ) return index; else if ( (index > 0) && (val - GetMin(index) < edge_size) ) return index - 1; } return -1; */ } int wxSheetArrayEdge::GetMin(size_t item) const { wxCHECK_MSG(int(item) < m_count, item*m_default_size, _T("invalid index") ); return m_data.IsEmpty() ? item*m_default_size : (item > 0 ? m_data[item-1] : 0); } int wxSheetArrayEdge::GetMax(size_t item) const { wxCHECK_MSG(int(item) < m_count, (item+1)*m_default_size - 1, _T("invalid index") ); return (m_data.IsEmpty() ? (item+1)*m_default_size : m_data[item]) - 1; } int wxSheetArrayEdge::GetSize(size_t item) const { wxCHECK_MSG(int(item) < m_count, m_default_size, _T("invalid index") ); return m_data.IsEmpty() ? m_default_size : (m_data[item] - (item > 0 ? m_data[item-1] : 0)); } void wxSheetArrayEdge::SetSize(size_t item, int size) { wxCHECK_RET(int(item) < GetCount(), wxT("Invalid edge index")); const int old_size = GetSize(item); if (size == old_size) return; // set to the min size if less than it const int min_size = GetMinSize(item); if (size < min_size) size = min_size; // need to really create the array if ( m_data.IsEmpty() ) InitArray(); const int diff = size - old_size; const int count = m_data.GetCount(); for ( int i = item; i < count; i++ ) m_data[i] += diff; if (size == m_default_size) CheckMinimize(); } void wxSheetArrayEdge::SetDefaultSize(int default_size, bool resizeExisting) { wxCHECK_RET(default_size >= 0, wxT("Edge default size must be greater than 0")); m_default_size = default_size; if (resizeExisting) m_data.Clear(); else CheckMinimize(); } int wxSheetArrayEdge::GetMinSize(size_t index) const { const int min_index = m_minSizes.FindIndex(index); return (min_index != wxNOT_FOUND) ? m_minSizes.GetItemValue(min_index) : m_min_allowed_size; } void wxSheetArrayEdge::SetMinSize(size_t index, int size) { if (size > m_min_allowed_size) m_minSizes.GetOrCreateValue(index) = size; else m_minSizes.RemoveValue(index); } bool wxSheetArrayEdge::SetMinAllowedSize(int min_allowed_size, bool resizeExisting) { wxCHECK_MSG(m_default_size >= min_allowed_size, false, wxT("Invalid min allowed size")); if (m_min_allowed_size == min_allowed_size) return false; if (resizeExisting && (min_allowed_size < m_min_allowed_size)) { size_t n, count = m_minSizes.GetCount(); for (n = 0; n < count; n++) { if (m_minSizes.GetItemValue(n) < min_allowed_size) m_minSizes.RemoveValue(n); } count = m_data.GetCount(); if (count > 0) { int shift = m_data[0] < min_allowed_size ? min_allowed_size - m_data[0] : 0; m_data[0] += shift; for (n = 1; n < count; n++) { m_data[n] += shift; if (m_data[n] - m_data[n-1] < min_allowed_size) { int s = min_allowed_size - (m_data[n] - m_data[n-1]); m_data[n] += s; shift += s; } } } } m_min_allowed_size = min_allowed_size; return true; } void wxSheetArrayEdge::UpdatePos(size_t pos, int count) { wxSHEET_CHECKUPDATE_RET(pos, count, m_count); m_count += count; const int old_count = m_data.GetCount(); if ((count == 0) || (old_count == 0)) return; int start_pos = pos, end_pos = old_count + count; int i, edge = 0; wxArrayInt sizes; // FIXME lazy way sizes.Alloc(old_count); sizes.Add( m_default_size, old_count); sizes[0] = m_data[0]; for ( i = 1; i < old_count; i++ ) sizes[i] = m_data[i] - m_data[i-1]; if (count > 0) // adding rows/cols { sizes.Insert( m_default_size, pos, count ); m_data.Insert( 0, pos, count ); edge = (pos > 0) ? m_data[pos-1] : 0; } else // if (count < 0) // deleting rows/cols { sizes.RemoveAt( pos, -count ); m_data.RemoveAt( pos, -count ); edge = (pos > 0) ? m_data[pos-1] : 0; } for ( i = start_pos; i < end_pos; i++ ) { edge += sizes[i]; m_data[i] = edge; } if (count < 0) // maybe deleted non default CheckMinimize(); } void wxSheetArrayEdge::InitArray() { if (m_count == 0) return; m_data.Clear(); m_data.Alloc( m_count ); int i, edge = 0; for ( i = 0; i < m_count; i++ ) { edge += m_default_size; m_data.Add( edge ); } } bool wxSheetArrayEdge::CheckMinimize() { const int count = m_data.GetCount(); if (count == 0) return false; // start from end since it'll have a better chance of being off for (int n = count - 1; n >= 0; n--) { if (m_data[n] != m_default_size*n) return false; } m_data.Clear(); return true; } gambit-0.2010.09.01/src/labenski/src/sheetedt.cpp0000644000076500007650000013655011350032206016121 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetedt.cpp // Purpose: wxSheet controls // Author: Paul Gammans, Roger Gammans // Modified by: John Labenski // Created: 11/04/2001 // RCS-ID: $Id$ // Copyright: (c) John Labenski, The Computer Surgery (paul@compsurg.co.uk) // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "sheetedt.h" #endif #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/defs.h" #include "wx/utils.h" #include "wx/textctrl.h" #include "wx/dc.h" #include "wx/dcclient.h" #include "wx/textctrl.h" #include "wx/checkbox.h" #include "wx/combobox.h" #include "wx/log.h" #include "wx/valtext.h" #include "wx/settings.h" #include "wx/intl.h" #endif // WX_PRECOMP #include "wx/sheet/sheet.h" #include "wx/sheet/sheetedt.h" #include "wx/tokenzr.h" #include "wx/spinctrl.h" // Required for wxIs... functions #include #define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); #if defined(__WXMOTIF__) #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier) #else #define WXUNUSED_MOTIF(identifier) identifier #endif // defined(__WXMOTIF__) #if defined(__WXGTK__) #define WXUNUSED_GTK(identifier) WXUNUSED(identifier) #else #define WXUNUSED_GTK(identifier) identifier #endif // defined(__WXGTK__) const wxSheetCellEditor wxNullSheetCellEditor; IMPLEMENT_DYNAMIC_CLASS(wxSheetCellEditor, wxObject) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellEditorRefData, wxObject) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellTextEditorRefData, wxSheetCellEditorRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellNumberEditorRefData, wxSheetCellTextEditorRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellFloatEditorRefData, wxSheetCellTextEditorRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellBoolEditorRefData, wxSheetCellEditorRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellChoiceEditorRefData, wxSheetCellEditorRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellEnumEditorRefData, wxSheetCellChoiceEditorRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellAutoWrapStringEditorRefData, wxSheetCellTextEditorRefData) // ---------------------------------------------------------------------------- // wxSheetCellEditorEvtHandler // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS( wxSheetCellEditorEvtHandler, wxEvtHandler ) BEGIN_EVENT_TABLE( wxSheetCellEditorEvtHandler, wxEvtHandler ) EVT_KEY_DOWN ( wxSheetCellEditorEvtHandler::OnKeyDown ) EVT_CHAR ( wxSheetCellEditorEvtHandler::OnChar ) EVT_WINDOW_DESTROY ( wxSheetCellEditorEvtHandler::OnDestroy ) END_EVENT_TABLE() wxSheetCellEditorEvtHandler::wxSheetCellEditorEvtHandler(wxSheet* sheet, const wxSheetCellEditor &editor) : m_sheet(sheet) { m_editor = (wxSheetCellEditorRefData*)editor.GetRefData(); wxCHECK_RET(m_sheet && m_editor, wxT("Invalid sheet or editor in wxSheetCellEditorEvtHandler")); } void wxSheetCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event) { if (!m_editor->OnKeyDown(event)) return; switch ( event.GetKeyCode() ) { case WXK_ESCAPE: { m_editor->ResetValue(); m_sheet->DisableCellEditControl(false); break; } case WXK_TAB: { m_sheet->GetEventHandler()->ProcessEvent( event ); break; } case WXK_RETURN: case WXK_NUMPAD_ENTER: { if (!m_sheet->GetEventHandler()->ProcessEvent(event)) m_editor->HandleReturn(event); break; } default: event.Skip(); } } void wxSheetCellEditorEvtHandler::OnChar(wxKeyEvent& event) { if (!m_editor->OnChar(event)) return; switch ( event.GetKeyCode() ) { case WXK_ESCAPE: case WXK_TAB: case WXK_RETURN: case WXK_NUMPAD_ENTER: break; default: event.Skip(); } } void wxSheetCellEditorEvtHandler::OnDestroy(wxWindowDestroyEvent& event) { event.Skip(); // when parent window is destroyed pop event handler and NULL the control if (m_editor->m_control && (m_editor->m_control->GetEventHandler() == this)) { // see if anyone else want's to process the event before we delete ourself if (!GetNextHandler()->ProcessEvent(event)) { wxWindow *win = m_editor->m_control; m_editor->m_control = NULL; win->PopEventHandler(true); } event.Skip(false); } } // ---------------------------------------------------------------------------- // wxSheetCellEditor // ---------------------------------------------------------------------------- #define M_CELLEDITORDATA ((wxSheetCellEditorRefData*)m_refData) wxSheetCellEditor::wxSheetCellEditor( wxSheetCellEditorRefData *editor ) { m_refData = editor; } bool wxSheetCellEditor::IsCreated() const { wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->IsCreated(); } bool wxSheetCellEditor::IsShown() const { wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->IsShown(); } wxWindow* wxSheetCellEditor::GetControl() const { wxCHECK_MSG(Ok(), NULL, wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->GetControl(); } void wxSheetCellEditor::SetControl(wxWindow* control) { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->SetControl(control); } void wxSheetCellEditor::DestroyControl() { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->DestroyControl(); } void wxSheetCellEditor::CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet) { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->CreateEditor(parent, id, evtHandler, sheet); } void wxSheetCellEditor::SetSize(const wxRect& rect, const wxSheetCellAttr &attr) { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->SetSize(rect, attr); } wxSize wxSheetCellEditor::GetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, const wxSheetCoords& coords) { wxCHECK_MSG(Ok(), grid.GetCellSize(coords), wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->GetBestSize(grid, attr, coords); } void wxSheetCellEditor::Show(bool show, const wxSheetCellAttr &attr) { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->Show(show, attr); } void wxSheetCellEditor::PaintBackground(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected) { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->PaintBackground(sheet, attr, dc, rect, coords, isSelected); } void wxSheetCellEditor::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->BeginEdit(coords, sheet); } bool wxSheetCellEditor::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->EndEdit(coords, sheet); } void wxSheetCellEditor::ResetValue() { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->ResetValue(); } bool wxSheetCellEditor::IsAcceptedKey(wxKeyEvent& event) { wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->IsAcceptedKey(event); } void wxSheetCellEditor::StartingKey(wxKeyEvent& event) { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->StartingKey(event); } void wxSheetCellEditor::StartingClick() { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->StartingClick(); } void wxSheetCellEditor::HandleReturn(wxKeyEvent& event) { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->HandleReturn(event); } bool wxSheetCellEditor::OnKeyDown(wxKeyEvent& event) { wxCHECK_MSG(Ok(), true, wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->OnKeyDown(event); } bool wxSheetCellEditor::OnChar(wxKeyEvent& event) { wxCHECK_MSG(Ok(), true, wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->OnChar(event); } void wxSheetCellEditor::SetParameters(const wxString& params) { wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); M_CELLEDITORDATA->SetParameters(params); } wxString wxSheetCellEditor::GetValue() const { wxCHECK_MSG(Ok(), wxEmptyString, wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->GetValue(); } wxString wxSheetCellEditor::GetInitValue() const { wxCHECK_MSG(Ok(), wxEmptyString, wxT("wxSheetCellEditor not created")); return M_CELLEDITORDATA->GetInitValue(); } bool wxSheetCellEditor::Copy(const wxSheetCellEditor& other) { wxCHECK_MSG(other.Ok(), false, wxT("wxSheetCellEditor not created")); UnRef(); m_refData = ((wxSheetCellEditorRefData*)other.m_refData)->Clone(); return true; } // ---------------------------------------------------------------------------- // wxSheetCellEditorRefData // ---------------------------------------------------------------------------- wxSheetCellEditorRefData::~wxSheetCellEditorRefData() { if (GetControl()) DestroyControl(); } bool wxSheetCellEditorRefData::IsShown() const { return GetControl() && GetControl()->IsShown(); } void wxSheetCellEditorRefData::CreateEditor(wxWindow* WXUNUSED(parent), wxWindowID WXUNUSED(id), wxEvtHandler* evtHandler, wxSheet* WXUNUSED(sheet)) { if (evtHandler && GetControl()) GetControl()->PushEventHandler(evtHandler); } void wxSheetCellEditorRefData::SetControl(wxWindow* control) { DestroyControl(); m_control = control; } void wxSheetCellEditorRefData::DestroyControl() { if (m_control) { wxWindow *win = m_control; m_control = NULL; // if pushed event handler, pop and delete the handler if (win != win->GetEventHandler()) win->PopEventHandler(true); win->Destroy(); } } void wxSheetCellEditorRefData::PaintBackground(wxSheet& , const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& , bool ) { // erase the background because we might not fill the cell dc.SetPen(*wxTRANSPARENT_PEN); dc.SetBrush(wxBrush(attr.GetBackgroundColour(), wxSOLID)); // only draw exactly what's needed /* FIXME - the checkbox in GTK doesn't draw it's full background wxRect ctrlRect(GetControl()->GetRect()); // top if (ctrlRect.GetTop() > rect.GetTop()) dc.DrawRectangle(wxRect(rect.x, rect.y, rect.width, ctrlRect.GetTop()-rect.GetTop())); // bottom if (ctrlRect.GetBottom() < rect.GetBottom()) dc.DrawRectangle(wxRect(rect.x, ctrlRect.GetBottom(), rect.width, rect.GetBottom()-ctrlRect.GetBottom())); // left if (ctrlRect.GetLeft() > rect.GetLeft()) dc.DrawRectangle(wxRect(rect.x, ctrlRect.y, ctrlRect.GetLeft() - rect.GetLeft(), ctrlRect.height)); // right if (ctrlRect.GetRight() < rect.GetRight()) dc.DrawRectangle(wxRect(ctrlRect.GetRight(), ctrlRect.y, rect.GetRight() - ctrlRect.GetRight(), ctrlRect.height)); */ dc.DrawRectangle(rect); // redraw the control we just painted over if (GetControl()) GetControl()->Refresh(); } void wxSheetCellEditorRefData::Show(bool show, const wxSheetCellAttr &attr) { wxCHECK_RET(GetControl(), wxT("wxSheetCellEditor not created")); // set the colours/fonts if we have any if ( show && attr.Ok() ) { GetControl()->SetForegroundColour(attr.GetForegroundColour()); // FIXME this is weird, in GTK you can't set the background of a textctrl // to the default window background colour, ie. label textctrls // this doesn't happen anymore in > 2.5.3 needs test in 2.4 maybe //wxColour c = attr.GetBackgroundColour(); //c.Set(wxMin(c.Red()+1, 255), c.Green(), c.Blue()); //GetControl()->SetBackgroundColour(c); GetControl()->SetBackgroundColour(attr.GetBackgroundColour()); GetControl()->SetFont(attr.GetFont()); } GetControl()->Show(show); } void wxSheetCellEditorRefData::SetSize(const wxRect& rect, const wxSheetCellAttr &) { wxCHECK_RET(GetControl(), wxT("wxSheetCellEditor not created")); GetControl()->SetSize(rect, wxSIZE_ALLOW_MINUS_ONE); } wxSize wxSheetCellEditorRefData::GetBestSize(wxSheet& grid, const wxSheetCellAttr& , const wxSheetCoords& coords) { wxCHECK_MSG(GetControl(), grid.GetCellSize(coords), wxT("wxSheetCellEditor not created")); return GetControl()->GetBestSize(); } bool wxSheetCellEditorRefData::IsAcceptedKey(wxKeyEvent& event) { // accept the simple key presses, not anything with Ctrl/Alt return !(event.ControlDown() || event.AltDown()); } // ---------------------------------------------------------------------------- // wxSheetCellTextEditorRefData // ---------------------------------------------------------------------------- #if wxUSE_TEXTCTRL void wxSheetCellTextEditorRefData::CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet) { SetControl(new wxTextCtrl(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize //,wxBORDER_NONE #if defined(__WXMSW__) , wxTE_PROCESS_TAB | wxTE_AUTO_SCROLL #endif // defined(__WXMSW__) )); // set max length allowed in the textctrl, if the parameter was set if (m_maxChars != 0) ((wxTextCtrl*)GetControl())->SetMaxLength(m_maxChars); wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); } void wxSheetCellTextEditorRefData::SetSize(const wxRect& rectOrig, const wxSheetCellAttr &attr) { wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); wxRect rect(rectOrig); // Put the control inside the grid lines on all sides. #if defined(__WXGTK__) // these are good for GTK 1.2, wx ver 2.5 //if (rect.x != 0) rect.x += 1; //if (rect.y != 0) rect.y += 1; #elif defined(__WXMSW__) // This works for wxMSW ver 2.5 //if (rect.x != 0) rect.x += 1; //if (rect.y != 0) rect.y += 1; #elif defined(__WXMOTIF__) // This is untested ??? int extra_x = ( rect.x > 2 ) ? 2 : 1; int extra_y = ( rect.y > 2 ) ? 2 : 1; extra_x *= 2; extra_y *= 2; rect.SetLeft( wxMax(0, rect.x - extra_x) ); rect.SetTop( wxMax(0, rect.y - extra_y) ); rect.SetRight( rect.GetRight() + 2*extra_x ); rect.SetBottom( rect.GetBottom() + 2*extra_y ); #endif wxSheetCellEditorRefData::SetSize(rect, attr); } void wxSheetCellTextEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_RET(IsCreated() && sheet, wxT("The wxSheetCellEditor must be Created first!")); m_startValue = sheet->GetCellValue(coords); m_maxLength = 0; DoBeginEdit(m_startValue); } void wxSheetCellTextEditorRefData::DoBeginEdit(const wxString& startValue) { wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); GetTextCtrl()->SetValue(startValue); GetTextCtrl()->SetInsertionPointEnd(); GetTextCtrl()->SetSelection(-1,-1); GetTextCtrl()->SetFocus(); } bool wxSheetCellTextEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_MSG(IsCreated() && sheet, false, wxT("The wxSheetCellEditor must be Created first!")); wxString value = GetTextCtrl()->GetValue(); bool changed = (value != m_startValue); if (changed) { if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) changed = false; else sheet->SetCellValue(coords, value); } m_startValue.Clear(); m_maxLength = 0; return changed; } void wxSheetCellTextEditorRefData::ResetValue() { wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); DoResetValue(m_startValue); } void wxSheetCellTextEditorRefData::DoResetValue(const wxString& startValue) { wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); GetTextCtrl()->SetValue(startValue); GetTextCtrl()->SetInsertionPointEnd(); } bool wxSheetCellTextEditorRefData::IsAcceptedKey(wxKeyEvent& event) { if ( wxSheetCellEditorRefData::IsAcceptedKey(event) ) { int keycode = event.GetKeyCode(); switch ( keycode ) { case WXK_NUMPAD0: case WXK_NUMPAD1: case WXK_NUMPAD2: case WXK_NUMPAD3: case WXK_NUMPAD4: case WXK_NUMPAD5: case WXK_NUMPAD6: case WXK_NUMPAD7: case WXK_NUMPAD8: case WXK_NUMPAD9: case WXK_MULTIPLY: case WXK_NUMPAD_MULTIPLY: case WXK_ADD: case WXK_NUMPAD_ADD: case WXK_SUBTRACT: case WXK_NUMPAD_SUBTRACT: case WXK_DECIMAL: case WXK_NUMPAD_DECIMAL: case WXK_DIVIDE: case WXK_NUMPAD_DIVIDE: return true; default: // accept 8 bit chars too if isprint() agrees if ( (keycode < 255) && (wxIsprint(keycode)) ) return true; } } return false; } void wxSheetCellTextEditorRefData::StartingKey(wxKeyEvent& event) { wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); if ( !GetTextCtrl()->EmulateKeyPress(event) ) event.Skip(); } void wxSheetCellTextEditorRefData::HandleReturn( wxKeyEvent& WXUNUSED_GTK(WXUNUSED_MOTIF(event)) ) { wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); #if defined(__WXMOTIF__) || defined(__WXGTK__) // wxMotif needs a little extra help... size_t pos = (size_t)( GetTextCtrl()->GetInsertionPoint() ); wxString s( GetTextCtrl()->GetValue() ); s = s.Left(pos) + wxT("\n") + s.Mid(pos); GetTextCtrl()->SetValue(s); GetTextCtrl()->SetInsertionPoint( pos ); #else // the other ports can handle a Return key press event.Skip(); #endif // defined(__WXMOTIF__) || defined(__WXGTK__) } bool wxSheetCellTextEditorRefData::OnChar( wxKeyEvent& WXUNUSED(event) ) { wxCHECK_MSG(IsCreated(), true, wxT("The wxSheetCellEditor must be Created first!")); // This function is used to expand the textctrl as you type // it doesn't stop the event, just looks at it wxString value = GetTextCtrl()->GetValue(); if (int(value.Length()) <= m_maxLength) return true; m_maxLength = value.Length(); wxRect rect(GetTextCtrl()->GetRect()); int clientWidth = GetTextCtrl()->GetParent()->GetClientSize().x; // already at edge of window, maybe the win should should scroll? if (rect.GetRight() >= clientWidth) return true; int w, h; wxFont font = GetTextCtrl()->GetFont(); GetTextCtrl()->GetTextExtent(value, &w, &h, NULL, NULL, &font); // can't just use w/value.Len since it might be "iii", too small for "WWW" int chW; GetTextCtrl()->GetTextExtent(wxT("W"), &chW, &h, NULL, NULL, &font); int extra = int(chW*1.5); //if (rect.width < w+extra) //GetTextCtrl()->SetSize(wxMin(w+extra, clientWidth-rect.x), rect.height); w += extra; wxSheet* sheet = wxDynamicCast(GetTextCtrl()->GetParent()->GetParent(), wxSheet); if (!sheet) return true; wxSheetCoords c(sheet->GetEditControlCoords()); if (!sheet->GetAttrOverflow(c)) return true; wxSheetCoords oneCell(1,1); int numCols = sheet->GetNumberCols(); wxRect scrollRect(sheet->CalcUnscrolledRect(rect)); for (c.m_col = sheet->XToGridCol(scrollRect.GetRight())+1; c.m_col < numCols; c.m_col++) { wxSheetCoords cellSize(sheet->GetCellSpan(c)); // looks weird going over a spanned cell if ((rect.width < w) && (rect.GetRight() < clientWidth) && (cellSize == oneCell)) rect.width += sheet->GetColWidth(c.m_col); else break; } // clip width to window size rect.width = wxMin(rect.width, clientWidth - rect.x); GetTextCtrl()->SetSize(rect.width, rect.height); return true; } void wxSheetCellTextEditorRefData::SetParameters(const wxString& params) { if ( params.IsEmpty() ) m_maxChars = 0; // reset to default else { long tmp; if ( !params.ToLong(&tmp) ) wxLogDebug(_T("Invalid wxSheetCellTextEditor parameter string '%s' ignored"), params.c_str()); else m_maxChars = (size_t)tmp; } } wxString wxSheetCellTextEditorRefData::GetValue() const { wxCHECK_MSG(IsCreated(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); return GetTextCtrl()->GetValue(); } #endif // wxUSE_TEXTCTRL // ---------------------------------------------------------------------------- // wxSheetCellAutoWrapStringEditorRefData // ---------------------------------------------------------------------------- #if wxUSE_TEXTCTRL void wxSheetCellAutoWrapStringEditorRefData::CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet) { SetControl( new wxTextCtrl(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_RICH) ); wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); } #endif // wxUSE_TEXTCTRL // ---------------------------------------------------------------------------- // wxSheetCellNumberEditorRefData // ---------------------------------------------------------------------------- #if defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) bool wxSheetCellNumberEditorRefData::Copy(const wxSheetCellNumberEditorRefData& other) { m_min = other.m_min; m_max = other.m_max; return wxSheetCellTextEditorRefData::Copy(other); } void wxSheetCellNumberEditorRefData::CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet) { if ( HasRange() ) { // create a spin ctrl SetControl( new wxSpinCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, m_min, m_max) ); wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); } else { // just a text control wxSheetCellTextEditorRefData::CreateEditor(parent, id, evtHandler, sheet); #if wxUSE_VALIDATORS GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); #endif // wxUSE_VALIDATORS } } void wxSheetCellNumberEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); // first get the value wxSheetTable *table = sheet->GetTable(); if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER) ) { m_startValue = table->GetValueAsLong(coords); } else { m_startValue = 0; wxString sValue = sheet->GetCellValue(coords); if (!sValue.IsEmpty() && !sValue.ToLong(&m_startValue)) { wxFAIL_MSG( _T("this cell doesn't have numeric value") ); return; } } if ( HasRange() ) { GetSpinCtrl()->SetValue((int)m_startValue); GetSpinCtrl()->SetFocus(); } else { DoBeginEdit(GetInitValue()); } } bool wxSheetCellNumberEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_MSG(IsCreated() && sheet, false, wxT("The wxSheetCellEditor must be Created first!")); bool changed; long value = 0; long oldValue = m_startValue; wxString text; if ( HasRange() ) { value = GetSpinCtrl()->GetValue(); changed = value != oldValue; if (changed) text = wxString::Format(wxT("%ld"), value); } else { text = GetTextCtrl()->GetValue(); changed = (text.IsEmpty() || text.ToLong(&value)) && (value != oldValue); } if ( changed ) { if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) return false; if (sheet->GetTable()->CanSetValueAs(coords, wxSHEET_VALUE_NUMBER)) sheet->GetTable()->SetValueAsLong(coords, value); else sheet->GetTable()->SetValue(coords, text); } return changed; } void wxSheetCellNumberEditorRefData::ResetValue() { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); if ( HasRange() ) GetSpinCtrl()->SetValue((int)m_startValue); else DoResetValue(GetInitValue()); } bool wxSheetCellNumberEditorRefData::IsAcceptedKey(wxKeyEvent& event) { if ( wxSheetCellEditorRefData::IsAcceptedKey(event) ) { int keycode = event.GetKeyCode(); switch ( keycode ) { case WXK_NUMPAD0: case WXK_NUMPAD1: case WXK_NUMPAD2: case WXK_NUMPAD3: case WXK_NUMPAD4: case WXK_NUMPAD5: case WXK_NUMPAD6: case WXK_NUMPAD7: case WXK_NUMPAD8: case WXK_NUMPAD9: case WXK_ADD: case WXK_NUMPAD_ADD: case WXK_SUBTRACT: case WXK_NUMPAD_SUBTRACT: case WXK_UP: case WXK_DOWN: return true; default: if ( (keycode < 128) && wxIsdigit(keycode) ) return true; } } return false; } void wxSheetCellNumberEditorRefData::StartingKey(wxKeyEvent& event) { if ( !HasRange() ) { int keycode = event.GetKeyCode(); if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-' || keycode == WXK_NUMPAD0 || keycode == WXK_NUMPAD1 || keycode == WXK_NUMPAD2 || keycode == WXK_NUMPAD3 || keycode == WXK_NUMPAD4 || keycode == WXK_NUMPAD5 || keycode == WXK_NUMPAD6 || keycode == WXK_NUMPAD7 || keycode == WXK_NUMPAD8 || keycode == WXK_NUMPAD9 || keycode == WXK_ADD || keycode == WXK_NUMPAD_ADD || keycode == WXK_SUBTRACT || keycode == WXK_NUMPAD_SUBTRACT) { wxSheetCellTextEditorRefData::StartingKey(event); // skip Skip() below return; } } event.Skip(); } void wxSheetCellNumberEditorRefData::SetParameters(const wxString& params) { if ( params.IsEmpty() ) { m_min = m_max = -1; // reset to default } else { long tmp; if ( params.BeforeFirst(_T(',')).ToLong(&tmp) ) { m_min = (int)tmp; if ( params.AfterFirst(_T(',')).ToLong(&tmp) ) { m_max = (int)tmp; // skip the error message below return; } } wxLogDebug(_T("Invalid wxSheetCellNumberEditor parameter string '%s' ignored"), params.c_str()); } } // return the value in the spin control if it is there (the text control otherwise) wxString wxSheetCellNumberEditorRefData::GetValue() const { wxCHECK_MSG(GetControl(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); wxString s; if ( HasRange() ) { long value = GetSpinCtrl()->GetValue(); s.Printf(wxT("%ld"), value); } else { s = GetTextCtrl()->GetValue(); } return s; } wxString wxSheetCellNumberEditorRefData::GetInitValue() const { return wxString::Format(_T("%ld"), m_startValue); } #endif //defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) // ---------------------------------------------------------------------------- // wxSheetCellFloatEditorRefData // ---------------------------------------------------------------------------- #if wxUSE_TEXTCTRL bool wxSheetCellFloatEditorRefData::Copy(const wxSheetCellFloatEditorRefData& other) { m_width = other.m_width; m_precision = other.m_precision; return wxSheetCellTextEditorRefData::Copy(other); } void wxSheetCellFloatEditorRefData::CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet) { wxSheetCellTextEditorRefData::CreateEditor(parent, id, evtHandler, sheet); #if wxUSE_VALIDATORS GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); #endif // wxUSE_VALIDATORS } void wxSheetCellFloatEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); // first get the value wxSheetTable *table = sheet->GetTable(); if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_FLOAT) ) { m_startValue = table->GetValueAsDouble(coords); } else { m_startValue = 0.0; wxString sValue = sheet->GetCellValue(coords); if (!sValue.ToDouble(&m_startValue) && !sValue.IsEmpty()) { wxFAIL_MSG( _T("this cell doesn't have float value") ); return; } } DoBeginEdit(GetInitValue()); } bool wxSheetCellFloatEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_MSG(IsCreated() && sheet, false, wxT("The wxSheetCellEditor must be Created first!")); double value = 0.0; wxString text(GetTextCtrl()->GetValue()); if ( (text.IsEmpty() || text.ToDouble(&value)) && (value != m_startValue) ) { if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) return false; if (sheet->GetTable()->CanSetValueAs(coords, wxSHEET_VALUE_FLOAT)) sheet->GetTable()->SetValueAsDouble(coords, value); else sheet->GetTable()->SetValue(coords, text.IsEmpty() ? GetStringValue(value) : text); return true; } return false; } void wxSheetCellFloatEditorRefData::ResetValue() { DoResetValue(GetInitValue()); } void wxSheetCellFloatEditorRefData::StartingKey(wxKeyEvent& event) { int keycode = event.GetKeyCode(); char tmpbuf[2]; tmpbuf[0] = (char) keycode; tmpbuf[1] = '\0'; wxString strbuf(tmpbuf, *wxConvCurrent); bool is_decimal_point = ( strbuf == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) ); if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-' || is_decimal_point || keycode == WXK_NUMPAD0 || keycode == WXK_NUMPAD1 || keycode == WXK_NUMPAD2 || keycode == WXK_NUMPAD3 || keycode == WXK_NUMPAD4 || keycode == WXK_NUMPAD5 || keycode == WXK_NUMPAD6 || keycode == WXK_NUMPAD7 || keycode == WXK_NUMPAD8 || keycode == WXK_NUMPAD9 || keycode == WXK_ADD || keycode == WXK_NUMPAD_ADD || keycode == WXK_SUBTRACT || keycode == WXK_NUMPAD_SUBTRACT) { wxSheetCellTextEditorRefData::StartingKey(event); return; // skip Skip() below } event.Skip(); } void wxSheetCellFloatEditorRefData::SetParameters(const wxString& params) { if ( params.IsEmpty() ) { m_width = m_precision = -1; // reset to default } else { long tmp; if ( params.BeforeFirst(_T(',')).ToLong(&tmp) ) { m_width = (int)tmp; if ( params.AfterFirst(_T(',')).ToLong(&tmp) ) { m_precision = (int)tmp; return; // skip the error message below } } wxLogDebug(_T("Invalid wxSheetCellFloatEditor parameter string '%s' ignored"), params.c_str()); } } wxString wxSheetCellFloatEditorRefData::GetStringValue(double value) const { wxString fmt; if ( m_width == -1 ) { // default width/precision fmt = _T("%f"); } else if ( m_precision == -1 ) { // default precision fmt.Printf(_T("%%%d.f"), m_width); } else { fmt.Printf(_T("%%%d.%df"), m_width, m_precision); } return wxString::Format(fmt, value); } bool wxSheetCellFloatEditorRefData::IsAcceptedKey(wxKeyEvent& event) { if ( wxSheetCellEditorRefData::IsAcceptedKey(event) ) { int keycode = event.GetKeyCode(); switch ( keycode ) { case WXK_NUMPAD0: case WXK_NUMPAD1: case WXK_NUMPAD2: case WXK_NUMPAD3: case WXK_NUMPAD4: case WXK_NUMPAD5: case WXK_NUMPAD6: case WXK_NUMPAD7: case WXK_NUMPAD8: case WXK_NUMPAD9: case WXK_ADD: case WXK_NUMPAD_ADD: case WXK_SUBTRACT: case WXK_NUMPAD_SUBTRACT: case WXK_DECIMAL: case WXK_NUMPAD_DECIMAL: return true; default: { // additionally accept 'e' as in '1e+6', also '-', '+', and '.' char tmpbuf[2]; tmpbuf[0] = (char) keycode; tmpbuf[1] = '\0'; wxString strbuf(tmpbuf, *wxConvCurrent); bool is_decimal_point = ( strbuf == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) ); if ( (keycode < 128) && (wxIsdigit(keycode) || tolower(keycode) == 'e' || is_decimal_point || keycode == '+' || keycode == '-') ) return true; } } } return false; } #endif // wxUSE_TEXTCTRL // ---------------------------------------------------------------------------- // wxSheetCellBoolEditorRefData // ---------------------------------------------------------------------------- #if wxUSE_CHECKBOX /* class wxSheetCellBoolEditorControl : public wxControl { public: wxSheetCellBoolEditorControl(wxWindow *parent, int align) : wxControl(parent, wxID_ANY), m_align(align) {} void OnPaint(wxPaintEvent& event) { } int m_align; DECLARE_EVENT_TABLE(wxSheetCellBoolEditorControl) } BEGIN_EVENT_TABLE( wxSheetCellBoolEditorControl, wxControl ) EVT_PAINT ( wxSheetCellEditorEvtHandler::OnPaint ) END_EVENT_TABLE() */ void wxSheetCellBoolEditorRefData::CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet) { SetControl( new wxCheckBox(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxNO_BORDER) ); wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); } void wxSheetCellBoolEditorRefData::SetSize(const wxRect& r, const wxSheetCellAttr &attr) { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); bool resize = false; wxSize size = GetControl()->GetSize(); wxCoord minSize = wxMin(r.width, r.height); // check if the checkbox is not too big/small for this cell wxSize sizeBest = GetControl()->GetBestSize(); if ( !(size == sizeBest) ) { // reset to default size if it had been made smaller size = sizeBest; resize = true; } if ( (size.x >= minSize) || (size.y >= minSize) ) { // leave 1 pixel margin size.x = size.y = minSize - 2; resize = true; } if ( resize ) { GetControl()->SetSize(size); } // position it in the centre of the rectangle (TODO: support alignment?) #if defined(__WXGTK__) || defined (__WXMOTIF__) // the checkbox without label still has some space to the right in wxGTK, // so shift it to the right size.x -= 8; #elif defined(__WXMSW__) // here too, but in other way size.x += 1; size.y -= 2; #endif // defined(__WXGTK__) || defined (__WXMOTIF__) int align = attr.Ok() ? attr.GetAlignment() : wxALIGN_CENTRE; int x = 0, y = 0; if ((align & wxALIGN_RIGHT) != 0) { x = r.x + r.width - size.x - 2; y = r.y + r.height/2 - size.y/2; } else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) { x = r.x + r.width/2 - size.x/2; y = r.y + r.height/2 - size.y/2; } else // wxALIGN_LEFT { x = r.x + 2; #ifdef __WXMSW__ x += 2; #endif //__WXMSW__ y = r.y + r.height/2 - size.y/2; } GetControl()->Move(x, y); } void wxSheetCellBoolEditorRefData::Show(bool show, const wxSheetCellAttr &attr) { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); GetControl()->Show(show); if ( show ) { wxColour colBg = attr.Ok() ? attr.GetBackgroundColour() : *wxLIGHT_GREY; GetCheckBox()->SetBackgroundColour(colBg); } } void wxSheetCellBoolEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); if (sheet->GetTable()->CanGetValueAs(coords, wxSHEET_VALUE_BOOL)) m_startValue = sheet->GetTable()->GetValueAsBool(coords); else { wxString cellval( sheet->GetTable()->GetValue(coords) ); m_startValue = !( !cellval || (cellval == wxT("0")) ); } GetCheckBox()->SetValue(m_startValue); GetCheckBox()->SetFocus(); } bool wxSheetCellBoolEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_MSG(GetControl(), false, wxT("The wxSheetCellEditor must be Created first!")); bool value = GetCheckBox()->GetValue(); bool changed = ( value != m_startValue ); if ( changed ) { if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) return false; if (sheet->GetTable() && sheet->GetTable()->CanGetValueAs(coords, wxSHEET_VALUE_BOOL)) sheet->GetTable()->SetValueAsBool(coords, value); else sheet->SetCellValue(coords, value ? _T("1") : wxEmptyString); } return changed; } void wxSheetCellBoolEditorRefData::ResetValue() { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); GetCheckBox()->SetValue(m_startValue); } void wxSheetCellBoolEditorRefData::StartingClick() { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); GetCheckBox()->SetValue(!GetCheckBox()->GetValue()); } bool wxSheetCellBoolEditorRefData::IsAcceptedKey(wxKeyEvent& event) { if ( wxSheetCellEditorRefData::IsAcceptedKey(event) ) { int keycode = event.GetKeyCode(); switch ( keycode ) { case WXK_MULTIPLY: case WXK_NUMPAD_MULTIPLY: case WXK_ADD: case WXK_NUMPAD_ADD: case WXK_SUBTRACT: case WXK_NUMPAD_SUBTRACT: case WXK_SPACE: case '+': case '-': return true; } } return false; } // return the value as "1" for true and the empty string for false wxString wxSheetCellBoolEditorRefData::GetValue() const { wxCHECK_MSG(GetControl(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); bool bSet = GetCheckBox()->GetValue(); return bSet ? _T("1") : wxEmptyString; } #endif // wxUSE_CHECKBOX // ---------------------------------------------------------------------------- // wxSheetCellChoiceEditorRefData // ---------------------------------------------------------------------------- #if wxUSE_COMBOBOX wxSheetCellChoiceEditorRefData::wxSheetCellChoiceEditorRefData(const wxArrayString& choices, bool allowOthers) : m_choices(choices), m_allowOthers(allowOthers) {} wxSheetCellChoiceEditorRefData::wxSheetCellChoiceEditorRefData(size_t count, const wxString choices[], bool allowOthers) : m_allowOthers(allowOthers) { if ( count > 0 ) { m_choices.Alloc(count); for ( size_t n = 0; n < count; n++ ) m_choices.Add(choices[n]); } } bool wxSheetCellChoiceEditorRefData::Copy(const wxSheetCellChoiceEditorRefData& other) { m_choices = other.m_choices; m_allowOthers = other.m_allowOthers; return wxSheetCellEditorRefData::Copy(other); } void wxSheetCellChoiceEditorRefData::CreateEditor(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler, wxSheet* sheet) { #if wxMINOR_VERSION > 4 SetControl( new wxComboBox(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, m_choices, m_allowOthers ? 0 : wxCB_READONLY) ); #else const size_t count = m_choices.GetCount(); wxString *choices = new wxString[count]; for ( size_t n = 0; n < count; n++ ) choices[n] = m_choices[n]; SetControl( new wxComboBox(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, count, choices, m_allowOthers ? 0 : wxCB_READONLY) ); delete []choices; #endif // wxMINOR_VERSION > 4 wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); } void wxSheetCellChoiceEditorRefData::PaintBackground(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected) { // as we fill the entire client area, don't do anything here to minimize // flicker // TODO: It doesn't actually fill the client area since the height of a // combo always defaults to the standard... Until someone has time to // figure out the right rectangle to paint, just do it the normal way... wxSheetCellEditorRefData::PaintBackground(sheet, attr, dc, rect, coords, isSelected); } void wxSheetCellChoiceEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); m_startValue = sheet->GetTable()->GetValue(coords); if (m_allowOthers) GetComboBox()->SetValue(m_startValue); else { // find the right position, or default to the first if not found int pos = GetComboBox()->FindString(m_startValue); if (pos == -1) pos = 0; if (GetComboBox()->GetCount() > pos) GetComboBox()->SetSelection(pos); } GetComboBox()->SetInsertionPointEnd(); GetComboBox()->SetFocus(); } bool wxSheetCellChoiceEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_MSG(GetControl(), false, wxT("The wxSheetCellEditor must be Created first!")); wxString value = GetComboBox()->GetValue(); if (value == m_startValue) return false; if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) return false; sheet->GetTable()->SetValue(coords, value); return true; } void wxSheetCellChoiceEditorRefData::ResetValue() { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); GetComboBox()->SetValue(m_startValue); GetComboBox()->SetInsertionPointEnd(); } void wxSheetCellChoiceEditorRefData::SetParameters(const wxString& params) { // what can we do? if ( params.IsEmpty() ) return; m_choices.Empty(); wxStringTokenizer tk(params, _T(',')); while ( tk.HasMoreTokens() ) m_choices.Add(tk.GetNextToken()); } // return the value in the text control wxString wxSheetCellChoiceEditorRefData::GetValue() const { wxCHECK_MSG(GetControl(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); return GetComboBox()->GetValue(); } #endif // wxUSE_COMBOBOX // ---------------------------------------------------------------------------- // wxSheetCellEnumEditorRefData // ---------------------------------------------------------------------------- #if wxUSE_COMBOBOX // A cell editor which displays an enum number as a textual equivalent. eg // data in cell is 0,1,2 ... n the cell could be displayed as // "John","Fred"..."Bob" in the combo choice box wxSheetCellEnumEditorRefData::wxSheetCellEnumEditorRefData(const wxString& choices) : wxSheetCellChoiceEditorRefData(), m_startint(-1) { if (!choices.IsEmpty()) SetParameters(choices); } void wxSheetCellEnumEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_RET(GetControl(), wxT("The wxSheetCellEnumEditor must be Created first!")); wxSheetTable *table = sheet->GetTable(); if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER) ) m_startint = table->GetValueAsLong(coords); else { wxString startValue = sheet->GetCellValue(coords); if (startValue.IsEmpty() || !startValue.ToLong(&m_startint)) m_startint = -1; } GetComboBox()->SetSelection(m_startint); GetComboBox()->SetInsertionPointEnd(); GetComboBox()->SetFocus(); } bool wxSheetCellEnumEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) { wxCHECK_MSG(GetControl(), false, wxT("The wxSheetCellEditor must be Created first!")); int pos = GetComboBox()->GetSelection(); bool changed = (pos != m_startint); if (changed) { if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) return false; if (sheet->GetTable() && sheet->GetTable()->CanSetValueAs(coords, wxSHEET_VALUE_NUMBER)) sheet->GetTable()->SetValueAsLong(coords, pos); else sheet->SetCellValue(coords, wxString::Format(wxT("%i"),pos)); } return changed; } #endif // wxUSE_COMBOBOX gambit-0.2010.09.01/src/labenski/src/sheetren.cpp0000644000076500007650000011250511350032206016123 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetren.cpp // Purpose: wxSheet controls // Author: Paul Gammans, Roger Gammans // Modified by: John Labenski // Created: 11/04/2001 // RCS-ID: $Id$ // Copyright: (c) John Labenski, The Computer Surgery (paul@compsurg.co.uk) // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "sheetren.h" #endif #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/defs.h" #include "wx/utils.h" #include "wx/dc.h" #include "wx/dcclient.h" #include "wx/log.h" #include "wx/valtext.h" #include "wx/settings.h" #include "wx/checkbox.h" #include "wx/intl.h" #endif // WX_PRECOMP #include "wx/sheet/sheet.h" #include "wx/sheet/sheetren.h" #include "wx/tokenzr.h" #include "wx/renderer.h" // Required for wxIs... functions #include #define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); #if defined(__WXMOTIF__) #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier) #else #define WXUNUSED_MOTIF(identifier) identifier #endif // defined(__WXMOTIF__) #if defined(__WXGTK__) #define WXUNUSED_GTK(identifier) WXUNUSED(identifier) #else #define WXUNUSED_GTK(identifier) identifier #endif // defined(__WXGTK__) const wxSheetCellRenderer wxNullSheetCellRenderer; /* XPM */ static const char *s_overflow_arrow_xpm_data[] = { /* columns rows colors chars-per-pixel */ "4 6 2 1", " c None", "a c Black", /* pixels */ "aa ", "aaa ", "aaaa", "aaaa", "aaa ", "aa "}; static wxBitmap s_overflowBitmap; // a bitmap to indicate cell overflows IMPLEMENT_DYNAMIC_CLASS(wxSheetCellRenderer, wxObject) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellRendererRefData, wxObject) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellStringRendererRefData, wxSheetCellRendererRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellNumberRendererRefData, wxSheetCellStringRendererRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellFloatRendererRefData, wxSheetCellStringRendererRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellBitmapRendererRefData, wxSheetCellStringRendererRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellBoolRendererRefData, wxSheetCellRendererRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellDateTimeRendererRefData, wxSheetCellStringRendererRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellEnumRendererRefData, wxSheetCellStringRendererRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellAutoWrapStringRendererRefData, wxSheetCellStringRendererRefData) IMPLEMENT_DYNAMIC_CLASS(wxSheetCellRolColLabelRendererRefData, wxSheetCellStringRendererRefData) // ---------------------------------------------------------------------------- // wxSheetCellRenderer // ---------------------------------------------------------------------------- #define M_CELLRENREFDATA ((wxSheetCellRendererRefData*)m_refData) wxSheetCellRenderer::wxSheetCellRenderer(wxSheetCellRendererRefData *renderer) { m_refData = renderer; } void wxSheetCellRenderer::Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected) { wxCHECK_RET(Ok(), wxT("wxSheetCellRenderer is not created")); M_CELLRENREFDATA->Draw(sheet, attr, dc, rect, coords, isSelected); } wxSize wxSheetCellRenderer::GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords) { wxCHECK_MSG(Ok(), sheet.GetCellSize(coords), wxT("wxSheetCellRenderer is not created")); return M_CELLRENREFDATA->GetBestSize(sheet, attr, dc, coords); } void wxSheetCellRenderer::SetParameters(const wxString& params) { wxCHECK_RET(Ok(), wxT("wxSheetCellRenderer is not created")); M_CELLRENREFDATA->SetParameters(params); } bool wxSheetCellRenderer::Copy(const wxSheetCellRenderer& other) { wxCHECK_MSG(other.Ok(), false, wxT("wxSheetCellRenderer is not created")); UnRef(); m_refData = ((wxSheetCellRendererRefData*)other.m_refData)->Clone(); return true; } // ---------------------------------------------------------------------------- // wxSheetCellRendererRefData // ---------------------------------------------------------------------------- // This is testing code to show the different selection blocks with different colours //#define TEST_SELECTION_BLOCKS #ifdef TEST_SELECTION_BLOCKS #include "wx/sheet/sheetsel.h" #include "math.h" #define UNUSE(a) a wxColour GetRainbow(double v) { double vmin = 0, vmax = 255, dv = vmax - vmin; if (v < (vmin + 0.25 * dv)) return wxColour(0, int(255.0*(4.0 * (v - vmin) / dv) + 0.5), 255); else if (v < (vmin + 0.5 * dv)) return wxColour(0, 255, int(255.0*(1.0 + 4.0 * (vmin + 0.25 * dv - v) / dv) + 0.5)); else if (v < (vmin + 0.75 * dv)) return wxColour(int(255.0*(4.0 * (v - vmin - 0.5 * dv) / dv) + 0.5), 255, 0); else return wxColour(255, int(255.0*(1.0 + 4.0 * (vmin + 0.75 * dv - v) / dv) + 0.5), 0); } #else #define UNUSE(a) #endif void wxSheetCellRendererRefData::Draw( wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& UNUSE(coords), bool isSelected ) { dc.SetBackgroundMode( wxSOLID ); // grey out fields if the sheet is disabled if ( sheet.IsEnabled() ) { if ( isSelected ) dc.SetBrush( wxBrush(sheet.GetSelectionBackground(), wxSOLID) ); else dc.SetBrush( wxBrush(attr.GetBackgroundColour(), wxSOLID) ); } else dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE), wxSOLID)); dc.SetPen( *wxTRANSPARENT_PEN ); dc.DrawRectangle(rect); #ifdef TEST_SELECTION_BLOCKS // colouring for identifying different blocks if (isSelected) { int i = sheet.GetSelection()->Index(coords); wxColour c(GetRainbow(i*10)); dc.SetBrush( wxBrush(c, wxSOLID) ); dc.DrawRectangle(rect); wxFont font = dc.GetFont(); dc.SetFont(*wxSMALL_FONT); dc.DrawText(wxString::Format(wxT("%d"), i), rect.x, rect.y); } #endif // TEST_SELECTION_BLOCKS //FIXME - border drawing code, maybe it goes here? //dc.SetPen( wxPen(sheet.GetGridLineColour(), 1, wxSOLID) ); //dc.DrawRectangle(rect.x-1, rect.y-1, rect.width+2, rect.height+2); } wxSize wxSheetCellRendererRefData::GetBestSize(wxSheet& sheet, const wxSheetCellAttr& WXUNUSED(attr), wxDC& WXUNUSED(dc), const wxSheetCoords& coords) { return sheet.GetCellSize(coords); // return current size } wxString wxSheetCellRendererRefData::GetString(wxSheet& sheet, const wxSheetCoords& coords) { return sheet.GetCellValue(coords); } // ---------------------------------------------------------------------------- // wxSheetCellStringRendererRefData // ---------------------------------------------------------------------------- wxSheetCellStringRendererRefData::wxSheetCellStringRendererRefData() { if (!s_overflowBitmap.Ok()) s_overflowBitmap = wxBitmap(s_overflow_arrow_xpm_data); } void wxSheetCellStringRendererRefData::SetTextColoursAndFont(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, bool isSelected) { dc.SetBackgroundMode( wxTRANSPARENT ); // TODO some special colours for attr.IsReadOnly() case? // different coloured text when the sheet is disabled if ( sheet.IsEnabled() ) { if ( isSelected ) { dc.SetTextBackground( sheet.GetSelectionBackground() ); dc.SetTextForeground( sheet.GetSelectionForeground() ); } else { dc.SetTextBackground( attr.GetBackgroundColour() ); dc.SetTextForeground( attr.GetForegroundColour() ); } } else { dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); } dc.SetFont( attr.GetFont() ); } wxSize wxSheetCellStringRendererRefData::DoGetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxString& text) { wxArrayString lines; long w=0, h=0; if (sheet.StringToLines(text, lines) > 0) { dc.SetFont(attr.GetFont()); sheet.GetTextBoxSize(dc, lines, &w, &h); } return (attr.GetOrientation() == wxHORIZONTAL) ? wxSize(w, h) : wxSize(h, w); } wxSize wxSheetCellStringRendererRefData::GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords) { return DoGetBestSize(sheet, attr, dc, GetString(sheet, coords)); } void wxSheetCellStringRendererRefData::Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected) { wxRect rect = rectCell; rect.Inflate(-1); // erase only this cells background, overflow cells should have been erased wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); DoDraw(sheet, attr, dc, rectCell, coords, isSelected); //wxRendererNative &ren = wxRendererNative::Get(); //ren.DrawComboBoxDropButton(&sheet, dc, rectCell); } void wxSheetCellStringRendererRefData::DoDraw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected) { wxRect rect = rectCell; rect.Inflate(-1); int align = attr.GetAlignment(); wxString value = sheet.GetCellValue(coords); int best_width = DoGetBestSize(sheet, attr, dc, value).GetWidth(); wxSheetCoords cellSpan(sheet.GetCellSpan(coords)); // shouldn't get here if <=0 int cell_rows = cellSpan.m_row; int cell_cols = cellSpan.m_col; bool is_grid_cell = wxSheet::IsGridCell(coords); // no overflow for row/col/corner labels bool overflow = is_grid_cell ? attr.GetOverflow() : false; int overflowCols = 0; int num_cols = sheet.GetNumberCols(); // this is the right col which includes overflow int rightCol = coords.m_col + cell_cols - 1; // Check if this cell should overflow to right and for how many cells if (overflow) { bool is_editing = sheet.IsCellEditControlShown(); wxSheetCoords editorCell = is_editing ? sheet.GetEditControlCoords() : wxNullSheetCoords; int row = coords.GetRow(), col = coords.GetCol(); wxSheetCoords ownerCell; if ((best_width > rectCell.width) && (col < num_cols-1) && sheet.GetTable()) { wxSheetCoords cell; for (cell.m_col = col+cell_cols; cell.m_col < num_cols; cell.m_col++) { bool is_empty = true; for (cell.m_row = row; cell.m_row < row+cell_rows; cell.m_row++) { // check w/ anchor cell for spanned cell block ownerCell = sheet.GetCellOwner(cell); if ( sheet.GetTable()->HasValue(ownerCell) || (ownerCell == editorCell) ) { is_empty = false; break; } } if (is_empty) rect.width += sheet.GetColWidth(cell.m_col); else { cell.m_col--; break; } if (rect.width >= best_width) break; } // this may extend out of sheet overflowCols = cell.m_col - col - cell_cols + 1; rightCol = wxMin(coords.m_col+cell_cols-1+overflowCols, num_cols - 1); } // redraw overflow cells individually for proper selection hilight if (overflowCols > 0) { // if overflowed then it's left aligned (yes I know ALIGN_LEFT=0) align &= ~wxSHEET_AttrAlignHoriz_Mask; align |= wxSHEET_AttrAlignLeft; wxRect clip(rect); clip.x += rectCell.width; int col_width; wxSheetCoords cell(coords); // draw each cell individually since it may be selected or not for (cell.m_col = col+cell_cols; cell.m_col <= rightCol; cell.m_col++) { col_width = sheet.GetColWidth(cell.m_col); clip.width = col_width - 1; dc.DestroyClippingRegion(); dc.SetClippingRegion(clip); SetTextColoursAndFont(sheet, attr, dc, sheet.IsCellSelected(cell)); sheet.DrawTextRectangle(dc, value, rect, align); clip.x += col_width - 1; } rect = rectCell; rect.Inflate(-1); rect.width++; dc.DestroyClippingRegion(); } } // Draw the text SetTextColoursAndFont(sheet, attr, dc, isSelected); sheet.DrawTextRectangle(dc, value, rect, align); if (attr.GetOverflowMarker()) { // Draw a marker to show that the contents has been clipped off int cellRight = sheet.GetColRight(rightCol); if (cellRight - rect.x < best_width) { int bmpWidth = s_overflowBitmap.GetWidth(); int bmpHeight = s_overflowBitmap.GetHeight(); int cellWidth = sheet.GetColWidth(rightCol); int cellHeight = sheet.GetRowHeight(coords.m_row); if ((bmpWidth < cellWidth-3) && (bmpHeight < cellHeight-3)) { int cellTop = sheet.GetRowTop(coords.m_row); int x = cellRight - bmpWidth - 2; int y = cellTop + (cellHeight - bmpHeight)/2; wxRect r(x-2, cellTop, bmpWidth+4-1, cellHeight-1); wxSheetCellAttr rightAttr(attr); if (overflowCols > 0) { wxSheetCoords clipCell(coords.m_row, rightCol); isSelected = sheet.IsCellSelected(clipCell); rightAttr = sheet.GetAttr(clipCell); } // clear background for bitmap wxSheetCellRendererRefData::Draw(sheet, rightAttr, dc, r, coords, isSelected); dc.DrawBitmap( s_overflowBitmap, x, y, true ); } } } } // ---------------------------------------------------------------------------- // wxSheetCellAutoWrapStringRendererRefData // ---------------------------------------------------------------------------- void wxSheetCellAutoWrapStringRendererRefData::Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected) { wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); SetTextColoursAndFont(sheet, attr, dc, isSelected); int align = attr.GetAlignment(); wxRect rect = rectCell; rect.Inflate(-1); sheet.DrawTextRectangle(dc, GetTextLines(sheet, dc, attr, rect, coords), rect, align); } wxArrayString wxSheetCellAutoWrapStringRendererRefData::GetTextLines(wxSheet& sheet, wxDC& dc, const wxSheetCellAttr& attr, const wxRect& rect, const wxSheetCoords& coords) { wxString data = sheet.GetCellValue(coords); wxArrayString lines; dc.SetFont(attr.GetFont()); //Taken from wxSheet again! wxCoord x = 0, y = 0, curr_x = 0; wxCoord max_x = rect.GetWidth(); wxStringTokenizer tk(data, _T(" \n\t\r")); wxString thisline; while ( tk.HasMoreTokens() ) { wxString tok = tk.GetNextToken(); //FIXME: this causes us to print an extra unnecesary // space at the end of the line. But it // is invisible , simplifies the size calculation // and ensures tokens are separated in the display tok += _T(" "); dc.GetTextExtent(tok, &x, &y); if ( curr_x + x > max_x) { lines.Add( thisline ); thisline = tok; curr_x = x; } else { thisline += tok; curr_x += x; } } lines.Add( thisline ); //Add last line return lines; } wxSize wxSheetCellAutoWrapStringRendererRefData::GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords) { wxCoord x, y, height, width = sheet.GetColWidth(coords.GetCol()) -10; int count = 250; //Limit iterations.. wxRect rect(0, 0, width, 10); // M is a nice large character 'y' gives descender!. dc.SetFont(attr.GetFont()); dc.GetTextExtent(wxT("My"), &x, &y); do // Search for a shape no taller than the golden ratio. { width += 10; rect.SetWidth(width); height = y * GetTextLines(sheet,dc,attr,rect,coords).GetCount(); count--; } while (count && (width < (height*1.68)) ); return wxSize(width, height); } // ---------------------------------------------------------------------------- // wxSheetCellNumberRendererRefData // ---------------------------------------------------------------------------- wxString wxSheetCellNumberRendererRefData::GetString(wxSheet& sheet, const wxSheetCoords& coords) { wxSheetTable *table = sheet.GetTable(); if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER) ) return wxString::Format(_T("%ld"), table->GetValueAsLong(coords)); return sheet.GetCellValue(coords); } void wxSheetCellNumberRendererRefData::Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected) { wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); SetTextColoursAndFont(sheet, attr, dc, isSelected); // draw the text right aligned by default int align = attr.GetAlignment(); // | wxALIGN_RIGHT; //FIXME Why forced right? wxRect rect = rectCell; rect.Inflate(-1); sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); } // ---------------------------------------------------------------------------- // wxSheetCellFloatRendererRefData // ---------------------------------------------------------------------------- bool wxSheetCellFloatRendererRefData::Copy(const wxSheetCellFloatRendererRefData &other) { SetWidth(other.GetWidth()); SetPrecision(other.GetPrecision()); return wxSheetCellStringRendererRefData::Copy(other); } wxString wxSheetCellFloatRendererRefData::GetString(wxSheet& sheet, const wxSheetCoords& coords) { wxSheetTable *table = sheet.GetTable(); bool hasDouble = false; double val = 0; wxString text; if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_FLOAT) ) { val = table->GetValueAsDouble(coords); hasDouble = true; } else { text = sheet.GetCellValue(coords); hasDouble = text.ToDouble(&val); } if ( hasDouble ) { if ( !m_format ) { if ( m_width < 0 ) { if ( m_precision < 0 ) m_format = _T("%f"); // default width/precision else m_format.Printf(_T("%%.%df"), m_precision); } else if ( m_precision < 0 ) m_format.Printf(_T("%%%d.f"), m_width); // default precision else m_format.Printf(_T("%%%d.%df"), m_width, m_precision); } text.Printf(m_format, val); } return text; } void wxSheetCellFloatRendererRefData::Draw( wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected ) { wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); SetTextColoursAndFont(sheet, attr, dc, isSelected); // draw the text right aligned by default -- FIXME ? WHY int align = attr.GetAlignment(); // | wxALIGN_RIGHT; wxRect rect(rectCell); rect.Inflate(-1); sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); } void wxSheetCellFloatRendererRefData::SetParameters(const wxString& params) { if ( params.IsEmpty() ) { // reset to defaults SetWidth(-1); SetPrecision(-1); } else { wxString tmp = params.BeforeFirst(_T(',')); if ( !tmp.IsEmpty() ) { long width; if ( tmp.ToLong(&width) ) SetWidth((int)width); else wxLogDebug(_T("Invalid wxSheetCellFloatRenderer width parameter string '%s ignored"), params.c_str()); } tmp = params.AfterFirst(_T(',')); if ( !tmp.IsEmpty() ) { long precision; if ( tmp.ToLong(&precision) ) SetPrecision((int)precision); else wxLogDebug(_T("Invalid wxSheetCellFloatRenderer precision parameter string '%s ignored"), params.c_str()); } } } // ---------------------------------------------------------------------------- // wxSheetCellBitmapRendererRefData // ---------------------------------------------------------------------------- wxSize wxSheetCellBitmapRendererRefData::GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxSheetCoords& coords) { wxSize bmpSize; if (m_bitmap.Ok()) bmpSize = wxSize( m_bitmap.GetWidth(), m_bitmap.GetHeight() ); wxSize strSize = wxSheetCellStringRendererRefData::GetBestSize(sheet, attr, dc, coords); return wxSize(bmpSize.x + strSize.x + 5, wxMax(bmpSize.y, strSize.y)); } #define MARGIN 2 void wxSheetCellBitmapRendererRefData::Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect_, const wxSheetCoords& coords, bool isSelected) { wxSheetCellRendererRefData::Draw(sheet, attr, dc, rect_, coords, isSelected); int text_align = attr.GetAlignment(); wxRect rect(rect_); wxSize bmpSize; if (m_bitmap.Ok()) { bmpSize.x = m_bitmap.GetWidth(); bmpSize.y = m_bitmap.GetHeight(); } wxSize txtSize(wxSheetCellStringRendererRefData::GetBestSize(sheet, attr, dc, coords)); wxRect bmpRect(rect); wxRect txtRect(rect); if ((txtSize.x == 0) && (bmpSize.x == 0)) return; int margin = 2; if ((txtSize.x == 0) || (bmpSize.x == 0)) margin = 0; if ((m_align & wxSHEET_BMPREN_BMPRIGHT) != 0) { //wxPrintf(wxT("1Printing row %d col %d \n"), coords.m_row, coords.m_col); bmpRect.x += txtSize.x + margin; bmpRect.width -= txtSize.x + margin; if (txtSize.x < rect.width) txtRect.width = txtSize.x; } else if ((m_align & wxSHEET_BMPREN_BMPABOVE) != 0) { //wxPrintf(wxT("2Printing row %d col %d \n"), coords.m_row, coords.m_col); txtRect.y += bmpSize.y + margin; txtRect.height -= bmpSize.y + margin; if (bmpSize.y < rect.height) bmpRect.height = bmpSize.y; } else if ((m_align & wxSHEET_BMPREN_BMPBELOW) != 0) { //wxPrintf(wxT("3Printing row %d col %d \n"), coords.m_row, coords.m_col); bmpRect.y += txtSize.y + margin; bmpRect.height -= txtSize.y + margin; if (txtSize.y < rect.height) txtRect.height = txtSize.y; } else //if ((m_align & wxSHEET_BMPREN_BMPLEFT) != 0) { //wxPrintf(wxT("4Printing row %d col %d \n"), coords.m_row, coords.m_col); txtRect.x += bmpSize.x + margin; txtRect.width -= bmpSize.x + margin; if (bmpSize.x < rect.width) bmpRect.width = bmpSize.x; } bmpRect.SetPosition(sheet.AlignInRect(m_align, bmpRect, bmpSize)); txtRect.SetPosition(sheet.AlignInRect(text_align, txtRect, txtSize)); bmpRect.Intersect(rect); txtRect.Intersect(rect); // text renderer will deflate it by 1 txtRect.Inflate(1); //wxPrintf(wxT("Printing row %d col %d \n"), coords.m_row, coords.m_col); //PRINT_RECT("orig ", rect); //PRINT_RECT("bmpRect", bmpRect); //PRINT_RECT("txtRect", txtRect); if ((txtRect.width > 0) && (txtRect.height > 0)) wxSheetCellStringRendererRefData::DoDraw(sheet, attr, dc, txtRect, coords, isSelected); if (m_bitmap.Ok() && (bmpRect.width > 0) && (bmpRect.height > 0)) { dc.SetClippingRegion(rect); dc.DrawBitmap(m_bitmap, bmpRect.x, bmpRect.y, true); dc.DestroyClippingRegion(); } } // ---------------------------------------------------------------------------- // wxSheetCellBoolRendererRefData // ---------------------------------------------------------------------------- wxSize wxSheetCellBoolRendererRefData::ms_sizeCheckMark; // FIXME these checkbox size calculations are really ugly... // between checkmark and box #define wxSHEET_CHECKMARK_MARGIN 2 wxSize wxSheetCellBoolRendererRefData::GetBestSize(wxSheet& sheet, const wxSheetCellAttr& WXUNUSED(attr), wxDC& WXUNUSED(dc), const wxSheetCoords& ) { // compute it only once (no locks for MT safeness in GUI thread...) if ( !ms_sizeCheckMark.x ) { // get checkbox size wxCheckBox *checkbox = new wxCheckBox(&sheet, wxID_ANY, wxEmptyString); wxSize size = checkbox->GetBestSize(); wxCoord checkSize = size.y + 2*wxSHEET_CHECKMARK_MARGIN; // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result #if defined(__WXGTK__) || defined(__WXMOTIF__) checkSize -= size.y / 2; #endif // defined(__WXGTK__) || defined(__WXMOTIF__) delete checkbox; ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize; } return ms_sizeCheckMark; } void wxSheetCellBoolRendererRefData::Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rect, const wxSheetCoords& coords, bool isSelected) { wxSheetCellRendererRefData::Draw(sheet, attr, dc, rect, coords, isSelected); // draw a check mark in the centre (ignoring alignment - TODO) wxSize size = GetBestSize(sheet, attr, dc, coords); // don't draw outside the cell wxCoord minSize = wxMin(rect.width, rect.height); if ((size.x >= minSize) || (size.y >= minSize)) size.x = size.y = minSize - 2; // leave (at least) 1 pixel margin // draw a border around checkmark int align = attr.GetAlignment(); wxRect rectBorder(rect.GetPosition(), size); if ((align & wxALIGN_RIGHT) != 0) rectBorder.x += rect.width - size.x - 2; else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) rectBorder.x += rect.width/2 - size.x/2; else // wxALIGN_LEFT rectBorder.x += 2; if ((align & wxALIGN_BOTTOM) != 0) rectBorder.y += rect.height - size.y - 2; else if ((align & wxALIGN_CENTRE_VERTICAL) != 0) rectBorder.y += rect.height/2 - size.y/2; else // wxALIGN_TOP rectBorder.y += 2; bool value; if ( sheet.GetTable()->CanGetValueAs(coords, wxSHEET_VALUE_BOOL) ) value = sheet.GetTable()->GetValueAsBool(coords); else { wxString strValue( sheet.GetTable()->GetValue(coords) ); value = !( strValue.IsEmpty() || (strValue == wxT("0")) ); } if ( value ) { wxRect rectMark = rectBorder; #ifdef __WXMSW__ // MSW DrawCheckMark() is weird (and should probably be changed...) rectMark.Inflate(-wxSHEET_CHECKMARK_MARGIN/2); rectMark.x++; rectMark.y++; #else // !MSW rectMark.Inflate(-wxSHEET_CHECKMARK_MARGIN); #endif // MSW/!MSW dc.SetTextForeground(attr.GetForegroundColour()); dc.DrawCheckMark(rectMark); } dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.SetPen(wxPen(attr.GetForegroundColour(), 1, wxSOLID)); dc.DrawRectangle(rectBorder); } // ---------------------------------------------------------------------------- // wxSheetCellDateTimeRendererRefData // ---------------------------------------------------------------------------- #if wxUSE_DATETIME // Enables a sheet cell to display a formated date and or time bool wxSheetCellDateTimeRendererRefData::Copy(const wxSheetCellDateTimeRendererRefData& other) { m_outFormat = other.m_outFormat; m_inFormat = other.m_inFormat; m_dateTime = other.m_dateTime; m_tz = other.m_tz; return wxSheetCellStringRendererRefData::Copy(other); } wxString wxSheetCellDateTimeRendererRefData::GetString(wxSheet& sheet, const wxSheetCoords& coords) { wxSheetTable *table = sheet.GetTable(); bool hasDatetime = false; wxDateTime val; wxString text; if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_DATETIME) ) { void* tempval = table->GetValueAsCustom(coords, wxSHEET_VALUE_DATETIME); if (tempval) { val = *((wxDateTime *)tempval); hasDatetime = true; delete (wxDateTime *)tempval; } } if ( !hasDatetime ) { text = sheet.GetCellValue(coords); hasDatetime = val.ParseFormat(text, m_inFormat, m_dateTime) != (wxChar *)NULL ; } else text = val.Format( m_outFormat, m_tz ); return text; //If we faild to parse string just show what we where given? } void wxSheetCellDateTimeRendererRefData::Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected) { wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); SetTextColoursAndFont(sheet, attr, dc, isSelected); // draw the text right aligned by default FIXME why? int align = attr.GetAlignment(); // | wxRIGHT; wxRect rect = rectCell; rect.Inflate(-1); sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); } void wxSheetCellDateTimeRendererRefData::SetParameters(const wxString& params) { if (!params.IsEmpty()) m_outFormat = params; } #endif // wxUSE_DATETIME // ---------------------------------------------------------------------------- // wxSheetCellEnumRendererRefData // ---------------------------------------------------------------------------- // Renders a number as a textual equivalent. // eg data in cell is 0,1,2 ... n the cell could be rendered as "John","Fred"..."Bob" wxSheetCellEnumRendererRefData::wxSheetCellEnumRendererRefData(const wxString& choices) { if (!choices.IsEmpty()) SetParameters(choices); } bool wxSheetCellEnumRendererRefData::Copy(const wxSheetCellEnumRendererRefData& other) { m_choices = other.m_choices; return wxSheetCellStringRendererRefData::Copy(other); } wxString wxSheetCellEnumRendererRefData::GetString( wxSheet& sheet, const wxSheetCoords& coords ) { wxSheetTable *table = sheet.GetTable(); if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER) ) { int choiceno = table->GetValueAsLong(coords); return m_choices[choiceno]; } return sheet.GetCellValue(coords); } void wxSheetCellEnumRendererRefData::Draw( wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected ) { wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); SetTextColoursAndFont(sheet, attr, dc, isSelected); // draw the text right aligned by default FIXME why? int align = attr.GetAlignment(); // | wxRIGHT; wxRect rect = rectCell; rect.Inflate(-1); sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); } void wxSheetCellEnumRendererRefData::SetParameters(const wxString& params) { if ( params.IsEmpty() ) return; // what can we do? m_choices.Empty(); wxStringTokenizer tk(params, _T(',')); while ( tk.HasMoreTokens() ) m_choices.Add(tk.GetNextToken()); } // ---------------------------------------------------------------------------- // wxSheetCellRolColLabelRendererRefData // ---------------------------------------------------------------------------- void wxSheetCellRolColLabelRendererRefData::Draw(wxSheet& sheet, const wxSheetCellAttr& attr, wxDC& dc, const wxRect& rectCell, const wxSheetCoords& coords, bool isSelected) { // erase this cells background wxRect rect(rectCell); wxSheetCellRendererRefData::Draw(sheet, attr, dc, rect, coords, isSelected); int left = rectCell.x; int top = rectCell.y; int right = rectCell.GetRight(); int bottom = rectCell.GetBottom(); //dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) ); // right side //dc.DrawLine( right, top, right, bottom ); // left side //if (coords.m_col == -1) // dc.DrawLine( left, top, left, bottom ); // top side //if (coords.m_row == -1) // dc.DrawLine( left, top, right, top ); // bottom //dc.DrawLine( left, bottom, right, bottom ); dc.SetPen( *wxWHITE_PEN ); // left highlight dc.DrawLine( left, top, left, bottom ); // top highlight dc.DrawLine( left, top, right, top ); SetTextColoursAndFont(sheet, attr, dc, isSelected); wxString value = sheet.GetCellValue(coords); if (!value.IsEmpty()) { int align = attr.GetAlignment(); int orient = attr.GetOrientation(); rect.Deflate(2); // want margins sheet.DrawTextRectangle(dc, value, rect, align, orient); } #if 0 // test code for sizing, draws corner tick marks if (1) { rect = rectCell; dc.SetPen(*wxGREEN_PEN); dc.DrawLine(left, top, left+25, top); dc.DrawLine(right-25, bottom, right, bottom); dc.DrawLine(left, top, left, top+10); dc.DrawLine(right, bottom-10, right, bottom); wxRect r(rectCell); dc.SetPen(*wxCYAN_PEN); dc.DrawLine(r.x, r.y, r.x+25, r.y); dc.DrawLine(r.GetRight()-25, r.GetBottom(), r.GetRight(), r.GetBottom()); dc.DrawLine(r.x, r.y, r.x, r.y+10); dc.DrawLine(r.GetRight(), r.GetBottom()-10, r.GetRight(), r.GetBottom()); } #endif // 0 } gambit-0.2010.09.01/src/labenski/src/sheetsel.cpp0000644000076500007650000011061111350032206016116 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetsel.cpp // Purpose: wxSheetSelection // Author: John Labenski // Modified by: // Created: 20/02/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski, Stefan Neis (Stefan.Neis@t-online.de) // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "sheetsel.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/defs.h" #include "wx/utils.h" // for wxMin and wxMax #include "wx/gdicmn.h" // for wxRect #endif // WX_PRECOMP #include "wx/sheet/sheet.h" #include "wx/sheet/sheetsel.h" // if set then //#define CHECK_BLOCK_OVERLAP 1 //#define CHECK_BLOCK_SORTING 1 #define PRINT_BLOCK(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), s, b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArraySheetCoords) WX_DEFINE_OBJARRAY(wxArraySheetBlock) const wxSheetCoords wxNullSheetCoords( INT_MIN, INT_MIN ); const wxSheetCoords wxGridCellSheetCoords( 0, 0 ); const wxSheetCoords wxRowLabelSheetCoords( 0, -1 ); const wxSheetCoords wxColLabelSheetCoords( -1, 0 ); const wxSheetCoords wxCornerLabelSheetCoords( -1, -1 ); const wxSheetBlock wxNullSheetBlock( 0, 0, 0, 0 ); // ---------------------------------------------------------------------------- // Compare functions for sorting // ---------------------------------------------------------------------------- static int wxCMPFUNC_CONV wxsheetcellblock_sort_topleft_bottomright( wxSheetBlock **a, wxSheetBlock **b) { return (*a)->CmpTopLeft(**b); /* int row = ((*a)->m_row - (*b)->m_row); if (row < 0) return -1; if (row == 0) return ((*a)->m_col - (*b)->m_col); return 1; */ } static int wxCMPFUNC_CONV wxsheetcellblock_sort_bottomright_topleft( wxSheetBlock **a, wxSheetBlock **b) { return (*b)->CmpRightBottom(**a); /* int col = ((*b)->GetRight() - (*a)->GetRight()); if (col < 0) return -1; if (col == 0) return ((*b)->GetBottom() - (*a)->GetBottom()); return 1; */ } // ---------------------------------------------------------------------------- // wxSheetCoords: location of a cell in the grid // ---------------------------------------------------------------------------- wxSheetCell_Type wxSheetCoords::GetCellCoordsType() const { if ((m_row >= 0) && (m_col >= 0)) { return wxSHEET_CELL_GRID; } else if (m_row == -1) { if (m_col == -1) return wxSHEET_CELL_CORNERLABEL; if (m_col >= 0) return wxSHEET_CELL_COLLABEL; } else if (m_col == -1) { if (m_row >= 0) return wxSHEET_CELL_ROWLABEL; } return wxSHEET_CELL_UNKNOWN; } wxSheetCoords wxSheetCoords::GetCellCoords(wxSheetCell_Type type) const { switch (type) { case wxSHEET_CELL_GRID : break; case wxSHEET_CELL_ROWLABEL : return wxSheetCoords( m_row, -1-m_col); case wxSHEET_CELL_COLLABEL : return wxSheetCoords(-1-m_row, m_col); case wxSHEET_CELL_CORNERLABEL : return wxSheetCoords(-1-m_row, -1-m_col); default : break; } return wxSheetCoords(*this); } wxSheetCoords& wxSheetCoords::SetCellCoords(wxSheetCell_Type type) { switch (type) { case wxSHEET_CELL_GRID : break; case wxSHEET_CELL_ROWLABEL : m_col = -1-m_col; break; case wxSHEET_CELL_COLLABEL : m_row = -1-m_row; break; case wxSHEET_CELL_CORNERLABEL : m_row = -1-m_row; m_col = -1-m_col; break; default : break; } return *this; } bool wxSheetCoords::UpdateRows( size_t row, int numRows ) { if ((numRows == 0) || (m_row < int(row))) return false; if ((numRows > 0) || (m_row > int(row) - numRows)) m_row += numRows; else m_row = int(row) - 1; // put it at beginning of delete return true; } bool wxSheetCoords::UpdateCols( size_t col, int numCols ) { if ((numCols == 0) || (m_col < int(col))) return false; if ((numCols > 0) || (m_col > int(col) - numCols)) m_col += numCols; else m_col = int(col) - 1; // put it at beginning of delete return true; } // ---------------------------------------------------------------------------- // wxSheetBlock: a rectangular block of cells // ---------------------------------------------------------------------------- wxSheetBlock::wxSheetBlock( const wxSheetCoords& coords1, const wxSheetCoords& coords2, bool make_upright ) { m_row = coords1.m_row; m_col = coords1.m_col; m_height = coords2.m_row - coords1.m_row; m_width = coords2.m_col - coords1.m_col; // block is upright with coords at corners if (make_upright) { if (m_width < 0) { m_width = -m_width; m_col = coords2.m_col; } m_width++; if (m_height < 0) { m_height = -m_height; m_row = coords2.m_row; } m_height++; } } wxArraySheetCoords wxSheetBlock::GetArrayCoords() const { wxArraySheetCoords arrCoords; if (IsEmpty()) return arrCoords; arrCoords.Alloc(GetWidth()*GetHeight()); const int bottom = GetBottom(), right = GetRight(); wxSheetCoords coords; for (coords.m_row = m_row; coords.m_row <= bottom; coords.m_row++) { for (coords.m_col = m_col; coords.m_col <= right; coords.m_col++) arrCoords.Add(coords); } return arrCoords; } wxSheetBlock wxSheetBlock::GetAligned() const { return wxSheetBlock( m_height < 0 ? m_row + m_height - 1 : m_row, m_width < 0 ? m_col + m_width - 1 : m_col, m_height < 0 ? 2 - m_height : m_height, m_width < 0 ? 2 - m_width : m_width ); } wxSheetBlock wxSheetBlock::Intersect( const wxSheetBlock &other ) const { // no need to check if IsEmpty since wxMin(Right/Bottom) does it // ugly code, but fastest in gcc int l = other.GetRight(); int r = GetRight(); r = wxMin(r, l); l = wxMax(m_col, other.m_col); int w = r-l+1; if (w < 0) return wxSheetBlock(); int t = other.GetBottom(); int b = GetBottom(); b = wxMin(b, t); t = wxMax(m_row, other.m_row); int h = b-t+1; if (h < 0) return wxSheetBlock(); return wxSheetBlock(t, l, h, w); /* // simplier code, but slower //int l = wxMax(m_col, other.m_col); //int r = wxMin(GetRight(), other.GetRight()); //int t = wxMax(m_row, other.m_row); //int b = wxMin(GetBottom(), other.GetBottom()); //return ((b-t+1 < 0) || (r-l+1 < 0)) ? wxSheetBlock() : // wxSheetBlock(t, l, b-t+1, r-l+1); */ } wxSheetBlock wxSheetBlock::Union( const wxSheetBlock &other ) const { // no need to check if IsEmpty since wxMin(Right/Bottom) does it // ugly code, but fastest in gcc int l = other.GetRight(); int r = GetRight(); r = wxMax(r, l); l = wxMin(m_col, other.m_col); int w = r-l+1; if (w < 0) return wxSheetBlock(); int t = other.GetBottom(); int b = GetBottom(); b = wxMax(b, t); t = wxMin(m_row, other.m_row); int h = b-t+1; if (h < 0) return wxSheetBlock(); return wxSheetBlock(t, l, h, w); /* // simplier code, but slower //int l = wxMin(m_col, other.m_col); //int r = wxMax(GetRight(), other.GetRight()); //int t = wxMin(m_row, other.m_row); //int b = wxMax(GetBottom(), other.GetBottom()); //return wxSheetBlock(t, l, wxMax(b-t+1, 0), wxMax(r-l+1, 0)); */ } wxSheetBlock wxSheetBlock::ExpandUnion( const wxSheetBlock &other ) const { if (IsEmpty()) return other; // preserve other block if (other.IsEmpty()) return *this; // preserve this // ugly code, but fastest in gcc int l = other.GetRight(); int r = GetRight(); r = wxMax(r, l); l = wxMin(m_col, other.m_col); int t = other.GetBottom(); int b = GetBottom(); b = wxMax(b, t); t = wxMin(m_row, other.m_row); return wxSheetBlock(t, l, b-t+1, r-l+1); /* // simplier code, but slower //int l = wxMin(m_col, other.m_col); //int r = wxMax(GetRight(), other.GetRight()); //int t = wxMin(m_row, other.m_row); //int b = wxMax(GetBottom(), other.GetBottom()); //return wxSheetBlock(t, l, b-t+1, r-l+1); */ } bool wxSheetBlock::Combine(const wxSheetBlock &block) { //if (IsEmpty() || block.IsEmpty()) return false; if (!Touches(block)) return false; if (Contains(block)) return true; if (block.Contains(*this)) { *this = block; return true; } // FIXME I forgot why wxSheetBlock::Combine needs this code? Isn't Contains good enough? const wxSheetBlock uBlock(Union(block)); if (uBlock.IsEmpty()) return false; // ugh this is really ugly, I can't figure a better way though /* // at least one of the two blocks has to be at each corner of the union if (((uBlock.GetLeftTop() == GetLeftTop()) || (uBlock.GetLeftTop() == block.GetLeftTop())) && ((uBlock.GetRightTop() == GetRightTop()) || (uBlock.GetRightTop() == block.GetRightTop())) && ((uBlock.GetLeftBottom() == GetLeftBottom()) || (uBlock.GetLeftBottom() == block.GetLeftBottom())) && ((uBlock.GetRightBottom() == GetRightBottom()) || (uBlock.GetRightBottom() == block.GetRightBottom())) ) { *this = uBlock; return true; } */ const int t = GetTop(); const int b = GetBottom(); const int l = GetLeft(); const int r = GetRight(); const int b_t = block.GetTop(); const int b_b = block.GetBottom(); const int b_l = block.GetLeft(); const int b_r = block.GetRight(); const int ub_t = uBlock.GetTop(); const int ub_b = uBlock.GetBottom(); const int ub_l = uBlock.GetLeft(); const int ub_r = uBlock.GetRight(); if ( ( ((ub_t==t)&&(ub_l==l)) || ((ub_t==b_t)&&(ub_l==b_l)) ) && ( ((ub_t==t)&&(ub_r==r)) || ((ub_t==b_t)&&(ub_r==b_r)) ) && ( ((ub_b==b)&&(ub_l==l)) || ((ub_b==b_b)&&(ub_l==b_l)) ) && ( ((ub_b==b)&&(ub_r==r)) || ((ub_b==b_b)&&(ub_r==b_r)) ) ) { *this = uBlock; return true; } return false; /* const int t = GetTop(); const int b = GetBottom(); const int l = GetLeft(); const int r = GetRight(); if ((t < b) || (l < r)) return false; // this is empty const int b_t = block.GetTop(); const int b_b = block.GetBottom(); const int b_l = block.GetLeft(); const int b_r = block.GetRight(); if ((b_t < b_b) || (b_l < b_r)) return false; // block is empty // if this contains other block if ((t <= b_t) && (l <= b_l) && (b >= b_b) && (r >= b_r)) return true; // if block contains this if ((t >= b_t) && (l >= b_l) && (b <= b_b) && (r <= b_r)) { *this = block; return true; } const int ub_t = uBlock.GetTop(); const int ub_b = uBlock.GetBottom(); const int ub_l = uBlock.GetLeft(); const int ub_r = uBlock.GetRight(); if ( ( ((ub_t==t)&&(ub_l==l)) || ((ub_t==b_t)&&(ub_l==b_l)) ) && ( ((ub_t==t)&&(ub_r==r)) || ((ub_t==b_t)&&(ub_r==b_r)) ) && ( ((ub_b==b)&&(ub_l==l)) || ((ub_b==b_b)&&(ub_l==b_l)) ) && ( ((ub_b==b)&&(ub_r==r)) || ((ub_b==b_b)&&(ub_r==b_r)) ) ) { *this = uBlock; return true; } return false; */ } int wxSheetBlock::Combine( const wxSheetBlock &block, wxSheetBlock &top, wxSheetBlock &bottom, wxSheetBlock &left, wxSheetBlock &right ) const { wxSheetBlock iBlock(Intersect(block)); if (iBlock.IsEmpty()) return wxSHEET_BLOCK_NONE; // nothing to combine if (Contains(block)) return wxSHEET_BLOCK_ALL; // can combine all of block, no leftover int combined = wxSHEET_BLOCK_NONE; if ( block.GetTop() < GetTop() ) { top.SetCoords( block.GetTop(), block.GetLeft(), GetTop()-1, block.GetRight() ); combined |= wxSHEET_BLOCK_TOP; } if ( block.GetBottom() > GetBottom() ) { bottom.SetCoords( GetBottom()+1, block.GetLeft(), block.GetBottom(), block.GetRight() ); combined |= wxSHEET_BLOCK_BOTTOM; } if ( block.GetLeft() < GetLeft() ) { left.SetCoords(iBlock.GetTop(), block.GetLeft(), iBlock.GetBottom(), GetLeft()-1 ); combined |= wxSHEET_BLOCK_LEFT; } if ( block.GetRight() > GetRight() ) { right.SetCoords( iBlock.GetTop(), GetRight()+1, iBlock.GetBottom(), block.GetRight() ); combined |= wxSHEET_BLOCK_RIGHT; } return combined; } int wxSheetBlock::Delete( const wxSheetBlock &block, wxSheetBlock &top, wxSheetBlock &bottom, wxSheetBlock &left, wxSheetBlock &right ) const { wxSheetBlock iBlock(Intersect(block)); if (iBlock.IsEmpty()) return wxSHEET_BLOCK_NONE; // nothing to delete if (block.Contains(*this)) return wxSHEET_BLOCK_ALL; // can delete all of this, no leftover int deleted = wxSHEET_BLOCK_NONE; if ( GetTop() < iBlock.GetTop() ) { top.SetCoords( GetTop(), GetLeft(), iBlock.GetTop()-1, GetRight() ); deleted |= wxSHEET_BLOCK_TOP; } if ( GetBottom() > iBlock.GetBottom() ) { bottom.SetCoords( iBlock.GetBottom()+1, GetLeft(), GetBottom(), GetRight() ); deleted |= wxSHEET_BLOCK_BOTTOM; } if ( GetLeft() < iBlock.GetLeft() ) { left.SetCoords( iBlock.GetTop(), GetLeft(), iBlock.GetBottom(), iBlock.GetLeft()-1 ); deleted |= wxSHEET_BLOCK_LEFT; } if ( GetRight() > iBlock.GetRight() ) { right.SetCoords( iBlock.GetTop(), iBlock.GetRight()+1, iBlock.GetBottom(), GetRight() ); deleted |= wxSHEET_BLOCK_RIGHT; } return deleted; } bool wxSheetBlock::UpdateRows( size_t row_, int numRows ) { int row = row_; if ((numRows == 0) || (GetBottom() < row)) return false; bool remove = numRows < 0; // this starts above the deleted rows if (m_row < row) { // this ends within deleted rows, trim to row if (remove && (GetBottom() < row - numRows)) SetBottom(row-1); // this straddles the inserted/deleted rows - resize else m_height += numRows; } // This is fully below it or an insert - shift coord else if (!remove || (m_row > row + labs(numRows))) { m_row += numRows; } // a remove and this's row is in deleted rows else { m_height += m_row - (row - numRows); m_row = row; } return true; } bool wxSheetBlock::UpdateCols( size_t col_, int numCols ) { int col = col_; if ((numCols == 0) || (GetRight() < col)) return false; bool remove = numCols < 0; // this starts above the deleted rows if (m_col < col) { // this ends within deleted rows, trim to row if (remove && (GetRight() < col - numCols)) SetRight(col-1); // this straddles the inserted/deleted rows - resize else m_width += numCols; } // This is fully below it or an insert - shift coord else if (!remove || (m_col > col + labs(numCols))) { m_col += numCols; } // a remove and this's row is in deleted rows else { m_width += m_col - (col - numCols); m_col = col; } return true; } int wxSheetBlock::CmpTopLeft(const wxSheetBlock& b) const { int cmp = m_row - b.m_row; if (cmp != 0) return cmp; cmp = m_col - b.m_col; if (cmp != 0) return cmp; cmp = m_height - b.m_height; if (cmp != 0) return cmp; cmp = m_width - b.m_width; return cmp; } int wxSheetBlock::CmpRightBottom(const wxSheetBlock& b) const { int cmp = GetRight() - b.GetRight(); if (cmp != 0) return cmp; cmp = GetBottom() - b.GetBottom(); if (cmp != 0) return cmp; cmp = m_col - b.m_col; if (cmp != 0) return cmp; cmp = m_row - b.m_row; return cmp; } // ---------------------------------------------------------------------------- // wxSheetSelection // ---------------------------------------------------------------------------- wxSheetSelection::wxSheetSelection(int options) : m_minimized(true), m_options(options) { } wxSheetSelection::wxSheetSelection( const wxSheetBlock& block, int options ) : m_minimized(true), m_options(options) { if (!block.IsEmpty()) { m_blocks.Add(block); m_bounds = block; } } void wxSheetSelection::Copy(const wxSheetSelection &source) { m_blocks.Clear(); WX_APPEND_ARRAY(m_blocks, source.GetBlockArray()); m_bounds = source.GetBoundingBlock(); m_minimized = source.IsMinimzed(); m_options = source.GetOptions(); } const wxSheetBlock& wxSheetSelection::GetBlock( size_t index ) const { wxCHECK_MSG(index < m_blocks.GetCount(), wxNullSheetBlock, wxT("Invalid index")); return m_blocks[index]; } void wxSheetSelection::SetBoundingBlock(const wxSheetBlock& block) { m_bounds = wxNullSheetBlock; if (block.IsEmpty()) { Clear(); return; } int n, count = m_blocks.GetCount(); for (n=0; n m_blocks[hi-1]) return hi; while ( lo < hi ) { n = (lo + hi)/2; const wxSheetBlock& tmp = m_blocks[n]; if (tmp == block) return n; if (tmp > block) hi = n; else lo = n + 1; } return lo; } int wxSheetSelection::FindTopRow(int row) const { size_t n, lo = 0, hi = m_blocks.GetCount(); if ((hi == 0) || (row >= m_blocks[0].GetTop())) return 0; if (row < m_blocks[hi-1u].GetTop()) return hi; while ( lo < hi ) { n = (lo + hi)/2; const int tmp_row = m_blocks[n].GetTop(); if (tmp_row > row) hi = n; else lo = n + 1; } return lo; } int wxSheetSelection::IndexIntersects( const wxSheetBlock& block ) const { int n, count = m_blocks.GetCount(); const int bottom_row = block.GetBottom(); if ((count == 0) || !m_bounds.Intersects(block)) return wxNOT_FOUND; for (n=FindTopRow(bottom_row); nClear(); wxArraySheetBlock extraBlocks; wxSheetBlock top, bottom, left, right; // iterate though blocks cutting input block out and adding remainder to end for (n=FindTopRow(bottom_row); nAdd(m_blocks[n].Intersect(block)); if (m_bounds.SideMatches(m_blocks[n]) != wxSHEET_BLOCK_NONE) recalc_bounds = true; if (m_blocks[n].Contains(block)) n = count + 100; // all done, but add cutouts back else n--; m_blocks.RemoveAt(last_n); count--; if (deleted != wxSHEET_BLOCK_ALL) { if ((deleted & wxSHEET_BLOCK_TOP) != 0) extraBlocks.Add(top); if ((deleted & wxSHEET_BLOCK_BOTTOM) != 0) extraBlocks.Add(bottom); if ((deleted & wxSHEET_BLOCK_LEFT) != 0) extraBlocks.Add(left); if ((deleted & wxSHEET_BLOCK_RIGHT) != 0) extraBlocks.Add(right); } } } if (done) { m_minimized = false; const int extra_count = extraBlocks.GetCount(); for (n=0; nClear(); } extra->Add(block); int extra_count = 1; int n, k, count = m_blocks.GetCount(); if (((m_options & wxSHEET_SELECTION_MULTIPLE_SEL) == 0) && (count > 0) && m_bounds.Intersects(block)) { const int bottom_row = block.GetBottom(); wxSheetBlock top, bottom, left, right; // interate though blocks breaking up input block if it's already selected for (n=FindTopRow(bottom_row); nItem(k), top, bottom, left, right); if (combined != wxSHEET_BLOCK_NONE) { extra->RemoveAt(k); extra_count--; k--; if (combined != wxSHEET_BLOCK_ALL) { if ((combined & wxSHEET_BLOCK_TOP) != 0) { extra->Add(top); extra_count++; } if ((combined & wxSHEET_BLOCK_BOTTOM) != 0) { extra->Add(bottom); extra_count++; } if ((combined & wxSHEET_BLOCK_LEFT) != 0) { extra->Add(left); extra_count++; } if ((combined & wxSHEET_BLOCK_RIGHT) != 0) { extra->Add(right); extra_count++; } } if (extra_count == 0) { n = count; break; } } } } } #ifdef CHECK_BLOCK_SORTING for (int m=1; mItem(n)); if (combineNow) Minimize(); return true; } return false; } int wxSheetSelection::InsertBlock(const wxSheetBlock& block) { const int index = FindInsertIndex(block); m_blocks.Insert(block, index); m_bounds = m_bounds.ExpandUnion(block); return index; } void wxSheetSelection::CalculateBounds() { int n, count = m_blocks.GetCount(); if (count == 0) { m_bounds = wxNullSheetBlock; return; } m_bounds = m_blocks[0]; for (n=1; n 0 ? 1000 : 0; for (n=0; n= int(m_blocks.GetCount()))) return wxSHEET_SELECTIONITER_GET_END; // first time here if (m_block_index < 0) { m_block_index = 0; coord = m_coords = m_blocks[m_block_index].GetLeftTop(); return wxSHEET_SELECTIONITER_GET_LEFTTOP; } // at end of block swap to new one if (m_coords == m_blocks[m_block_index].GetRightBottom()) { ++m_block_index; if (m_block_index < int(m_blocks.GetCount())) { coord = m_coords = m_blocks[m_block_index].GetLeftTop(); return wxSHEET_SELECTIONITER_GET_LEFTTOP; } else // past end nothing more to check return wxSHEET_SELECTIONITER_GET_END; } // at end of col, down to next row if (m_coords.GetCol() == m_blocks[m_block_index].GetRight()) { m_coords.SetCol(m_blocks[m_block_index].GetLeft()); m_coords.m_row++; coord = m_coords; return (coord == m_blocks[m_block_index].GetRightBottom()) ? wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM : wxSHEET_SELECTIONITER_GET_NEXTROW; } // increment the col m_coords.m_col++; coord = m_coords; return wxSHEET_SELECTIONITER_GET_NEXTCOL; } wxSheetSelectionIterGet_Type wxSheetSelectionIterator::GetNextReverse(wxSheetCoords &coord) { if ((m_blocks.GetCount() < 1u) || (m_block_index >= int(m_blocks.GetCount()))) return wxSHEET_SELECTIONITER_GET_END; // first time here if (m_block_index < 0) { m_block_index = 0; coord = m_coords = m_blocks[m_block_index].GetRightBottom(); return wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM; } // at end of block swap to new one if (m_coords == m_blocks[m_block_index].GetLeftTop()) { ++m_block_index; if (m_block_index < int(m_blocks.GetCount())) { coord = m_coords = m_blocks[m_block_index].GetRightBottom(); return wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM; } else // past end nothing more to check return wxSHEET_SELECTIONITER_GET_END; } // at left col, up to next row if (m_coords.GetCol() == m_blocks[m_block_index].GetLeft()) { m_coords.SetCol(m_blocks[m_block_index].GetRight()); m_coords.m_row--; coord = m_coords; return (coord == m_blocks[m_block_index].GetLeftTop()) ? wxSHEET_SELECTIONITER_GET_LEFTTOP : wxSHEET_SELECTIONITER_GET_NEXTROW; } // increment the col m_coords.m_col--; coord = m_coords; return wxSHEET_SELECTIONITER_GET_NEXTCOL; } bool wxSheetSelectionIterator::IsInSelection(int row, int col) const { int n, count = m_blocks.GetCount(); for (n=0; nDecRef(); } #else virtual ~wxSheetVariant() { delete m_data; } #endif void Copy(const wxSheetVariant& other); void Copy(const wxVariant& other); void Copy(const wxVariantData& other); void Copy(const wxVariantData* other); wxVariant GetwxVariant() const { return wxVariant(m_data); } wxVariantData* GetData() const { return m_data; } wxSheetVariant& operator=(const wxSheetVariant& other) { Copy(other); return *this; } wxSheetVariant& operator=(const wxVariant& other) { Copy(other); return *this; } wxSheetVariant& operator=(const wxVariantData& other) { Copy(other); return *this; } wxVariantData* m_data; }; void wxSheetVariant::Copy(const wxSheetVariant& other) { Copy(other.GetData()); } void wxSheetVariant::Copy(const wxVariant& other) { Copy(other.GetData()); } void wxSheetVariant::Copy(const wxVariantData& other) { #if wxCHECK_VERSION(2,7,0) m_data->DecRef(); m_data = const_cast(&other); m_data->IncRef(); #else delete m_data; m_data = (wxVariantData*) other.GetClassInfo()->CreateObject(); m_data->Copy(*(wxVariantData*)&other); #endif } void wxSheetVariant::Copy(const wxVariantData* other) { #if wxCHECK_VERSION(2,7,0) m_data->DecRef(); #else delete m_data; #endif if (other) Copy(*other); else m_data = NULL; } WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetVariant, wxArraySheetVariant, class WXDLLIMPEXP_SHEET); #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArraySheetVariant) class WXDLLIMPEXP_SHEET wxSheetRowColVariantContainer { public: wxSheetRowColVariantContainer(bool has_data = false); // Update the number of rows/cols. In numRows/Cols > 0 insert them else // remove them. bool UpdateRows( size_t row, int numRows ); bool UpdateCols( size_t col, int numCols ); protected: wxArraySheetVariant *m_data; }; wxSheetRowColVariantContainer::wxSheetRowColVariantContainer(bool has_data) : m_data(NULL) { if (has_data) m_data = new wxArraySheetVariant; } bool wxSheetRowColVariantContainer::UpdateRows( size_t row, int numRows ) { return false; } bool wxSheetRowColVariantContainer::UpdateCols( size_t col, int numCols ) { return false; } gambit-0.2010.09.01/src/labenski/src/sheetspt.cpp0000644000076500007650000005507211350032206016152 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheetspt.cpp // Purpose: wxSheetSplitter and related classes // Author: John Labenski // Modified by: // Created: 4/1/2004 // RCS-ID: $Id$ // Copyright: (c) John Labenski // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "sheetspt.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #include "wx/sheet/sheetspt.h" #ifndef WX_PRECOMP #include "wx/dcclient.h" #include "wx/settings.h" #include "wx/dcscreen.h" #endif #include "wx/renderer.h" #define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), s, b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); // ---------------------------------------------------------------------------- // wxSheetSplitter // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS( wxSheetSplitter, wxWindow ) BEGIN_EVENT_TABLE( wxSheetSplitter, wxWindow ) EVT_PAINT ( wxSheetSplitter::OnPaint ) EVT_SIZE ( wxSheetSplitter::OnSize ) EVT_MOUSE_EVENTS ( wxSheetSplitter::OnMouse ) EVT_SHEET_SPLIT_BEGIN ( wxID_ANY, wxSheetSplitter::OnSplit ) EVT_SHEET_VIEW_CHANGED ( wxID_ANY, wxSheetSplitter::OnViewChanged ) WX_EVENT_TABLE_CONTROL_CONTAINER(wxSheetSplitter) END_EVENT_TABLE() #if wxCHECK_VERSION(2, 7, 0) WX_DELEGATE_TO_CONTROL_CONTAINER(wxSheetSplitter, wxWindow); #else WX_DELEGATE_TO_CONTROL_CONTAINER(wxSheetSplitter); #endif // wxCHECK_VERSION void wxSheetSplitter::Init() { m_container.SetContainerWindow(this); m_tlSheet = NULL; m_trSheet = NULL; m_blSheet = NULL; m_brSheet = NULL; m_splitMode = wxSHEET_SPLIT_NONE; m_splitCursor = wxSHEET_SPLIT_NONE; //m_sash_width = 4; m_enable_split_vert = true; m_enable_split_horiz = true; } bool wxSheetSplitter::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { // allow TABbing from one window to the other style |= wxTAB_TRAVERSAL; // we draw our border ourselves to blend the sash with it style &= ~wxBORDER_MASK; style |= wxBORDER_NONE; if (!wxWindow::Create(parent, id, pos, size, style|wxCLIP_CHILDREN, name)) return false; //SetForegroundColour(*wxBLACK); // don't erase the splitter background, it's pointless as we overwrite it SetBackgroundStyle(wxBG_STYLE_CUSTOM); return true; } wxSheetSplitter::~wxSheetSplitter() { // stop paint events, probably not necessary anymore, doesn't hurt though if (m_tlSheet) m_tlSheet->GetSheetRefData()->RemoveSheet(m_tlSheet); if (m_trSheet) m_trSheet->GetSheetRefData()->RemoveSheet(m_trSheet); if (m_blSheet) m_blSheet->GetSheetRefData()->RemoveSheet(m_blSheet); if (m_brSheet) m_brSheet->GetSheetRefData()->RemoveSheet(m_brSheet); } bool wxSheetSplitter::Destroy() { // stop paint events, probably not necessary anymore, doesn't hurt though if (m_tlSheet) m_tlSheet->GetSheetRefData()->RemoveSheet(m_tlSheet); if (m_trSheet) m_trSheet->GetSheetRefData()->RemoveSheet(m_trSheet); if (m_blSheet) m_blSheet->GetSheetRefData()->RemoveSheet(m_blSheet); if (m_brSheet) m_brSheet->GetSheetRefData()->RemoveSheet(m_brSheet); return wxWindow::Destroy(); } void wxSheetSplitter::Initialize(wxSheet* sheet) { wxCHECK_RET(sheet && (sheet->GetParent() == this), wxT("Invalid sheet or parent")); m_tlSheet = sheet; // In >= wx25 a window's min size is set when created with a size, breaks splitting m_tlSheet->SetSizeHints(-1, -1); ConfigureWindows(); LayoutWindows(); } wxSheet* wxSheetSplitter::CreateSheet(wxWindowID id) { wxCHECK_MSG(m_tlSheet, NULL, wxT("Unable to create wxSheet child in splitter, splitter not initialized yet.")); wxSheetSplitterEvent event(GetId(), wxEVT_SHEET_SPLIT_CREATE_SHEET); event.SetEventObject(this); event.SetExtraLong(id); GetEventHandler()->ProcessEvent(event); if (event.GetSheet()) { wxSheet *sheet = event.GetSheet(); wxCHECK_MSG(sheet->GetParent() == this, sheet, wxT("Invalid parent for wxSheet in splitter")); return sheet; } return m_tlSheet->Clone(id); } wxSheet* wxSheetSplitter::CreateTopRightSheet(wxWindowID id) { wxSheet *sheet = CreateSheet(id); wxCHECK_MSG(sheet, NULL, wxT("Unable to create wxSheet child in splitter")); sheet->RefSheet(m_tlSheet); sheet->GetRowLabelWindow()->Show(false); sheet->GetCornerLabelWindow()->Show(false); sheet->EnableSplitHorizontally(false); sheet->SetGridOrigin(m_tlSheet->GetGridOrigin()); return sheet; } wxSheet* wxSheetSplitter::CreateBottomLeftSheet(wxWindowID id) { wxSheet *sheet = CreateSheet(id); wxCHECK_MSG(sheet, NULL, wxT("Unable to create wxSheet child in splitter")); sheet->RefSheet(m_tlSheet); sheet->GetColLabelWindow()->Show(false); sheet->GetCornerLabelWindow()->Show(false); sheet->EnableSplitVertically(false); sheet->SetGridOrigin(m_tlSheet->GetGridOrigin()); return sheet; } wxSheet* wxSheetSplitter::CreateBottomRightSheet(wxWindowID id) { wxSheet *sheet = CreateSheet(id); wxCHECK_MSG(sheet, NULL, wxT("Unable to create wxSheet child in splitter")); sheet->RefSheet(m_tlSheet); sheet->GetRowLabelWindow()->Show(false); sheet->GetColLabelWindow()->Show(false); sheet->GetCornerLabelWindow()->Show(false); sheet->EnableSplitVertically(false); sheet->EnableSplitHorizontally(false); sheet->SetGridOrigin(m_trSheet->GetGridOrigin()); return sheet; } void wxSheetSplitter::SplitVertically(int y_pos, bool sendEvt) { wxCHECK_RET(m_tlSheet, wxT("Unable to split vertically, not initialized yet.")); wxCHECK_RET(!IsSplitVertically(), wxT("Already vertically split")); wxCHECK_RET((y_pos >= m_minSize.y) || (y_pos < GetClientSize().GetHeight() - m_minSize.y), wxT("Invalid vertical split position")); m_blSheet = CreateBottomLeftSheet(); wxCHECK_RET(m_blSheet, wxT("Unable to create wxSheet child in splitter")); if (m_trSheet && !m_brSheet) { m_brSheet = CreateBottomRightSheet(); wxCHECK_RET(m_brSheet, wxT("Unable to create wxSheet child in splitter")); } m_splitPos.y = y_pos; ConfigureWindows(); LayoutWindows(); Refresh(false); if (sendEvt) SendEvent( wxEVT_SHEET_SPLIT_CHANGED, true ); } void wxSheetSplitter::SplitHorizontally(int x_pos, bool sendEvt) { wxCHECK_RET(m_tlSheet, wxT("Unable to split horizontally, not initialized yet.")); wxCHECK_RET(!IsSplitHorizontally(), wxT("Already horizontally split")); wxCHECK_RET((x_pos >= m_minSize.x) || (x_pos < GetClientSize().GetWidth() - m_minSize.x), wxT("Invalid horizontal split position")); m_trSheet = CreateTopRightSheet(); wxCHECK_RET(m_trSheet, wxT("Unable to create wxSheet child in splitter")); if (m_blSheet && !m_brSheet) { m_brSheet = CreateBottomRightSheet(); wxCHECK_RET(m_brSheet, wxT("Unable to create wxSheet child in splitter")); } m_splitPos.x = x_pos; ConfigureWindows(); LayoutWindows(); Refresh(false); if (sendEvt) SendEvent( wxEVT_SHEET_SPLIT_CHANGED, false ); } void wxSheetSplitter::UnsplitVertically(bool remove_bottom, bool sendEvt) { wxCHECK_RET(IsSplitVertically(), wxT("Not vertically split")); wxPoint blOrigin = m_blSheet->GetGridOrigin(); m_blSheet->Show(false); m_blSheet->Destroy(); m_blSheet = NULL; if (m_brSheet) { wxPoint brOrigin = m_brSheet->GetGridOrigin(); m_brSheet->Show(false); m_brSheet->Destroy(); m_brSheet = NULL; if (!remove_bottom) m_trSheet->SetGridOrigin(brOrigin); } if (!remove_bottom) m_tlSheet->SetGridOrigin(blOrigin); m_splitPos.y = 0; ConfigureWindows(); LayoutWindows(); Refresh(false); if (sendEvt) SendEvent( wxEVT_SHEET_SPLIT_UNSPLIT, true ); } void wxSheetSplitter::UnsplitHorizontally(bool remove_right, bool sendEvt) { wxCHECK_RET(IsSplitHorizontally(), wxT("Not horizontally split")); wxPoint trOrigin = m_trSheet->GetGridOrigin(); m_trSheet->Show(false); m_trSheet->Destroy(); m_trSheet = NULL; if (m_brSheet) { wxPoint brOrigin = m_brSheet->GetGridOrigin(); m_brSheet->Show(false); m_brSheet->Destroy(); m_brSheet = NULL; if (!remove_right) m_blSheet->SetGridOrigin(brOrigin); } if (!remove_right) m_tlSheet->SetGridOrigin(trOrigin); m_splitPos.x = 0; ConfigureWindows(); LayoutWindows(); Refresh(false); if (sendEvt) SendEvent( wxEVT_SHEET_SPLIT_UNSPLIT, false ); } void wxSheetSplitter::SetVerticalSplitPosition(int y_pos, bool sendEvt) { wxCHECK_RET(m_tlSheet, wxT("wxSheetSplitter not initialized")); y_pos = GetAdjustedVerticalSashPosition(y_pos); wxSize clientSize(GetClientSize()); int border_size = GetBorderSize(); if ((y_pos <= border_size) || (y_pos >= clientSize.y-border_size)) { if (IsSplitVertically()) UnsplitVertically(!(y_pos <= border_size), sendEvt); } else if (!IsSplitVertically()) { SplitVertically(y_pos, sendEvt); } else if (m_splitPos.y != y_pos) { m_splitPos.y = y_pos; LayoutWindows(); Refresh(false); if (sendEvt) SendEvent( wxEVT_SHEET_SPLIT_CHANGED, true ); } } void wxSheetSplitter::SetHorizontalSplitPosition(int x_pos, bool sendEvt) { wxCHECK_RET(m_tlSheet, wxT("wxSheetSplitter not horizontally split")); x_pos = GetAdjustedHorizontalSashPosition(x_pos); wxSize clientSize(GetClientSize()); int border_size = GetBorderSize(); if ((x_pos <= border_size) || (x_pos >= clientSize.x-border_size)) { if (IsSplitHorizontally()) UnsplitHorizontally(!(x_pos <= border_size), sendEvt); } else if (!IsSplitHorizontally()) { SplitHorizontally(x_pos, sendEvt); } else if (m_splitPos.x != x_pos) { m_splitPos.x = x_pos; LayoutWindows(); Refresh(false); if (sendEvt) SendEvent( wxEVT_SHEET_SPLIT_CHANGED, false ); } } int wxSheetSplitter::GetAdjustedVerticalSashPosition(int pos) const { int width = GetClientSize().GetWidth(); if (width < m_minSize.x) pos = width/2; else if (pos <= m_minSize.x) pos = m_minSize.x; else if (pos >= width - m_minSize.x) pos = width - m_minSize.x; return pos; } int wxSheetSplitter::GetAdjustedHorizontalSashPosition(int pos) const { int height = GetClientSize().GetHeight(); if (height < m_minSize.y) pos = height/2; else if (pos <= m_minSize.y) return m_minSize.y; else if (pos >= height - m_minSize.y) return height - m_minSize.y; return pos; } void wxSheetSplitter::ConfigureWindows() { if (!m_tlSheet) return; if (m_tlSheet) { int sb_mode = (m_trSheet ? wxSheet::SB_VERT_NEVER : wxSheet::SB_AS_NEEDED) | (m_blSheet ? wxSheet::SB_HORIZ_NEVER : wxSheet::SB_AS_NEEDED); m_tlSheet->SetScrollBarMode(sb_mode); m_tlSheet->EnableSplitVertically(!m_blSheet && m_enable_split_vert); m_tlSheet->EnableSplitHorizontally(!m_trSheet && m_enable_split_horiz); } if (m_trSheet) { int sb_mode = (m_brSheet ? wxSheet::SB_HORIZ_NEVER : wxSheet::SB_AS_NEEDED); m_trSheet->SetHorizontalScrollBarMode(sb_mode); m_trSheet->EnableSplitVertically(!m_brSheet && m_enable_split_vert); } if (m_blSheet) { int sb_mode = (m_brSheet ? wxSheet::SB_VERT_NEVER : wxSheet::SB_AS_NEEDED); m_blSheet->SetVerticalScrollBarMode(sb_mode); m_blSheet->EnableSplitHorizontally(!m_brSheet && m_enable_split_horiz); } } void wxSheetSplitter::LayoutWindows() { if (!m_tlSheet) return; wxSize clientSize(GetClientSize()); int x = m_splitPos.x; int y = m_splitPos.y; int sash_size = GetSashSize(); int border_size = GetBorderSize(); if (!m_trSheet) x = clientSize.x - 2*border_size; /* else if (m_trSheet && (x > clientSize.x - m_minSize.x)) { // fix sash position to stay within visible part of window x = clientSize.x - m_minSize.x; if (x < sash_size + border_size + 2) x = clientSize.x/2; m_splitPos.x = x; } */ if (!m_blSheet) y = clientSize.y - 2*border_size; /* else if (m_blSheet && (y > clientSize.y - m_minSize.y)) { // fix sash position to stay within visible part of window y = clientSize.y - m_minSize.y; if (y < sash_size + border_size + 2) y = clientSize.y/2; m_splitPos.y = y; } */ wxRect rect = wxRect(border_size, border_size, x, y); if (m_tlSheet->GetRect() != rect) m_tlSheet->SetSize(rect); if (m_trSheet) { rect = wxRect(x+sash_size, border_size, clientSize.x-x-sash_size-border_size, y); if (m_trSheet->GetRect() != rect) m_trSheet->SetSize(rect); } if (m_blSheet) { rect = wxRect(border_size, y+sash_size, x, clientSize.y-y-sash_size-border_size); if (m_blSheet->GetRect() != rect) m_blSheet->SetSize(rect); } if (m_brSheet) { rect = wxRect(x+sash_size, y+sash_size, clientSize.x-x-sash_size-border_size, clientSize.y-y-sash_size-border_size); if (m_brSheet->GetRect() != rect) m_brSheet->SetSize(rect); } } void wxSheetSplitter::OnSize( wxSizeEvent& event ) { m_splitPos.x = GetAdjustedVerticalSashPosition(m_splitPos.x); m_splitPos.y = GetAdjustedHorizontalSashPosition(m_splitPos.y); LayoutWindows(); event.Skip(); } void wxSheetSplitter::OnViewChanged(wxSheetEvent& event) { wxSheet *sheet = (wxSheet*)event.GetEventObject(); wxPoint origin = sheet->GetGridOrigin(); if (sheet == m_tlSheet) { if (m_trSheet) m_trSheet->SetGridOrigin(-1, origin.y); if (m_blSheet) m_blSheet->SetGridOrigin(origin.x, -1); } else if (sheet == m_trSheet) { if (m_tlSheet) m_tlSheet->SetGridOrigin(-1, origin.y); if (m_brSheet) m_brSheet->SetGridOrigin(origin.x, -1); } else if (sheet == m_blSheet) { if (m_brSheet) m_brSheet->SetGridOrigin(-1, origin.y); if (m_tlSheet) m_tlSheet->SetGridOrigin(origin.x, -1); } else if (sheet == m_brSheet) { if (m_blSheet) m_blSheet->SetGridOrigin(-1, origin.y); if (m_trSheet) m_trSheet->SetGridOrigin(origin.x, -1); } } void wxSheetSplitter::OnSplit(wxSheetSplitterEvent& event) { // pass event to parent to see if they want to veto it first GetParent()->GetEventHandler()->ProcessEvent(event); if (!event.IsAllowed()) return; if (!HasCapture()) CaptureMouse(); m_splitMode = event.IsVerticalSplit() ? wxSHEET_SPLIT_VERTICAL : wxSHEET_SPLIT_HORIZONTAL; SetMouseCursor(m_splitMode); // out of bounds, don't draw initial tracker m_mousePos = wxPoint(-10, -10); } void wxSheetSplitter::OnMouse(wxMouseEvent& event) { wxPoint mousePos(event.GetPosition()); if (event.LeftDown()) { m_splitMode = SashHitTest(mousePos); SetMouseCursor(m_splitMode); if ((m_splitMode != wxSHEET_SPLIT_NONE) && !HasCapture()) CaptureMouse(); } else if (event.Moving()) { SetMouseCursor(SashHitTest(mousePos)); } else if (event.Dragging() && HasCapture()) { DrawSashTracker(m_mousePos.x, m_mousePos.y); bool vert = (m_splitMode == wxSHEET_SPLIT_VERTICAL); wxSheetSplitterEvent sEvent(GetId(), wxEVT_SHEET_SPLIT_CHANGING); sEvent.SetEventObject(this); sEvent.m_vert_split = vert; sEvent.SetSashPosition(vert ? m_mousePos.y : m_mousePos.x); if (DoSendEvent(sEvent)) { m_mousePos = mousePos; if (vert) m_mousePos.x = sEvent.GetSashPosition(); else m_mousePos.y = sEvent.GetSashPosition(); } DrawSashTracker(m_mousePos.x, m_mousePos.y); } else if (event.LeftUp() && HasCapture()) { ReleaseMouse(); DrawSashTracker(m_mousePos.x, m_mousePos.y); m_mousePos = mousePos; if (m_splitMode == wxSHEET_SPLIT_VERTICAL) SetVerticalSplitPosition(m_mousePos.y, true); else if (m_splitMode == wxSHEET_SPLIT_HORIZONTAL) SetHorizontalSplitPosition(m_mousePos.x, true); m_mousePos = wxPoint(-10, -10); m_splitMode = wxSHEET_SPLIT_NONE; } else if (event.LeftDClick()) { m_splitMode = SashHitTest(mousePos); if (SendEvent(wxEVT_SHEET_SPLIT_DOUBLECLICKED, m_splitMode == wxSHEET_SPLIT_VERTICAL)) { if ((m_minSize.y == 0) && (m_splitMode == wxSHEET_SPLIT_VERTICAL)) UnsplitVertically(true, true); else if ((m_minSize.x == 0) && (m_splitMode == wxSHEET_SPLIT_HORIZONTAL)) UnsplitHorizontally(true, true); } } else if (event.Leaving() || event.Entering()) { SetMouseCursor(wxSHEET_SPLIT_NONE); } } void wxSheetSplitter::OnPaint( wxPaintEvent& WXUNUSED(event) ) { wxPaintDC dc(this); DrawSash(dc); } void wxSheetSplitter::DrawSash(wxDC &dc) { wxSize clientSize(GetClientSize()); bool draw_horiz = (m_splitPos.x > 0) && (m_splitPos.x < clientSize.x); bool draw_vert = (m_splitPos.y > 0) && (m_splitPos.y < clientSize.y); #if 0 // old method where we just draw a black line if (draw_horiz || draw_vert) { int sash_size = GetSashSize(); dc.SetPen(wxPen(GetForegroundColour(), sash_size, wxSOLID)); if (draw_horiz) dc.DrawLine(m_splitPos.x + sash_size/2, 0, m_splitPos.x + sash_size/2, clientSize.y); if (draw_vert) dc.DrawLine(0, m_splitPos.y + sash_size/2, clientSize.x, m_splitPos.y + sash_size/2); } #else wxRendererNative& ren = wxRendererNative::Get(); if (HasFlag(wxSP_3DBORDER)) ren.DrawSplitterBorder(this, dc, GetClientRect()); // don't draw sash if we're configured to not show it if ( HasFlag(wxSP_NOSASH) ) return; if (draw_horiz) ren.DrawSplitterSash(this, dc, clientSize, m_splitPos.x, wxVERTICAL, (m_splitCursor == wxSHEET_SPLIT_HORIZONTAL) ? (int)wxCONTROL_CURRENT : 0); if (draw_vert) ren.DrawSplitterSash(this, dc, clientSize, m_splitPos.y, wxHORIZONTAL, (m_splitCursor == wxSHEET_SPLIT_VERTICAL) ? (int)wxCONTROL_CURRENT : 0); #endif } void wxSheetSplitter::DrawSashTracker(int x, int y) { if ((x < 0) && (y < 0)) return; int w, h; GetClientSize(&w, &h); int x1, y1; int x2, y2; int sash_size = GetSashSize(); int border_size = GetBorderSize(); if ( m_splitMode == wxSHEET_SPLIT_HORIZONTAL ) { x1 = x2 = ((x > w) ? w : ((x < 0) ? 0 : x)) + sash_size/2; y1 = border_size; y2 = h-border_size; } else { x1 = border_size; x2 = w-border_size; y1 = y2 = ((y > h) ? h : ((y < 0) ? 0 : y)) + sash_size/2; } ClientToScreen(&x1, &y1); ClientToScreen(&x2, &y2); wxScreenDC screenDC; screenDC.SetLogicalFunction(wxINVERT); screenDC.SetPen(wxPen(GetForegroundColour(), sash_size, wxSOLID)); screenDC.SetBrush(*wxTRANSPARENT_BRUSH); screenDC.DrawLine(x1, y1, x2, y2); screenDC.SetLogicalFunction(wxCOPY); } int wxSheetSplitter::GetSashSize() const { return wxRendererNative::Get().GetSplitterParams(this).widthSash; } int wxSheetSplitter::GetBorderSize() const { return wxRendererNative::Get().GetSplitterParams(this).border; } int wxSheetSplitter::SashHitTest(const wxPoint& pt) const { if ((m_splitPos.x <= 0) && (m_splitPos.y <= 0)) return wxSHEET_SPLIT_NONE; wxSize clientSize = GetClientSize(); int sash_size = GetSashSize(); int border_size = GetBorderSize(); if (m_trSheet && (m_splitPos.x > 0)) { wxRect rect(m_splitPos.x, border_size, sash_size, clientSize.y-2*border_size); #if wxCHECK_VERSION(2,7,0) if (rect.Contains(pt)) #else if (rect.Inside(pt)) #endif return wxSHEET_SPLIT_HORIZONTAL; } if (m_blSheet && (m_splitPos.y > 0)) { wxRect rect(border_size, m_splitPos.y, clientSize.x-2*border_size, sash_size); #if wxCHECK_VERSION(2,7,0) if (rect.Contains(pt)) #else if (rect.Inside(pt)) #endif return wxSHEET_SPLIT_VERTICAL; } return wxSHEET_SPLIT_NONE; } void wxSheetSplitter::SetMouseCursor(int sheet_split_mode) { if (m_splitCursor == sheet_split_mode) return; m_splitCursor = sheet_split_mode; wxClientDC dc(this); DrawSash(dc); switch (sheet_split_mode) { case wxSHEET_SPLIT_VERTICAL : SetCursor(wxCURSOR_SIZENS); break; case wxSHEET_SPLIT_HORIZONTAL : SetCursor(wxCURSOR_SIZEWE); break; case wxSHEET_SPLIT_NONE : default : SetCursor(*wxSTANDARD_CURSOR); } } bool wxSheetSplitter::SendEvent( wxEventType type, bool vert_split ) { wxSheetSplitterEvent event(GetId(), type); event.SetEventObject(this); event.m_vert_split = vert_split; event.m_sash_pos = vert_split ? m_splitPos.y : m_splitPos.x; return DoSendEvent(event); } bool wxSheetSplitter::DoSendEvent( wxSheetSplitterEvent& event ) { bool claimed = GetEventHandler()->ProcessEvent(event); bool vetoed = !event.IsAllowed(); return !vetoed && !claimed; } // ---------------------------------------------------------------------------- // events // ---------------------------------------------------------------------------- DEFINE_EVENT_TYPE(wxEVT_SHEET_SPLIT_BEGIN) DEFINE_EVENT_TYPE(wxEVT_SHEET_SPLIT_CHANGING) DEFINE_EVENT_TYPE(wxEVT_SHEET_SPLIT_CHANGED) DEFINE_EVENT_TYPE(wxEVT_SHEET_SPLIT_DOUBLECLICKED) DEFINE_EVENT_TYPE(wxEVT_SHEET_SPLIT_UNSPLIT) DEFINE_EVENT_TYPE(wxEVT_SHEET_SPLIT_CREATE_SHEET) gambit-0.2010.09.01/src/labenski/src/sheettbl.cpp0000644000076500007650000011166711350032206016130 00000000000000/////////////////////////////////////////////////////////////////////////////// // Name: sheettbl.cpp // Purpose: wxSheetTable and related classes // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn) // Modified by: John Labenski, Robin Dunn, Vadim Zeitlin // Created: 1/08/1999 // RCS-ID: $Id$ // Copyright: (c) John Labenski, Michael Bedward (mbedward@ozemail.com.au) // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "sheettbl.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #include "wx/sheet/sheettbl.h" #include "wx/sheet/sheet.h" #include // used in GetDefaultColLabelValue #ifndef WX_PRECOMP #endif // WX_PRECOMP #define PRINT_BLOCK(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); #define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); #define wxStrF wxString::Format // ---------------------------------------------------------------------------- #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArrayPairArrayIntSheetString) DEFINE_PAIRED_INT_DATA_ARRAYS(wxString, wxPairArrayIntSheetString) DEFINE_PAIRED_INT_DATA_ARRAYS(wxPairArrayIntSheetString, wxPairArrayIntPairArraySheetString) #if !wxUSE_GRID WX_DEFINE_OBJARRAY(wxSheetStringArray) // else use wxGridStringArray #endif // wxUSE_GRID // ---------------------------------------------------------------------------- // wxArrayStringUpdatePos - UpdatePos for wxArrayString // ---------------------------------------------------------------------------- bool wxArrayStringUpdatePos(wxArrayString& arr, size_t pos, int num, bool no_error) { if (num == 0) return false; else if (num > 0) { // if no_error check if <= GetCount, else let array error out if (!no_error || (pos <= arr.GetCount())) arr.Insert( wxEmptyString, pos, num ); } else // if (num < 0) { const int count = arr.GetCount(); if (no_error && (int(pos) - num > count)) { num = -(count - int(pos)); if ((num >= 0) || (count == 0)) return false; } else { wxCHECK_MSG( int(pos) - num <= count, false, wxStrF(wxT("Called wxArrayStringUpdatePos(pos=%d, N=%d)\nPos value is invalid for present array with %d elements"), int(pos), num, count) ); } if ((pos == 0u) && (num == count)) arr.Clear(); else arr.RemoveAt( pos, -num ); } return true; } // ---------------------------------------------------------------------------- // wxSheetDataBase // ---------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS( wxSheetValueProviderBase, wxObject ) void wxSheetValueProviderBase::Clear() { const int numRows = GetNumberRows(); const int numCols = GetNumberCols(); if (numRows > 0) UpdateRows(0, -numRows); if (numCols > 0) UpdateCols(0, -numCols); } void wxSheetValueProviderBase::Copy(const wxSheetValueProviderBase& other) { Clear(); const int numRows = other.GetNumberRows(); const int numCols = other.GetNumberCols(); m_options = other.GetOptions(); UpdateRows(0, numRows); UpdateCols(0, numCols); wxSheetCoords c; for (c.m_row = 0; c.m_row < numRows; c.m_row++) { for (c.m_col = 0; c.m_col < numCols; c.m_col++) { wxString val(other.GetValue(c)); if (!val.IsEmpty()) SetValue(c, val); } } } // ---------------------------------------------------------------------------- // wxSheetStringData - base class for a string provider class for the table // ---------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS( wxSheetValueProviderString, wxSheetValueProviderBase ) wxSheetValueProviderString::wxSheetValueProviderString(size_t numRows, size_t numCols, int options) :wxSheetValueProviderBase(0, 0, options) { m_numRows += numRows; m_numCols += numCols; DoUpdateRows(0, HasOption(wxSHEET_ValueProviderColPref) ? numRows : numCols); DoUpdateCols(0, HasOption(wxSHEET_ValueProviderColPref) ? numCols : numRows); } wxString wxSheetValueProviderString::GetValue( const wxSheetCoords& coords_ ) const { wxCHECK_MSG(ContainsCell(coords_), wxEmptyString, wxT("Invalid coords")); wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); //wxPrintf(wxT("RC %d %d - NumRC %d %d DataRC %d %d '%s'\n"), coords_.m_row, coords_.m_col, m_numRows, m_numCols, // m_data.GetCount(), int(m_data.GetCount()) > coords.m_col ? m_data[coords.m_col].GetCount() : 0, // wxDateTime::Now().FormatISOTime().c_str()); if ((int(m_data.GetCount()) > coords.m_row) && (int(m_data[coords.m_row].GetCount()) > coords.m_col)) return m_data[coords.m_row][coords.m_col]; return wxEmptyString; } void wxSheetValueProviderString::SetValue( const wxSheetCoords& coords_, const wxString& value ) { wxCHECK_RET(ContainsCell(coords_), wxT("Invalid coords")); wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); // add "rows" as necessary to store value int count = m_data.GetCount(); if (count <= coords.m_row) { wxArrayString sa; sa.Add( wxEmptyString, 1+coords.m_col ); m_data.Insert( sa, count, 1+coords.m_row-count ); } else // believe it or not - NOT having this else statement is 10% faster in gcc { // add "cols" as necessary to store value count = m_data[coords.m_row].GetCount(); if (count <= coords.m_col) { m_data.Item(coords.m_row).Insert( wxEmptyString, count, 1+coords.m_col-count ); } } m_data[coords.m_row][coords.m_col] = value; } int wxSheetValueProviderString::GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const { wxCHECK_MSG(ContainsCell(coords), coords.m_col - 1, wxT("Invalid coords")); if (HasOption(wxSHEET_ValueProviderColPref)) { if (int(m_data.GetCount()) <= coords.m_row) return -1; if (int(m_data[coords.m_row].GetCount()) < coords.m_col) return m_data[coords.m_row].GetCount() - 1; } // the else case cannot be optimized - just use default return coords.m_col - 1; } bool wxSheetValueProviderString::UpdateRows( size_t row, int numRows ) { wxSHEET_CHECKUPDATE_MSG(row, numRows, m_numRows, false); m_numRows += numRows; return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateRows(row, numRows) : DoUpdateCols(row, numRows); } bool wxSheetValueProviderString::UpdateCols( size_t col, int numCols ) { wxSHEET_CHECKUPDATE_MSG(col, numCols, m_numCols, false); m_numCols += numCols; return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateCols(col, numCols) : DoUpdateRows(col, numCols); } bool wxSheetValueProviderString::DoUpdateRows( size_t row, int numRows ) { // get things right before calling this, remember the rows may not be // filled completely and this won't error out const int curNumRows = m_data.GetCount(); //const int curNumCols = curNumRows > 0 ? m_data.Item(0).GetCount() : m_numCols; if (numRows == 0) return false; else if (numRows > 0) { if (curNumRows > int(row)) // only insert, no need to append { wxArrayString sa; m_data.Insert( sa, row, numRows ); } } else // if (numRows < 0) { if (curNumRows > int(row)) { m_data.RemoveAt( row, wxMin(curNumRows-int(row), -numRows) ); } } return true; } bool wxSheetValueProviderString::DoUpdateCols( size_t col, int numCols ) { // only insert or delete cols, no need to append const int curNumRows = m_data.GetCount(); if (numCols == 0) return false; else if (numCols > 0) { for ( int row = 0; row < curNumRows; row++ ) { if (m_data[row].GetCount() > col) m_data[row].Insert( wxEmptyString, col, numCols ); } } else // if (numCols < 0) { for ( int row = 0; row < curNumRows; row++ ) { const int curNumCols = m_data[row].GetCount(); if (curNumCols > int(col)) { m_data[row].RemoveAt( col, wxMin(curNumCols-int(col), -numCols) ); } } } return true; } void wxSheetValueProviderString::SetOptions(int options) { if (options == m_options) return; wxSheetValueProviderString data(0,0,options); data.Copy(*this); m_options = options; Copy(data); } //----------------------------------------------------------------------------- // wxPairArrayIntPairArraySheetString - string data //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS( wxSheetValueProviderSparseString, wxSheetValueProviderBase ) wxSheetValueProviderSparseString::wxSheetValueProviderSparseString(size_t numRows, size_t numCols, int options) :wxSheetValueProviderBase(0, 0, options) { m_numRows += numRows; m_numCols += numCols; DoUpdateRows(0, HasOption(wxSHEET_ValueProviderColPref) ? numRows : numCols); DoUpdateCols(0, HasOption(wxSHEET_ValueProviderColPref) ? numCols : numRows); } wxString wxSheetValueProviderSparseString::GetValue( const wxSheetCoords& coords_ ) const { wxCHECK_MSG(ContainsCell(coords_), wxEmptyString, wxT("Invalid coords")); wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); const int rowPos = m_data.FindIndex(coords.m_row); if (rowPos != wxNOT_FOUND) return m_data.GetItemValue(rowPos).GetValue(coords.m_col); return wxEmptyString; } void wxSheetValueProviderSparseString::SetValue( const wxSheetCoords& coords_, const wxString& value ) { wxCHECK_RET(ContainsCell(coords_), wxT("Invalid coords")); wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); const int rowPos = m_data.FindIndex(coords.m_row); if (value.IsEmpty()) { // remove the value if empty if (rowPos != wxNOT_FOUND) { m_data.GetItemValue(rowPos).RemoveValue(coords.m_col); // remove this row if empty if (m_data.GetItemValue(rowPos).GetCount() == 0) m_data.RemoveAt(rowPos); } } else { if (rowPos == wxNOT_FOUND) m_data.GetOrCreateValue(coords.m_row).SetValue(coords.m_col, value); else m_data.GetItemValue(rowPos).SetValue(coords.m_col, value); } } bool wxSheetValueProviderSparseString::HasValue( const wxSheetCoords& coords_ ) const { wxCHECK_MSG(ContainsCell(coords_), false, wxT("Invalid coords")); wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); const int rowPos = m_data.FindIndex(coords.m_row); if (rowPos == wxNOT_FOUND) return false; return m_data.GetItemValue(rowPos).FindIndex(coords.m_col) != wxNOT_FOUND; } int wxSheetValueProviderSparseString::GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const { wxCHECK_MSG(ContainsCell(coords), coords.m_col - 1, wxT("Invalid coords")); if (HasOption(wxSHEET_ValueProviderColPref)) { const int rowPos = m_data.FindIndex(coords.m_row); if (rowPos != wxNOT_FOUND) { // pos == 0 meaning nothing to left, == count for col > last filled const int colPos = m_data.GetItemValue(rowPos).FindInsertIndex(coords.m_col); if (colPos > 0) return m_data.GetItemValue(rowPos).GetItemKey(colPos-1); } return -1; } return coords.m_col - 1; } bool wxSheetValueProviderSparseString::UpdateRows( size_t row, int numRows ) { wxSHEET_CHECKUPDATE_MSG(row, numRows, m_numRows, false) m_numRows += numRows; return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateRows(row, numRows) : DoUpdateCols(row, numRows); } bool wxSheetValueProviderSparseString::UpdateCols( size_t col, int numCols ) { wxSHEET_CHECKUPDATE_MSG(col, numCols, m_numRows, false) m_numCols += numCols; return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateCols(col, numCols) : DoUpdateRows(col, numCols); } bool wxSheetValueProviderSparseString::DoUpdateRows( size_t row, int numRows ) { return m_data.UpdatePos(row, numRows); } bool wxSheetValueProviderSparseString::DoUpdateCols( size_t col, int numCols ) { bool done = false; size_t row, rowCount = m_data.GetCount(); for (row=0; rowsecond.find(coords.m_col); if (col_iter != row_iter->second.end()) return col_iter->second; } return wxEmptyString; } void wxSheetValueProviderHashString::SetValue( const wxSheetCoords& coords_, const wxString& value ) { wxCHECK_RET(ContainsCell(coords_), wxT("Invalid coords")); wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); wxSheetStringHashStringHash::iterator row_iter = m_data.find(coords.m_row); if (row_iter == m_data.end()) { wxSheetStringHash colHash; colHash[coords.m_col] = value; m_data[coords.m_row] = colHash; return; } row_iter->second[coords.m_col] = value; } bool wxSheetValueProviderHashString::HasValue( const wxSheetCoords& coords_ ) const { wxCHECK_MSG(ContainsCell(coords_), false, wxT("Invalid coords")); wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); wxSheetStringHashStringHash::const_iterator row_iter = m_data.find(coords.m_row); if (row_iter != m_data.end()) { wxSheetStringHash::const_iterator col_iter = row_iter->second.find(coords.m_col); if (col_iter != row_iter->second.end()) return true; } return false; } int wxSheetValueProviderHashString::GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const { wxCHECK_MSG(ContainsCell(coords), coords.m_col - 1, wxT("Invalid coords")); if (HasOption(wxSHEET_ValueProviderColPref)) { wxSheetStringHashStringHash::const_iterator row_iter = m_data.find(coords.m_row); if (row_iter == m_data.end()) return -1; } return coords.m_col - 1; } bool wxSheetValueProviderHashString::UpdateRows( size_t row, int numRows ) { wxSHEET_CHECKUPDATE_MSG(row, numRows, m_numRows, false) bool append = (int(row) == m_numRows); m_numRows += numRows; if (!m_numCols || !m_numRows) { ClearValues(); return true; } if (!append) return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateRows(row, numRows) : DoUpdateCols(row, numRows); return true; } bool wxSheetValueProviderHashString::UpdateCols( size_t col, int numCols ) { wxSHEET_CHECKUPDATE_MSG(col, numCols, m_numRows, false) bool append = (int(col) == m_numRows); m_numCols += numCols; if (!m_numCols || !m_numRows) { ClearValues(); return true; } if (!append) return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateCols(col, numCols) : DoUpdateRows(col, numCols); return true; } bool wxSheetValueProviderHashString::DoUpdateRows( size_t row, int numRows ) { if (numRows == 0) return false; else if (numRows > 0) { if (!m_data.empty()) // FIXME only insert, already checked append { wxFAIL_MSG(wxT("Not implemented")); } } else // if (numRows < 0) { const int row_end = row + numRows; wxSheetStringHashStringHash::iterator row_iter = m_data.begin(); while (row_iter != m_data.end()) { int data_row = row_iter->first; if ((data_row >= int(row)) && (data_row < row_end)) { wxSheetStringHashStringHash::iterator it = row_iter; row_iter++; m_data.erase(it); } else row_iter++; } } return true; } bool wxSheetValueProviderHashString::DoUpdateCols( size_t col, int numCols ) { if (numCols == 0) return false; else if (numCols > 0) { if (!m_data.empty()) // FIXME only insert, already checked append { wxFAIL_MSG(wxT("Not implemented")); } } else // if (numCols < 0) { const int col_end = col + numCols; wxSheetStringHashStringHash::iterator row_iter = m_data.begin(); while (row_iter != m_data.end()) { wxSheetStringHash::iterator col_iter = row_iter->second.begin(); while (col_iter != row_iter->second.end()) { int data_col = col_iter->first; if ((data_col >= int(col)) && (data_col < col_end)) { wxSheetStringHash::iterator it = col_iter; col_iter++; row_iter->second.erase(it); } else col_iter++; } row_iter++; } } return true; } void wxSheetValueProviderHashString::SetOptions(int options) { if (options == m_options) return; wxSheetValueProviderHashString data(0,0,options); data.Copy(*this); m_options = options; Copy(data); } #endif // wxSHEET_USE_VALUE_PROVIDER_HASH // ---------------------------------------------------------------------------- // wxSheetTable // ---------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS( wxSheetTable, wxObject ) wxSheetTable::wxSheetTable(wxSheet *view) :wxObject(), m_view(view), m_attrProvider(NULL), m_own_attr_provider(true), m_gridCellValues(NULL), m_own_grid_cell_values(true), m_rowLabelValues(NULL), m_own_row_label_values(true), m_colLabelValues(NULL), m_own_col_label_values(true), m_spannedCells(NULL), m_own_spanned_cells(true) { m_spannedCells = new wxSheetSelection(); } wxSheetTable::~wxSheetTable() { SetAttrProvider(NULL, true); SetGridCellValueProvider(NULL, true); SetRowLabelValueProvider(NULL, true); SetColLabelValueProvider(NULL, true); SetSpannedBlocks(NULL, true); } int wxSheetTable::GetNumberRows() { wxCHECK_MSG(GetGridCellValueProvider(), 0, wxT("Invalid cell data for the table")); return GetGridCellValueProvider()->GetNumberRows(); } int wxSheetTable::GetNumberCols() { wxCHECK_MSG(GetGridCellValueProvider(), 0, wxT("Invalid cell data for the table")); return GetGridCellValueProvider()->GetNumberCols(); } wxString wxSheetTable::GetValue( const wxSheetCoords& coords ) { switch (wxSheet::GetCellCoordsType(coords)) { case wxSHEET_CELL_GRID : { // need cell data for values, or override this wxCHECK_MSG(GetGridCellValueProvider(), wxEmptyString, wxT("Invalid grid cell data for the table")); return GetGridCellValueProvider()->GetValue(coords); } case wxSHEET_CELL_ROWLABEL : { // just return default if no row label data wxSheetCoords rowCoords(coords.SheetToRowLabel()); if (GetRowLabelValueProvider() && GetRowLabelValueProvider()->HasValue(rowCoords)) return GetRowLabelValueProvider()->GetValue(rowCoords); return GetDefaultRowLabelValue(coords.m_row); } case wxSHEET_CELL_COLLABEL : { wxSheetCoords colCoords(coords.SheetToColLabel()); if (GetColLabelValueProvider() && GetColLabelValueProvider()->HasValue(colCoords)) return GetColLabelValueProvider()->GetValue(colCoords); return GetDefaultColLabelValue(coords.m_col); } case wxSHEET_CELL_CORNERLABEL : { return m_cornerLabelValue; } default : return wxEmptyString; } } void wxSheetTable::SetValue( const wxSheetCoords& coords, const wxString& value ) { // You must override this or have set data containers for this to work switch (wxSheet::GetCellCoordsType(coords)) { case wxSHEET_CELL_GRID : { wxCHECK_RET(GetGridCellValueProvider(), wxT("Invalid grid cell data for the table")); GetGridCellValueProvider()->SetValue(coords, value); break; } case wxSHEET_CELL_ROWLABEL : { wxCHECK_RET(GetRowLabelValueProvider(), wxT("Invalid row label data for the table")); GetRowLabelValueProvider()->SetValue(coords.SheetToRowLabel(), value); break; } case wxSHEET_CELL_COLLABEL : { wxCHECK_RET(GetColLabelValueProvider(), wxT("Invalid col label data for the table")); GetColLabelValueProvider()->SetValue(coords.SheetToColLabel(), value); break; } case wxSHEET_CELL_CORNERLABEL : { m_cornerLabelValue = value; break; } default : break; } } bool wxSheetTable::HasValue( const wxSheetCoords& coords ) { switch (wxSheet::GetCellCoordsType(coords)) { case wxSHEET_CELL_GRID : { if (GetGridCellValueProvider()) return GetGridCellValueProvider()->HasValue(coords); break; } case wxSHEET_CELL_ROWLABEL : { if (GetRowLabelValueProvider()) return GetRowLabelValueProvider()->HasValue(coords.SheetToRowLabel()); break; } case wxSHEET_CELL_COLLABEL : { if (GetColLabelValueProvider()) return GetColLabelValueProvider()->HasValue(coords.SheetToColLabel()); break; } case wxSHEET_CELL_CORNERLABEL : default : break; } return !GetValue(coords).IsEmpty(); } int wxSheetTable::GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) { switch (wxSheet::GetCellCoordsType(coords)) { case wxSHEET_CELL_GRID : { if (GetGridCellValueProvider()) return GetGridCellValueProvider()->GetFirstNonEmptyColToLeft(coords); break; } case wxSHEET_CELL_ROWLABEL : { if (GetRowLabelValueProvider()) return GetRowLabelValueProvider()->GetFirstNonEmptyColToLeft(coords.SheetToRowLabel()); break; } case wxSHEET_CELL_COLLABEL : { if (GetColLabelValueProvider()) return GetColLabelValueProvider()->GetFirstNonEmptyColToLeft(coords.SheetToColLabel()); break; } case wxSHEET_CELL_CORNERLABEL : default : break; } return coords.m_col-1; } void wxSheetTable::ClearValues(int update) { if (((update & wxSHEET_UpdateGridCellValues) != 0) && GetGridCellValueProvider()) GetGridCellValueProvider()->ClearValues(); if (((update & wxSHEET_UpdateRowLabelValues) != 0) && GetRowLabelValueProvider()) GetRowLabelValueProvider()->ClearValues(); if (((update & wxSHEET_UpdateColLabelValues) != 0) && GetColLabelValueProvider()) GetColLabelValueProvider()->ClearValues(); /* FIXME should add clearing attrs here if (((update & wxSHEET_UpdateGridCellAttrs) != 0) && GetAttrProvider()) GetAttrProvider()-> if (((update & wxSHEET_UpdateRowLabelAttrs) != 0) && GetAttrProvider()) GetAttrProvider()-> if (((update & wxSHEET_UpdateColLabelAttrs) != 0) && GetAttrProvider()) GetAttrProvider()-> */ } wxString wxSheetTable::GetDefaultRowLabelValue( int row ) const { return wxString::Format(wxT("%d"), row+1); // Starting at zero confuses users } wxString wxSheetTable::GetDefaultColLabelValue( int col ) const { // default col labels are: cols [0-25]=[A-Z], cols [26-675]=[AA-ZZ] /* wxString s, s2; unsigned int i, n; for ( n = 1; ; n++ ) { s += wxChar((_T('A')) + (wxChar)( col%26 )); col = col/26 - 1; if ( col < 0 ) break; } // reverse the string... for ( i = n; i > 0; i-- ) s2 += s[i-1]; //for ( i = 0; i < n; i++ ) s2 += s[n-i-1]; return s2; */ // new method using log function so you don't have to reverse the string wxCHECK_MSG(col >= 0, wxEmptyString, wxT("Invalid col")); const size_t chars = size_t(log(col)/3.2580965380); // log_26(x) = log(x)/log(26.0) wxString s(wxT('A'), chars+1); for ( size_t n = 0; n <= chars; n++ ) { s[size_t(chars - n)] = wxChar(_T('A') + (wxChar)(col%26)); col = col/26 - 1; } return s; } long wxSheetTable::GetValueAsLong( const wxSheetCoords& coords ) { const wxString val(GetValue(coords)); long lval = 0; val.ToLong(&lval); //wxCHECK_MSG(val.ToLong(&lval), 0, wxT("Unable to get cell ") + CS(coords) + wxT(" value as long.")); return lval; } double wxSheetTable::GetValueAsDouble( const wxSheetCoords& coords ) { const wxString val(GetValue(coords)); double dval = 0.0; val.ToDouble(&dval); // wxCHECK_MSG(val.ToDouble(&dval), 0.0, wxT("Unable to get cell ") + CS(coords) + wxT(" value as double.")); return dval; } bool wxSheetTable::GetValueAsBool( const wxSheetCoords& coords ) { const wxString val(GetValue(coords)); if (val.IsEmpty() || (val == wxT("0")) || (val.CmpNoCase(wxT("f")) == 0) || (val.CmpNoCase(wxT("false")) == 0)) return false; return true; } void wxSheetTable::SetValueAsLong( const wxSheetCoords& coords, long value ) { SetValue(coords, wxString::Format(wxT("%ld"), value)); } void wxSheetTable::SetValueAsDouble( const wxSheetCoords& coords, double value ) { SetValue(coords, wxString::Format(wxT("%g"), value)); } void wxSheetTable::SetValueAsBool( const wxSheetCoords& coords, bool value ) { SetValue(coords, value ? wxT("1") : wxT("0")); } void* wxSheetTable::GetValueAsCustom( const wxSheetCoords& coords, const wxString& typeName ) { wxFAIL_MSG(wxStrF(wxT("Unable to return wxSheetTable::GetValueAsCustom for cell (%d, %d) and type '%s'"), coords.m_row, coords.m_col, typeName.c_str())); return NULL; } void wxSheetTable::SetValueAsCustom( const wxSheetCoords& coords, const wxString& typeName, void* WXUNUSED(value) ) { wxFAIL_MSG(wxStrF(wxT("Unable to set wxSheetTable::SetValueAsCustom for cell (%d, %d) and type '%s'"), coords.m_row, coords.m_col, typeName.c_str())); } bool wxSheetTable::CanGetValueAs( const wxSheetCoords& coords, const wxString& typeName ) { if ((typeName == wxSHEET_VALUE_NUMBER) || (typeName == wxSHEET_VALUE_CHOICEINT)) { const wxString val(GetValue(coords)); long lval = 0; return val.ToLong(&lval); } else if (typeName == wxSHEET_VALUE_FLOAT) { const wxString val(GetValue(coords)); double dval = 0.0; return val.ToDouble(&dval); } else if (typeName == wxSHEET_VALUE_BOOL) { const wxString val(GetValue(coords)); return val.IsEmpty() || (val == wxT("0")) || (val == wxT("1")) || (val.CmpNoCase(wxT("f")) == 0) || (val.CmpNoCase(wxT("t")) == 0) || (val.CmpNoCase(wxT("false")) == 0) || (val.CmpNoCase(wxT("true")) == 0); } return typeName == wxSHEET_VALUE_STRING; } bool wxSheetTable::CanSetValueAs( const wxSheetCoords& coords, const wxString& typeName ) { return CanGetValueAs(coords, typeName); } wxString wxSheetTable::GetTypeName( const wxSheetCoords& ) { return wxEmptyString; //wxSHEET_VALUE_STRING; } void wxSheetTable::SetGridCellValueProvider(wxSheetValueProviderBase *gridCellValues, bool is_owner) { if (m_gridCellValues && m_own_grid_cell_values) delete m_gridCellValues; m_gridCellValues = gridCellValues; m_own_grid_cell_values = is_owner; } void wxSheetTable::SetRowLabelValueProvider(wxSheetValueProviderBase *rowLabelValues, bool is_owner) { if (m_rowLabelValues && m_own_row_label_values) delete m_rowLabelValues; m_rowLabelValues = rowLabelValues; m_own_row_label_values = is_owner; } void wxSheetTable::SetColLabelValueProvider(wxSheetValueProviderBase *colLabelValues, bool is_owner) { if (m_colLabelValues && m_own_col_label_values) delete m_colLabelValues; m_colLabelValues = colLabelValues; m_own_col_label_values = is_owner; } wxSheetCellAttr wxSheetTable::GetAttr( const wxSheetCoords& coords, wxSheetAttr_Type kind ) { // Ok to return nothing if (GetAttrProvider()) return GetAttrProvider()->GetAttr(coords, kind); return wxNullSheetCellAttr; } void wxSheetTable::SetAttr( const wxSheetCoords& coords, const wxSheetCellAttr& attr, wxSheetAttr_Type kind) { // This is called from the wxCHECK_RET(GetAttrProvider(), wxT("Invalid attr provider in table")); GetAttrProvider()->SetAttr(coords, attr, kind); } void wxSheetTable::SetAttrProvider(wxSheetCellAttrProvider *attrProvider, bool is_owner) { if (m_attrProvider && m_own_attr_provider) delete m_attrProvider; m_attrProvider = attrProvider; m_own_attr_provider = is_owner; } bool wxSheetTable::HasSpannedCells() { return GetSpannedBlocks() && (GetSpannedBlocks()->GetCount() != 0u); } wxSheetBlock wxSheetTable::GetCellBlock( const wxSheetCoords& coords ) { if (GetSpannedBlocks()) // ok not to have this, just return 1x1 { const int n = GetSpannedBlocks()->Index(coords); if (n != wxNOT_FOUND) return GetSpannedBlocks()->GetBlock(n); } return wxSheetBlock(coords, 1, 1); } void wxSheetTable::SetCellSpan( const wxSheetBlock& block ) { wxCHECK_RET(GetSpannedBlocks(), wxT("Invalid spanned block container")); wxCHECK_RET(!block.IsEmpty(), wxT("Cannot set cell size smaller than (1,1)")); wxCHECK_RET((ContainsGridCell(block.GetLeftTop()) && ContainsGridCell(block.GetRightBottom())) || (ContainsRowLabelCell(block.GetLeftTop()) && ContainsRowLabelCell(block.GetRightBottom())) || (ContainsColLabelCell(block.GetLeftTop()) && ContainsColLabelCell(block.GetRightBottom())), wxT("Cannot set cell size for cell out of grid")); wxSheetBlock bounds(block); const wxArraySheetBlock &arrBlock = GetSpannedBlocks()->GetBlockArray(); int n, index = wxNOT_FOUND, intersections = 0, count = arrBlock.GetCount(); //int index = wxNOT_FOUND; // Check for multiple intersections, one is fine, but topleft corners must match for (n=0; nDeselectBlock(arrBlock[index], false); } // no need to add a 1x1 block if ((block.GetWidth() > 1) || (block.GetHeight() > 1)) { // don't combine them sel->SelectBlock(block, false); } if (GetView()) GetView()->RefreshGridCellBlock(bounds); } void wxSheetTable::SetSpannedBlocks(wxSheetSelection *spannedCells, bool is_owner) { if (m_spannedCells && m_own_spanned_cells) delete m_spannedCells; m_spannedCells = spannedCells; m_own_spanned_cells = is_owner; } bool wxSheetTable::UpdateRows( size_t row, int numRows, int update) { const int curNumRows = GetNumberRows(); wxSHEET_CHECKUPDATE_MSG(row, numRows, curNumRows, false); if (((update & wxSHEET_UpdateGridCellValues) != 0) && GetGridCellValueProvider()) GetGridCellValueProvider()->UpdateRows(row, numRows); if (((update & wxSHEET_UpdateRowLabelValues) != 0) && GetRowLabelValueProvider()) GetRowLabelValueProvider()->UpdateRows(row, numRows); if (((update & wxSHEET_UpdateSpanned) != 0) && GetSpannedBlocks()) ((wxSheetSelection*)GetSpannedBlocks())->UpdateRows( row, numRows ); if (((update & wxSHEET_UpdateAttributes) != 0) && GetAttrProvider()) GetAttrProvider()->UpdateRows( row, numRows, update ); return UpdateSheetRows(row, numRows, update); } bool wxSheetTable::UpdateCols( size_t col, int numCols, int update ) { const int curNumCols = GetNumberCols(); wxSHEET_CHECKUPDATE_MSG(col, numCols, curNumCols, false); if (((update & wxSHEET_UpdateGridCellValues) != 0) && GetGridCellValueProvider()) GetGridCellValueProvider()->UpdateCols(col, numCols); if (((update & wxSHEET_UpdateColLabelValues) != 0) && GetColLabelValueProvider()) GetColLabelValueProvider()->UpdateCols(col, numCols); if (((update & wxSHEET_UpdateSpanned) != 0) && GetSpannedBlocks()) ((wxSheetSelection*)GetSpannedBlocks())->UpdateCols( col, numCols ); if (((update & wxSHEET_UpdateAttributes) != 0) && GetAttrProvider()) GetAttrProvider()->UpdateCols( col, numCols, update ); return UpdateSheetCols(col, numCols, update); } bool wxSheetTable::UpdateSheetRows( size_t row, int numRows, int update ) { return GetView() && GetView()->DoUpdateRows(row, numRows, update); } bool wxSheetTable::UpdateSheetCols( size_t col, int numCols, int update ) { return GetView() && GetView()->DoUpdateCols(col, numCols, update); } bool wxSheetTable::UpdateSheetRowsCols(int update) { bool done = false; if (!GetView()) return done; const int tableRows = GetNumberRows(); const int tableCols = GetNumberCols(); const int sheetRows = GetView()->GetNumberRows(); const int sheetCols = GetView()->GetNumberCols(); if (tableRows != sheetRows) done |= UpdateSheetRows(tableRows < sheetRows ? tableRows : sheetRows, tableRows - sheetRows, update); if (tableCols != sheetCols) done |= UpdateSheetCols(tableCols < sheetCols ? tableCols : sheetCols, tableCols - sheetCols, update); return done; } gambit-0.2010.09.01/src/labenski/src/spinctld.cpp0000644000076500007650000004433511350032206016133 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: spinctld.h // Author: John Labenski // Created: 11/05/02 // Copyright: John Labenski, 2002 // License: wxWidgets ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "spinctld.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/valtext.h" // for wxTextValidator #include "wx/textctrl.h" #endif // WX_PRECOMP #include "wx/wxthings/spinctld.h" #include #if wxCHECK_VERSION(2,5,0) #include "wx/math.h" #else #if defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__) #include #define wxFinite(x) _finite(x) #elif defined(__GNUG__)||defined(__GNUWIN32__)||defined(__DJGPP__)|| \ defined(__SGI_CC__)||defined(__SUNCC__)||defined(__XLC__)|| \ defined(__HPUX__)||defined(__MWERKS__) #define wxFinite(x) finite(x) #else #define wxFinite(x) ((x) == (x)) #endif #endif // wxCHECK_VERSION(2,5,0) // NOTES : if the textctrl is focused and the program is ending, a killfocus // event is sent in MSW, this is why m_textCtrl is set to NULL in it's // destructor and there's so many checks for it not being NULL //---------------------------------------------------------------------------- // wxSpinCtrlDbl //---------------------------------------------------------------------------- // the textctrl used for the wxSpinCtrlDbl, needed for keypresses class wxSpinCtrlDblTextCtrl : public wxTextCtrl { public: wxSpinCtrlDblTextCtrl( wxWindow *parent, wxWindowID id, const wxString &value = wxEmptyString, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString &name = wxTextCtrlNameStr); // MSW sends extra kill focus event virtual ~wxSpinCtrlDblTextCtrl() { if (m_parent) m_parent->m_textCtrl = NULL; m_parent = NULL; } wxSpinCtrlDbl *m_parent; void OnChar( wxKeyEvent &event ); // pass chars to wxSpinCtrlDbl void OnKillFocus( wxFocusEvent &event ); // sync the spin to textctrl private: DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(wxSpinCtrlDblTextCtrl,wxTextCtrl) // EVT_TEXT_ENTER( wxID_ANY, wxSpinCtrlDblTextCtrl::OnTextEnter ) // get them from spinctrldbl // EVT_TEXT( wxID_ANY, wxSpinCtrlDblTextCtrl::OnTextUpdate ) // get them from spinctrldbl EVT_CHAR( wxSpinCtrlDblTextCtrl::OnChar ) EVT_KILL_FOCUS( wxSpinCtrlDblTextCtrl::OnKillFocus ) END_EVENT_TABLE() wxSpinCtrlDblTextCtrl::wxSpinCtrlDblTextCtrl( wxWindow *parent, wxWindowID id, const wxString &value, const wxPoint &pos, const wxSize &size, long style, const wxValidator& validator, const wxString &name) :wxTextCtrl( parent, id, value, pos, size, style, validator, name) { m_parent = (wxSpinCtrlDbl*)parent; } void wxSpinCtrlDblTextCtrl::OnChar( wxKeyEvent &event ) { if (m_parent) m_parent->OnChar( event ); } void wxSpinCtrlDblTextCtrl::OnKillFocus( wxFocusEvent &event ) { if (m_parent) m_parent->SyncSpinToText(true); event.Skip(); } //---------------------------------------------------------------------------- // wxSpinCtrlDbl //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS( wxSpinCtrlDbl, wxControl ) BEGIN_EVENT_TABLE(wxSpinCtrlDbl,wxControl) EVT_SPIN_UP ( wxID_ANY, wxSpinCtrlDbl::OnSpinUp ) EVT_SPIN_DOWN ( wxID_ANY, wxSpinCtrlDbl::OnSpinDown ) EVT_TEXT_ENTER( wxID_ANY, wxSpinCtrlDbl::OnTextEnter ) //EVT_TEXT ( wxID_ANY, wxSpinCtrlDbl::OnText ) EVT_SET_FOCUS ( wxSpinCtrlDbl::OnFocus ) EVT_KILL_FOCUS( wxSpinCtrlDbl::OnKillFocus ) END_EVENT_TABLE() void wxSpinCtrlDbl::Init() { m_min = 0; m_max = 100; m_value = 0; m_default_value = 0; m_increment = 1; m_digits = wxSPINCTRLDBL_AUTODIGITS; m_snap_ticks = false; m_spinButton = NULL; m_textCtrl = NULL; } bool wxSpinCtrlDbl::Create( wxWindow *parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style, double min, double max, double initial, double increment, int digits, const wxString& name) { if (!wxControl::Create(parent, id, pos, size, style|wxNO_BORDER, wxDefaultValidator, name)) return false; wxControl::SetLabel(name); wxControl::SetBackgroundColour(parent->GetBackgroundColour()); wxControl::SetForegroundColour(parent->GetForegroundColour()); int width = size.GetWidth(), height = size.GetHeight(); wxSize best_size( DoGetBestSize() ); if (width == -1) width = best_size.GetWidth(); if (height == -1) height = best_size.GetHeight(); // Create a validator for numbers, +-, and eE for exponential wxTextValidator validator(wxFILTER_INCLUDE_CHAR_LIST); #if wxCHECK_VERSION(2, 5, 4) wxArrayString list; wxString valid_chars(wxT(" 0123456789+-.eE")); size_t len = valid_chars.Length(); for (size_t i=0; iGetSize().GetWidth(), height), wxTE_NOHIDESEL|wxTE_PROCESS_ENTER, validator); DoSetSize( pos.x, pos.y, width, height ); #if wxCHECK_VERSION(2,7,0) SetInitialSize(wxSize(width, height)); #else SetBestSize(wxSize(width, height)); #endif m_min = min; m_max = max; m_value = initial; m_default_value = initial; m_increment = increment; SetDigits( digits ); // set the value here without generating an event if (!value.IsEmpty()) m_textCtrl->SetValue(value); else m_textCtrl->SetValue(wxString::Format(m_textFormat.c_str(), initial)); return true; } wxSpinCtrlDbl::~wxSpinCtrlDbl() { if (m_textCtrl) // null this since MSW sends KILL_FOCUS on deletion { m_textCtrl->m_parent = NULL; wxSpinCtrlDblTextCtrl *text = m_textCtrl; m_textCtrl = NULL; delete text; } delete m_spinButton; m_spinButton = NULL; } #define wxSPINCTRLDBL_SPIN_WIDTH 15 #define wxSPINCTRLDBL_SPIN_HEIGHT 22 void wxSpinCtrlDbl::DoSetSize(int x, int y, int width, int height, int sizeFlags) { //wxPrintf(wxT("DoSetSize %d, %d %d %d %d %d\n"), GetId(), x, y, width, height, sizeFlags); wxSize bestSize( DoGetBestSize() ); if (width < 0) width = bestSize.GetWidth(); if (height < 0) height = bestSize.GetHeight(); wxWindow::DoSetSize(x, y, width, height, sizeFlags); int spinwidth = wxSPINCTRLDBL_SPIN_WIDTH; int spinheight = wxSPINCTRLDBL_SPIN_HEIGHT; if (m_spinButton) m_spinButton->GetSize( &spinwidth, &spinheight ); #ifdef __WIN95__ // humm... these used to be different if (m_textCtrl) m_textCtrl->SetSize( 0, 0, width - spinwidth, height ); if (m_spinButton) m_spinButton->SetSize( width-spinwidth-2, 0, -1, height ); //m_textCtrl->SetSize( -3, -3, width - spinwidth, height ); // old wxWin < 2.3.2 //m_spinButton->SetSize( width-spinwidth-4, -3, -1, height-1 ); #else if (m_textCtrl) m_textCtrl->SetSize( 0, 0, width - spinwidth, height ); if (m_spinButton) m_spinButton->SetSize( width-spinwidth, 0, -1, height ); #endif } static wxSize s_spinctrl_bestSize(-999,-999); wxSize wxSpinCtrlDbl::DoGetBestSize() const { //wxPrintf(wxT("GetBestSize %d\n"), GetId()); if (s_spinctrl_bestSize.x == -999) { wxSpinCtrl spin((wxWindow*)this, wxID_ANY); s_spinctrl_bestSize = spin.GetBestSize(); // oops something went wrong, set to reasonable value if (s_spinctrl_bestSize.GetWidth() < 20) s_spinctrl_bestSize.SetWidth(95); if (s_spinctrl_bestSize.GetHeight() < 10) s_spinctrl_bestSize.SetHeight(wxSPINCTRLDBL_SPIN_HEIGHT); } return s_spinctrl_bestSize; } void wxSpinCtrlDbl::DoSendEvent() { wxCommandEvent event( wxEVT_COMMAND_SPINCTRL_UPDATED, GetId() ); event.SetEventObject( this ); event.SetInt( (int)(m_value+0.5) ); if (m_textCtrl) event.SetString( m_textCtrl->GetValue() ); GetEventHandler()->ProcessEvent( event ); } void wxSpinCtrlDbl::OnSpinUp( wxSpinEvent &WXUNUSED(event) ) { if (m_textCtrl && m_textCtrl->IsModified() ) SyncSpinToText(false); if ( InRange(m_value + m_increment) ) { m_value += m_increment; SetValue( m_value ); DoSendEvent(); } } void wxSpinCtrlDbl::OnSpinDown( wxSpinEvent &WXUNUSED(event) ) { if (m_textCtrl && m_textCtrl->IsModified() ) SyncSpinToText(false); if ( InRange(m_value - m_increment) ) { m_value -= m_increment; SetValue( m_value ); DoSendEvent(); } } void wxSpinCtrlDbl::OnTextEnter( wxCommandEvent &event ) { SyncSpinToText(true); event.Skip(); } void wxSpinCtrlDbl::OnText( wxCommandEvent &event ) { //wxPrintf(wxT("Text '%s'\n"), event.GetString()); fflush(stdout); event.Skip(); } void wxSpinCtrlDbl::OnChar( wxKeyEvent &event ) { double modifier = 1.0; if ( event.m_shiftDown ) modifier = 2.0; if ( event.m_controlDown ) modifier *= 10.0; if ( event.m_altDown ) modifier *= 100.0; switch ( event.GetKeyCode() ) { case WXK_UP : { if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false); SetValue( m_value + m_increment * modifier ); DoSendEvent(); break; } case WXK_DOWN : { if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false); SetValue( m_value - m_increment * modifier ); DoSendEvent(); break; } case WXK_PRIOR : // pg-up { if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false); SetValue( m_value + m_increment * 10.0 * modifier ); DoSendEvent(); break; } case WXK_NEXT : // pg-down { if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false); SetValue( m_value - m_increment * 10.0 * modifier ); DoSendEvent(); break; } case WXK_SPACE : { SetValue(m_value); event.Skip(false); break; } case WXK_ESCAPE : { SetDefaultValue(); DoSendEvent(); break; } case WXK_TAB : { wxNavigationKeyEvent new_event; new_event.SetEventObject( GetParent() ); new_event.SetDirection( !event.ShiftDown() ); // CTRL-TAB changes the (parent) window, i.e. switch notebook page new_event.SetWindowChange( event.ControlDown() ); new_event.SetCurrentFocus( this ); GetParent()->GetEventHandler()->ProcessEvent( new_event ); break; } default : event.Skip(); break; } } void wxSpinCtrlDbl::SetValue( double value ) { if (!m_textCtrl || !InRange(value)) return; if ( m_snap_ticks && (m_increment != 0) ) { double snap_value = (value - m_default_value) / m_increment; if (wxFinite(snap_value)) // FIXME what to do about a failure? { if (snap_value - floor(snap_value) < ceil(snap_value) - snap_value) value = m_default_value + floor(snap_value) * m_increment; else value = m_default_value + ceil(snap_value) * m_increment; } } wxString str(wxString::Format(m_textFormat.c_str(), value)); if ((value != m_value) || (str != m_textCtrl->GetValue())) { m_textCtrl->SetValue( str ); m_textCtrl->DiscardEdits(); m_value = value; str.ToDouble( &m_value ); // wysiwyg for textctrl } } void wxSpinCtrlDbl::SetValue( const wxString& text, bool force ) { if (!m_textCtrl) return; double value; if ( text.ToDouble(&value) ) SetValue( value ); else if (force) { m_textCtrl->SetValue( text ); m_textCtrl->DiscardEdits(); } } void wxSpinCtrlDbl::SetRange( double min_val, double max_val ) { //wxCHECK_RET(max_val > min_val, wxT("invalid spinctrl range")); m_min = min_val; m_max = max_val; if (HasRange()) { if (m_value > m_max) SetValue(m_max); else if (m_value < m_min) SetValue(m_min); } } void wxSpinCtrlDbl::SetIncrement( double increment ) { m_increment = increment; SetValue(m_value); } void wxSpinCtrlDbl::SetDigits( int digits, formatType fmt ) { wxCHECK_RET(digits >= -1, wxT("invalid spinctrl format")); if ((digits == wxSPINCTRLDBL_AUTODIGITS) && (fmt != lg_fmt)) { wxString wxstr; int lastplace = -1, extra_digits = 0; if (fmt == le_fmt) { wxstr.Printf(wxT("%le"), m_increment ); wxstr.LowerCase(); lastplace = wxstr.Find(wxT('e')) - 2; long places; if (wxstr.AfterFirst(wxT('e')).ToLong(&places)) extra_digits = int(labs(places)); } else if (fmt == lf_fmt) { wxstr.Printf(wxT("%lf"), m_increment ); lastplace = wxstr.Len()-1; } int decimalplace = wxstr.Find(wxT('.')); int i = 0; for ( i=lastplace; i>decimalplace; i-- ) { if ( wxstr.GetChar(i) != wxT('0') ) { m_digits = extra_digits + i-decimalplace; switch (fmt) { case le_fmt : m_textFormat.Printf(wxT("%%.%dle"), m_digits ); break; case lf_fmt : default : m_textFormat.Printf(wxT("%%.%dlg"), m_digits ); break; } SetValue(m_value); return; } } m_digits = 0; // no digits, I guess } else m_digits = digits; switch (fmt) { case le_fmt : m_textFormat.Printf(wxT("%%.%dle"), m_digits ); break; case lg_fmt : { if (m_digits == -1) m_textFormat.Printf(wxT("%%lg") ); else m_textFormat.Printf(wxT("%%.%dlg"), m_digits ); break; } case lf_fmt : default : m_textFormat.Printf(wxT("%%.%dlf"), m_digits ); break; } SetValue(m_value); } void wxSpinCtrlDbl::SetFormat( const wxString& format ) { wxString wxstr; if ( wxstr.Printf(format.c_str(), 123456.123456) > 0 ) m_textFormat = format; SetValue(m_value); } void wxSpinCtrlDbl::SetDefaultValue( double default_value ) { if ( InRange(default_value) ) { m_default_value = default_value; SetDefaultValue(); } } void wxSpinCtrlDbl::SetSnapToTicks(bool forceTicks) { if (m_snap_ticks != forceTicks) { m_snap_ticks = forceTicks; SetValue( m_value ); } } void wxSpinCtrlDbl::OnFocus( wxFocusEvent &event ) { if (m_textCtrl) m_textCtrl->SetFocus(); // this is to pass TAB navigation event.Skip(); } void wxSpinCtrlDbl::OnKillFocus( wxFocusEvent &event ) { SyncSpinToText(true); event.Skip(); } void wxSpinCtrlDbl::SyncSpinToText(bool send_event, bool force_valid) { if (!m_textCtrl) return; double txt_value; if ( m_textCtrl->GetValue().ToDouble( &txt_value ) ) { if ( force_valid || !HasRange() || InRange(txt_value) ) { if (force_valid && HasRange()) { if (txt_value > GetMax()) txt_value = GetMax(); else if (txt_value < GetMin()) txt_value = GetMin(); } if (m_value != txt_value) { SetValue( txt_value ); if (send_event) DoSendEvent(); } } } else if (force_valid) { // textctrl is out of sync, discard and reset SetValue(GetValue()); } } bool wxSpinCtrlDbl::SetFont( const wxFont &font ) { if (!m_textCtrl) return false; return m_textCtrl->SetFont( font ); } wxFont wxSpinCtrlDbl::GetFont() const { if (!m_textCtrl) return GetFont(); return m_textCtrl->GetFont(); } bool wxSpinCtrlDbl::SetBackgroundColour(const wxColour& colour) { if (!m_textCtrl) return wxControl::SetBackgroundColour(colour); bool ret = false; ret = m_textCtrl->SetBackgroundColour(colour); m_textCtrl->Refresh(); // FIXME is this necessary in GTK/OSX return ret; } wxColour wxSpinCtrlDbl::GetBackgroundColour() const { if (!m_textCtrl) return wxControl::GetBackgroundColour(); return m_textCtrl->GetBackgroundColour(); } bool wxSpinCtrlDbl::SetForegroundColour(const wxColour& colour) { if (!m_textCtrl) return wxControl::SetForegroundColour(colour); bool ret = false; ret = m_textCtrl->SetForegroundColour(colour); m_textCtrl->Refresh(); return ret; } wxColour wxSpinCtrlDbl::GetForegroundColour() const { if (!m_textCtrl) return wxControl::GetForegroundColour(); return m_textCtrl->GetForegroundColour(); } gambit-0.2010.09.01/src/labenski/src/toggle.cpp0000644000076500007650000004046611350032206015575 00000000000000///////////////////////////////////////////////////////////////////////////// // Name: wxCustomButton based on wxCustomToggleCtrl.cpp // Purpose: a toggle button // Author: Bruce Phillips // Modified by: John Labenski // Created: 11/05/2002 // RCS-ID: // Copyright: (c) Bruce Phillips, John Labenki // Licence: wxWidgets licence ///////////////////////////////////////////////////////////////////////////// #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "toggle.h" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/control.h" #include "wx/settings.h" #include "wx/bitmap.h" #include "wx/timer.h" #include "wx/dc.h" #include "wx/dcclient.h" #endif // WX_PRECOMP #include "wx/tglbtn.h" #include "wx/image.h" #include "wx/wxthings/toggle.h" // ========================================================================== // wxCustomButton // ========================================================================== IMPLEMENT_DYNAMIC_CLASS( wxCustomButton, wxControl ) BEGIN_EVENT_TABLE(wxCustomButton,wxControl) EVT_MOUSE_EVENTS ( wxCustomButton::OnMouseEvents ) EVT_PAINT ( wxCustomButton::OnPaint ) EVT_TIMER ( wxID_ANY, wxCustomButton::OnTimer) EVT_SIZE ( wxCustomButton::OnSize ) END_EVENT_TABLE() wxCustomButton::~wxCustomButton() { if (HasCapture()) ReleaseMouse(); if (m_timer) delete m_timer; } void wxCustomButton::Init() { m_focused = false; m_labelMargin = wxSize(4,4); m_bitmapMargin = wxSize(2,2); m_down = 0; m_timer = NULL; m_eventType = 0; m_button_style = wxCUSTBUT_TOGGLE|wxCUSTBUT_BOTTOM; } bool wxCustomButton::Create(wxWindow* parent, wxWindowID id, const wxString& label, const wxBitmap &bitmap, const wxPoint& pos, const wxSize& size, long style, const wxValidator& val, const wxString& name) { if (!wxControl::Create(parent,id,pos,size,wxNO_BORDER|wxCLIP_CHILDREN,val,name)) return false; wxControl::SetLabel(label); wxControl::SetBackgroundColour(parent->GetBackgroundColour()); wxControl::SetForegroundColour(parent->GetForegroundColour()); wxControl::SetFont(parent->GetFont()); if (bitmap.Ok()) m_bmpLabel = bitmap; if (!SetButtonStyle(style)) return false; wxSize bestSize = DoGetBestSize(); SetSize(wxSize(size.x<0 ? bestSize.x:size.x, size.y<0 ? bestSize.y:size.y)); #if wxCHECK_VERSION(2,7,0) SetInitialSize(GetSize()); #else SetBestSize(GetSize()); #endif CalcLayout(true); return true; } void wxCustomButton::SetValue(bool depressed) { wxCHECK_RET(!(m_button_style & wxCUSTBUT_NOTOGGLE), wxT("can't set button state")); m_down = depressed ? 1 : 0; Refresh(false); } bool wxCustomButton::SetButtonStyle(long style) { int n_styles = 0; if ((style & wxCUSTBUT_LEFT) != 0) n_styles++; if ((style & wxCUSTBUT_RIGHT) != 0) n_styles++; if ((style & wxCUSTBUT_TOP) != 0) n_styles++; if ((style & wxCUSTBUT_BOTTOM) != 0) n_styles++; wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxCustomButton label position allowed")); n_styles = 0; if ((style & wxCUSTBUT_NOTOGGLE) != 0) n_styles++; if ((style & wxCUSTBUT_BUTTON) != 0) n_styles++; if ((style & wxCUSTBUT_TOGGLE) != 0) n_styles++; if ((style & wxCUSTBUT_BUT_DCLICK_TOG) != 0) n_styles++; if ((style & wxCUSTBUT_TOG_DCLICK_BUT) != 0) n_styles++; wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxCustomButton style allowed")); m_button_style = style; if ((m_button_style & wxCUSTBUT_BUTTON) != 0) m_down = 0; CalcLayout(true); return true; } void wxCustomButton::SetLabel( const wxString &label ) { wxControl::SetLabel(label); CalcLayout(true); } // sequence of events in GTK is up, dclick, up. void wxCustomButton::OnMouseEvents(wxMouseEvent& event) { if (m_button_style & wxCUSTBUT_NOTOGGLE) return; if (event.LeftDown() || event.RightDown()) { if (!HasCapture()) CaptureMouse(); // keep depressed until up m_down++; Redraw(); } else if (event.LeftDClick() || event.RightDClick()) { m_down++; // GTK eats second down event Redraw(); } else if (event.LeftUp()) { if (HasCapture()) ReleaseMouse(); m_eventType = wxEVT_LEFT_UP; #if wxCHECK_VERSION(2,7,0) if (wxRect(wxPoint(0,0), GetSize()).Contains(event.GetPosition())) #else if (wxRect(wxPoint(0,0), GetSize()).Inside(event.GetPosition())) #endif { if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0)) { m_down = 0; Redraw(); SendEvent(); return; } else { if (!m_timer) { m_timer = new wxTimer(this, m_down+1); m_timer->Start(200, true); } else { m_eventType = wxEVT_LEFT_DCLICK; } if ((m_button_style & wxCUSTBUT_TOGGLE) && (m_button_style & wxCUSTBUT_TOG_DCLICK_BUT)) m_down++; } } Redraw(); } else if (event.RightUp()) { if (HasCapture()) ReleaseMouse(); m_eventType = wxEVT_RIGHT_UP; #if wxCHECK_VERSION(2,7,0) if (wxRect(wxPoint(0,0), GetSize()).Contains(event.GetPosition())) #else if (wxRect(wxPoint(0,0), GetSize()).Inside(event.GetPosition())) #endif { if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0)) { m_down = 0; Redraw(); SendEvent(); return; } else { m_down++; if (!m_timer) { m_timer = new wxTimer(this, m_down); m_timer->Start(250, true); } else { m_eventType = wxEVT_RIGHT_DCLICK; } } } Redraw(); } else if (event.Entering()) { m_focused = true; if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture()) m_down++; Redraw(); } else if (event.Leaving()) { m_focused = false; if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture()) m_down--; Redraw(); } } void wxCustomButton::OnTimer( wxTimerEvent &event ) { m_timer->Stop(); delete m_timer; m_timer = NULL; // Clean up the button presses // FIXME - GTK eats second left down for a DClick, who know about the others? if (m_button_style & wxCUSTBUT_BUTTON) { m_down = 0; } else if (m_button_style & wxCUSTBUT_TOGGLE) { if (m_eventType == wxEVT_LEFT_UP) m_down = event.GetId()%2 ? 0 : 1; else m_down = event.GetId()%2 ? 1 : 0; } else if (m_button_style & wxCUSTBUT_BUT_DCLICK_TOG) { if (m_eventType == wxEVT_LEFT_DCLICK) m_down = event.GetId()%2 ? 0 : 1; else m_down = event.GetId()%2 ? 1 : 0; } else if (m_button_style & wxCUSTBUT_TOG_DCLICK_BUT) { if (m_eventType == wxEVT_LEFT_UP) m_down = event.GetId()%2 ? 0 : 1; else m_down = event.GetId()%2 ? 1 : 0; } Refresh(false); SendEvent(); } void wxCustomButton::SendEvent() { if (((m_button_style & wxCUSTBUT_TOGGLE) && (m_eventType == wxEVT_LEFT_UP)) || ((m_button_style & wxCUSTBUT_BUT_DCLICK_TOG) && (m_eventType == wxEVT_LEFT_DCLICK)) || ((m_button_style & wxCUSTBUT_TOG_DCLICK_BUT) && (m_eventType == wxEVT_LEFT_UP))) { wxCommandEvent eventOut(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, GetId()); eventOut.SetInt(m_down%2 ? 1 : 0); eventOut.SetExtraLong(m_eventType); eventOut.SetEventObject(this); GetEventHandler()->ProcessEvent(eventOut); } else { wxCommandEvent eventOut(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); eventOut.SetInt(0); eventOut.SetExtraLong(m_eventType); eventOut.SetEventObject(this); GetEventHandler()->ProcessEvent(eventOut); } } wxBitmap wxCustomButton::CreateBitmapDisabled(const wxBitmap &bitmap) const { wxCHECK_MSG(bitmap.Ok(), wxNullBitmap, wxT("invalid bitmap")); unsigned char br = GetBackgroundColour().Red(); unsigned char bg = GetBackgroundColour().Green(); unsigned char bb = GetBackgroundColour().Blue(); wxImage image = bitmap.ConvertToImage(); int pos, width = image.GetWidth(), height = image.GetHeight(); unsigned char *img_data = image.GetData(); for (int j=0; j lh ? bh : lh; if (has_bitmap && has_label) lw -= wxMin(m_labelMargin.x, m_bitmapMargin.x); return wxSize(lw+bw, h); } int w = bw > lw ? bw : lw; if (has_bitmap && has_label) lh -= wxMin(m_labelMargin.y, m_bitmapMargin.y); return wxSize(w, lh+bh); } void wxCustomButton::CalcLayout(bool refresh) { int w, h; GetSize(&w,&h); int bw = 0, bh = 0; int lw = 0, lh = 0; if (m_bmpLabel.Ok()) // assume they're all the same size { bw = m_bmpLabel.GetWidth(); bh = m_bmpLabel.GetHeight(); } wxString label = GetLabel(); if (!label.IsEmpty()) { GetTextExtent(label, &lw, &lh); } // Center the label or bitmap if only one or the other if (!m_bmpLabel.Ok()) { m_bitmapPos = wxPoint(0,0); m_labelPos = wxPoint((w-lw)/2, (h-lh)/2); } else if (label.IsEmpty()) { m_bitmapPos = wxPoint((w-bw)/2, (h-bh)/2); m_labelPos = wxPoint(0,0); } else if (m_button_style & wxCUSTBUT_LEFT) { int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x); m_labelPos = wxPoint((w - (bw+lw+m_labelMargin.x+m_bitmapMargin.x+mid_margin))/2 + m_labelMargin.x, (h - lh)/2); m_bitmapPos = wxPoint(m_labelPos.x + lw + mid_margin, (h - bh)/2); } else if (m_button_style & wxCUSTBUT_RIGHT) { int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x); m_bitmapPos = wxPoint((w - (bw+lw+m_labelMargin.x+m_bitmapMargin.x+mid_margin))/2 + m_bitmapMargin.x, (h - bh)/2); m_labelPos = wxPoint(m_bitmapPos.x + bw + mid_margin, (h - lh)/2); } else if (m_button_style & wxCUSTBUT_TOP) { int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y); m_labelPos = wxPoint((w - lw)/2, (h - (bh+lh+m_labelMargin.y+m_bitmapMargin.y+mid_margin))/2 + m_labelMargin.y); m_bitmapPos = wxPoint((w - bw)/2, m_labelPos.y + lh + mid_margin); } else // if (m_button_style & wxCUSTBUT_BOTTOM) DEFAULT { int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y); m_bitmapPos = wxPoint((w - bw)/2, (h - (bh+lh+m_labelMargin.y+m_bitmapMargin.y+mid_margin))/2 + m_bitmapMargin.y); m_labelPos = wxPoint((w - lw)/2, m_bitmapPos.y + bh + mid_margin); } if (refresh) Refresh(false); } gambit-0.2010.09.01/src/libgambit/0000777000076500007650000000000011441457113013246 500000000000000gambit-0.2010.09.01/src/libgambit/array.h0000644000076500007650000001413611435216101014447 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/array.h // A basic bounds-checked array type // // 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 LIBGAMBIT_ARRAY_H #define LIBGAMBIT_ARRAY_H namespace Gambit { /// A basic bounds-checked array template class Array { protected: int mindex, maxdex; T *data; /// Private helper function that accomplishes the insertion of an object int InsertAt(const T &t, int n) { if (this->mindex > n || n > this->maxdex + 1) throw IndexException(); T *new_data = new T[++this->maxdex - this->mindex + 1] - this->mindex; int i; for (i = this->mindex; i <= n - 1; i++) new_data[i] = this->data[i]; new_data[i++] = t; for (; i <= this->maxdex; i++) new_data[i] = this->data[i - 1]; if (this->data) delete [] (this->data + this->mindex); this->data = new_data; return n; } public: /// @name Lifecycle //@{ /// Constructs an array of length 'len', starting at '1' Array(unsigned int len = 0) : mindex(1), maxdex(len), data((len) ? new T[len] - 1 : 0) { } /// Constructs an array starting at lo and ending at hi Array(int lo, int hi) : mindex(lo), maxdex(hi) { if (maxdex + 1 < mindex) throw RangeException(); data = (maxdex >= mindex) ? new T[maxdex -mindex + 1] - mindex : 0; } /// Copy the contents of another array Array(const Array &a) : mindex(a.mindex), maxdex(a.maxdex), data((maxdex >= mindex) ? new T[maxdex - mindex + 1] - mindex : 0) { for (int i = mindex; i <= maxdex; i++) data[i] = a.data[i]; } /// Destruct and deallocates the array virtual ~Array() { if (maxdex >= mindex) delete [] (data + mindex); } /// Copy the contents of another array Array &operator=(const Array &a) { if (this != &a) { // We only reallocate if necessary. This should be somewhat faster // if many objects are of the same length. Furthermore, it is // _essential_ for the correctness of the PVector and DVector // assignment operator, since it assumes the value of data does // not change. if (!data || (data && (mindex != a.mindex || maxdex != a.maxdex))) { if (data) delete [] (data + mindex); mindex = a.mindex; maxdex = a.maxdex; data = (maxdex >= mindex) ? new T[maxdex - mindex + 1] - mindex : 0; } for (int i = mindex; i <= maxdex; i++) data[i] = a.data[i]; } return *this; } //@} /// @name Operator overloading //@{ /// Test the equality of two arrays bool operator==(const Array &a) const { if (mindex != a.mindex || maxdex != a.maxdex) return false; for (int i = mindex; i <= maxdex; i++) { if ((*this)[i] != a[i]) return false; } return true; } /// Test the inequality of two arrays bool operator!=(const Array &a) const { return !(*this == a); } //@} /// @name General data access //@{ /// Return the length of the array int Length(void) const { return maxdex - mindex + 1; } /// Return the first index int First(void) const { return mindex; } /// Return the last index int Last(void) const { return maxdex; } /// Access the index'th entry in the array const T &operator[](int index) const { if (index < mindex || index > maxdex) throw IndexException(); return data[index]; } /// Access the index'th entry in the array T &operator[](int index) { if (index < mindex || index > maxdex) throw IndexException(); return data[index]; } /// Return the index at which a given element resides in the array. int Find(const T &t) const { int i; for (i = this->mindex; i <= this->maxdex && this->data[i] != t; i++); return (i <= this->maxdex) ? i : (mindex-1); } /// Return true if the element is currently residing in the array bool Contains(const T &t) const { return Find(t) != mindex-1; } //@} /// @name Modifying the contents of the array //@{ /// \brief Append a new element to the array. /// /// Append a new element to the array, and return the index at which the /// element can be found. Note that this index is guaranteed to be the /// last (highest) index in the array. int Append(const T &t) { return InsertAt(t, this->maxdex + 1); } /// \brief Insert a new element into the array at a given index. /// /// Insert a new element into the array at a given index. If the index is /// less than the lowest index, the element is inserted at the beginning; /// if the index is greater than the highest index, the element is appended. /// Returns the index at which the element actually is placed. int Insert(const T &t, int n) { return InsertAt(t, (n < this->mindex) ? this->mindex : ((n > this->maxdex + 1) ? this->maxdex + 1 : n)); } /// \brief Remove an element from the array. /// /// Remove the element at a given index from the array. Returns the value /// of the element removed. T Remove(int n) { if (n < this->mindex || n > this->maxdex) throw IndexException(); T ret(this->data[n]); T *new_data = (--this->maxdex>=this->mindex) ? new T[this->maxdex-this->mindex+1] - this->mindex : 0; int i; for (i = this->mindex; i < n; i++) new_data[i] = this->data[i]; for (; i <= this->maxdex; i++) new_data[i] = this->data[i + 1]; delete [] (this->data + this->mindex); this->data = new_data; return ret; } //@} }; } // end namespace Gambit #endif // LIBGAMBIT_ARRAY_H gambit-0.2010.09.01/src/libgambit/behav.cc0000644000076500007650000000206311435216101014550 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/behav.cc // Instantiation of behavior profile classes. // // 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 "libgambit.h" #include "behav.imp" template class Gambit::MixedBehavProfile; template class Gambit::MixedBehavProfile; gambit-0.2010.09.01/src/libgambit/behav.h0000644000076500007650000001365411441446351014433 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/behav.h // Behavior strategy profile classes // // 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 LIBGAMBIT_BEHAV_H #define LIBGAMBIT_BEHAV_H #include "game.h" namespace Gambit { /// /// MixedBehavProfile implements a randomized behavior profile on /// an extensive game. /// template class MixedBehavProfile : public DVector { protected: BehavSupport m_support; mutable bool m_cacheValid; // structures for storing cached data: nodes mutable Vector m_realizProbs, m_beliefs, m_nvals, m_bvals; mutable Matrix m_nodeValues; // structures for storing cached data: information sets mutable PVector m_infosetValues; // structures for storing cached data: actions mutable DVector m_actionValues; // aka conditional payoffs mutable DVector m_gripe; const T &ActionValue(const GameAction &act) const { return m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->m_number); } T &ActionValue(const GameAction &act) { return m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->m_number); } /// @name Auxiliary functions for computation of interesting values //@{ void GetPayoff(GameNodeRep *, const T &, int, T &) const; void ComputeSolutionDataPass2(const GameNode &node) const; void ComputeSolutionDataPass1(const GameNode &node) const; void ComputeSolutionData(void) const; //@} /// @name Converting mixed strategies to behavior //@{ void BehaviorStrat(int, GameNodeRep *); void RealizationProbs(const MixedStrategyProfile &, int pl, const Array &, GameNodeRep *); //@} public: /// @name Lifecycle //@{ MixedBehavProfile(const BehavSupport &); MixedBehavProfile(const MixedBehavProfile &); MixedBehavProfile(const MixedStrategyProfile &); ~MixedBehavProfile() { } MixedBehavProfile &operator=(const MixedBehavProfile &); MixedBehavProfile &operator=(const Vector &p) { Invalidate(); Vector::operator=(p); return *this;} MixedBehavProfile &operator=(const T &x) { Invalidate(); DVector::operator=(x); return *this; } //@} /// @name Operator overloading //@{ bool operator==(const MixedBehavProfile &) const; bool operator!=(const MixedBehavProfile &x) const { return !(*this == x); } bool operator==(const DVector &x) const { return DVector::operator==(x); } bool operator!=(const DVector &x) const { return DVector::operator!=(x); } const T &operator()(const GameAction &p_action) const { return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), p_action->GetInfoset()->GetNumber(), m_support.GetIndex(p_action)); } T &operator()(const GameAction &p_action) { return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), p_action->GetInfoset()->GetNumber(), m_support.GetIndex(p_action)); } const T &operator()(int a, int b, int c) const { return DVector::operator()(a, b, c); } T &operator()(int a, int b, int c) { Invalidate(); return DVector::operator()(a, b, c); } const T &operator[](int a) const { return Array::operator[](a); } T &operator[](int a) { Invalidate(); return Array::operator[](a); } MixedBehavProfile &operator+=(const MixedBehavProfile &x) { Invalidate(); DVector::operator+=(x); return *this; } MixedBehavProfile &operator+=(const DVector &x) { Invalidate(); DVector::operator+=(x); return *this; } MixedBehavProfile &operator-=(const MixedBehavProfile &x) { Invalidate(); DVector::operator-=(x); return *this; } MixedBehavProfile &operator*=(const T &x) { Invalidate(); DVector::operator*=(x); return *this; } //@} /// @name Initialization, validation //@{ /// Force recomputation of stored quantities void Invalidate(void) const { m_cacheValid = false; } /// Set the profile to the centroid void Centroid(void); //@} /// @name General data access //@{ int Length(void) const { return Array::Length(); } Game GetGame(void) const { return m_support.GetGame(); } const BehavSupport &GetSupport(void) const { return m_support; } bool IsDefinedAt(GameInfoset p_infoset) const; //@} /// @name Computation of interesting quantities //@{ T GetPayoff(int p_player) const; T GetLiapValue(bool p_definedOnly = false) const; const T &GetRealizProb(const GameNode &node) const; const T &GetBeliefProb(const GameNode &node) const; Vector GetNodeValue(const GameNode &node) const; T GetInfosetProb(const GameInfoset &iset) const; const T &GetInfosetValue(const GameInfoset &iset) const; T GetActionProb(const GameAction &act) const; const T &GetActionValue(const GameAction &act) const; const T &GetRegret(const GameAction &act) const; T DiffActionValue(const GameAction &action, const GameAction &oppAction) const; T DiffRealizProb(const GameNode &node, const GameAction &oppAction) const; T DiffNodeValue(const GameNode &node, const GamePlayer &player, const GameAction &oppAction) const; //@} }; } // end namespace Gambit #endif // LIBGAMBIT_BEHAV_H gambit-0.2010.09.01/src/libgambit/behav.imp0000644000076500007650000004447211441446351014773 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/behav.imp // Behavior strategy profile classes. // // 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 "behav.h" namespace Gambit { //======================================================================== // MixedBehavProfile: Lifecycle //======================================================================== template MixedBehavProfile::MixedBehavProfile(const MixedBehavProfile &p_profile) : DVector(p_profile), m_support(p_profile.m_support), m_cacheValid(false), m_realizProbs(p_profile.m_realizProbs), m_beliefs(p_profile.m_beliefs), m_nvals(p_profile.m_nvals), m_bvals(p_profile.m_bvals), m_nodeValues(p_profile.m_nodeValues), m_infosetValues(p_profile.m_infosetValues), m_actionValues(p_profile.m_actionValues), m_gripe(p_profile.m_gripe) { m_realizProbs = (T) 0.0; m_beliefs = (T) 0.0; m_nodeValues = (T) 0.0; m_infosetValues = (T) 0.0; m_actionValues = (T) 0.0; m_gripe = (T) 0.0; } template MixedBehavProfile::MixedBehavProfile(const BehavSupport &p_support) : DVector(p_support.NumActions()), m_support(p_support), m_cacheValid(false), m_realizProbs(p_support.GetGame()->NumNodes()), m_beliefs(p_support.GetGame()->NumNodes()), m_nvals(p_support.GetGame()->NumNodes()), m_bvals(p_support.GetGame()->NumNodes()), m_nodeValues(p_support.GetGame()->NumNodes(), p_support.GetGame()->NumPlayers()), m_infosetValues(p_support.GetGame()->NumInfosets()), m_actionValues(p_support.GetGame()->NumActions()), m_gripe(p_support.GetGame()->NumActions()) { m_realizProbs = (T) 0.0; m_beliefs = (T) 0.0; m_nodeValues = (T) 0.0; m_infosetValues = (T) 0.0; m_actionValues = (T) 0.0; m_gripe = (T) 0.0; Centroid(); } template void MixedBehavProfile::BehaviorStrat(int pl, GameNodeRep *p_node) { for (int i = 1; i <= p_node->children.Length(); i++) { GameNodeRep *child = p_node->children[i]; if (p_node->GetPlayer() && p_node->GetPlayer()->GetNumber() == pl) { if (m_nvals[p_node->number] > (T) 0 && m_nvals[child->number] > (T) 0) { (*this)(p_node->GetPlayer()->GetNumber(), p_node->GetInfoset()->GetNumber(), m_support.GetIndex(p_node->GetInfoset()->GetAction(i))) = m_nvals[child->number] / m_nvals[p_node->number]; } } BehaviorStrat(pl, child); } } template void MixedBehavProfile::RealizationProbs(const MixedStrategyProfile &mp, int pl, const Array &actions, GameNodeRep *node) { T prob; for (int i = 1; i <= node->children.Length(); i++) { if (node->GetPlayer() && !node->GetPlayer()->IsChance()) { if (node->GetPlayer()->GetNumber() == pl) { if (actions[node->GetInfoset()->GetNumber()] == i) prob = (T) 1; else prob = (T) 0; } else if (GetSupport().Contains(node->GetInfoset()->GetAction(i))) prob = (T) 1 / (T) GetSupport().NumActions(node->GetPlayer()->GetNumber(), node->GetInfoset()->GetNumber()); else { prob = (T) 0; } } else { // n.GetPlayer() == 0 prob = node->infoset->GetActionProb(i); } GameNode child = node->children[i]; m_bvals[child->number] = prob * m_bvals[node->number]; m_nvals[child->number] += m_bvals[child->number]; RealizationProbs(mp, pl, actions, child); } } template MixedBehavProfile::MixedBehavProfile(const MixedStrategyProfile &p_profile) : DVector(p_profile.GetGame()->NumActions()), m_support(p_profile.GetGame()), m_cacheValid(false), m_realizProbs(m_support.GetGame()->NumNodes()), m_beliefs(m_support.GetGame()->NumNodes()), m_nvals(m_support.GetGame()->NumNodes()), m_bvals(m_support.GetGame()->NumNodes()), m_nodeValues(m_support.GetGame()->NumNodes(), m_support.GetGame()->NumPlayers()), m_infosetValues(m_support.GetGame()->NumInfosets()), m_actionValues(m_support.GetGame()->NumActions()), m_gripe(m_support.GetGame()->NumActions()) { m_realizProbs = (T) 0.0; m_beliefs = (T) 0.0; m_nodeValues = (T) 0.0; m_infosetValues = (T) 0.0; m_actionValues = (T) 0.0; m_gripe = (T) 0.0; ((Vector &) *this).operator=((T)0); GameNodeRep *root = m_support.GetGame()->GetRoot(); const StrategySupport &support = p_profile.GetSupport(); GameRep *game = m_support.GetGame(); for (GamePlayerIterator player = game->Players(); !player.AtEnd(); player++) { m_nvals = (T) 0; m_bvals = (T) 0; for (SupportStrategyIterator strategy = support.Strategies(player); !strategy.AtEnd(); strategy++) { if (p_profile[strategy] > (T) 0) { const Array &actions = strategy->m_behav; m_bvals[root->GetNumber()] = p_profile[strategy]; RealizationProbs(p_profile, player->GetNumber(), actions, root); } } m_nvals[1] = (T) 1; // set the root nval BehaviorStrat(player->GetNumber(), root); } } template MixedBehavProfile &MixedBehavProfile::operator=(const MixedBehavProfile &p_profile) { if (this != &p_profile && m_support == p_profile.m_support) { Invalidate(); DVector::operator=(p_profile); m_support = p_profile.m_support; } return *this; } //======================================================================== // MixedBehavProfile: Operator overloading //======================================================================== template bool MixedBehavProfile::operator==(const MixedBehavProfile &p_profile) const { return (m_support == p_profile.m_support && (DVector &) *this == (DVector &) p_profile); } //======================================================================== // MixedBehavProfile: General data access //======================================================================== template void MixedBehavProfile::Centroid(void) { T center; for (int pl = 1; pl <= this->dvlen.Length(); pl++) for (int iset = 1; iset <= this->dvlen[pl]; iset++) if (m_support.NumActions(pl,iset) > 0) { center = ((T) 1 / (T) m_support.NumActions(pl, iset)); int act; for (act = 1; act <= this->svlen[this->dvidx[pl] + iset - 1]; act++) this->dvptr[pl][iset][act] = center; } } //======================================================================== // MixedBehavProfile: Interesting quantities //======================================================================== // // The p_definedOnly parameter allows us to compute the LiapValue for profiles // which are incomplete. Some methods -- such as the sequence form // methods -- return all zeroes for all action probabilities at // information sets sufficiently far off the equilibrium path. // In such cases, *any* completion is Nash. // // This is really a hack because we don't have a proper way yet of // indicating this. // template T MixedBehavProfile::GetLiapValue(bool p_definedOnly) const { static const T BIG1 = (T) 10000; static const T BIG2 = (T) 100; T x, result = ((T) 0), avg, sum; // HACK: force it to recompute data. FIX THIS. m_cacheValid = false; ComputeSolutionData(); for (int i = 1; i <= m_support.GetGame()->NumPlayers(); i++) { for (int iset = 1; iset <= m_support.GetGame()->GetPlayer(i)->NumInfosets(); iset++) { avg = sum = (T)0; for (int act = 1; act <= m_support.NumActions(i, iset); act++) { GameActionRep *action = m_support.GetAction(i, iset, act); x = GetActionProb(action); avg += x * m_actionValues(action->GetInfoset()->GetPlayer()->GetNumber(), action->GetInfoset()->GetNumber(), action->m_number); sum += x; if (x > (T)0) x = (T)0; result += BIG1 * x * x; // add penalty for neg probabilities } for (int act = 1; act <= m_support.NumActions(i, iset); act++) { x = ActionValue(m_support.GetAction(i, iset, act)) - avg; if (x < (T)0) x = (T)0; result += x * x; // add penalty if not best response } x = sum - (T)1; if (!p_definedOnly || sum >= (T) 1.0e-4) { result += BIG2 * x * x; // add penalty for sum not equal to 1 } } } return result; } template const T &MixedBehavProfile::GetRealizProb(const GameNode &node) const { ComputeSolutionData(); return m_realizProbs[node->number]; } template const T &MixedBehavProfile::GetBeliefProb(const GameNode &node) const { ComputeSolutionData(); return m_beliefs[node->number]; } template Vector MixedBehavProfile::GetNodeValue(const GameNode &node) const { ComputeSolutionData(); return m_nodeValues.Row(node->number); } template T MixedBehavProfile::GetInfosetProb(const GameInfoset &iset) const { ComputeSolutionData(); T prob = (T) 0; for (int i = 1; i <= iset->NumMembers(); i++) { prob += m_realizProbs[iset->GetMember(i)->number]; } return prob; } template const T &MixedBehavProfile::GetInfosetValue(const GameInfoset &iset) const { ComputeSolutionData(); return m_infosetValues(iset->GetPlayer()->GetNumber(), iset->GetNumber()); } template T MixedBehavProfile::GetActionProb(const GameAction &action) const { if (action->GetInfoset()->GetPlayer()->IsChance()) { GameInfosetRep *infoset = action->GetInfoset(); return infoset->GetActionProb(action->GetNumber()); } else if (!m_support.Contains(action)) { return (T) 0.0; } else { return (*this)(action->GetInfoset()->GetPlayer()->GetNumber(), action->GetInfoset()->GetNumber(), m_support.GetIndex(action)); } } template const T &MixedBehavProfile::GetActionValue(const GameAction &act) const { ComputeSolutionData(); return m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->m_number); } template const T &MixedBehavProfile::GetRegret(const GameAction &act) const { ComputeSolutionData(); return m_gripe(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->m_number); } template void MixedBehavProfile::GetPayoff(GameNodeRep *node, const T &prob, int player, T &value) const { if (node->outcome) { value += prob * node->outcome->GetPayoff(player); } if (node->children.Length()) { int pl = node->infoset->m_player->m_number, iset = node->infoset->m_number; if (pl == 0) { // chance player for (int act = 1; act <= node->NumChildren(); act++) { GetPayoff(node->GetChild(act), prob * node->infoset->GetActionProb(act), player, value); } } else { for (int act = 1; act <= m_support.NumActions(pl, iset); act++) { GameActionRep *action = m_support.GetAction(pl, iset, act); GetPayoff(node->GetChild(action->GetNumber()), prob * GetActionProb(action), player, value); } } } } template T MixedBehavProfile::GetPayoff(int player) const { T value = (T) 0; GetPayoff(m_support.GetGame()->GetRoot(), (T) 1, player, value); return value; } // // The following routines compute the derivatives of quantities as // the probability of the action 'p_oppAction' is changed. // See Turocy (2001), "Computing the Quantal Response Equilibrium // Correspondence" for details. // These assume that the profile is interior (totally mixed), // and that the game is of perfect recall // template T MixedBehavProfile::DiffActionValue(const GameAction &p_action, const GameAction &p_oppAction) const { ComputeSolutionData(); T deriv = (T) 0; GameInfoset infoset = p_action->GetInfoset(); GamePlayer player = p_action->GetInfoset()->GetPlayer(); for (int i = 1; i <= infoset->NumMembers(); i++) { GameNode member = infoset->GetMember(i); GameNode child = member->GetChild(p_action->m_number); deriv += DiffRealizProb(member, p_oppAction) * (m_nodeValues(child->number, player->GetNumber()) - m_actionValues(p_action->GetInfoset()->GetPlayer()->GetNumber(), p_action->GetInfoset()->GetNumber(), p_action->m_number)); deriv += m_realizProbs[member->number] * DiffNodeValue(member->GetChild(p_action->m_number), player, p_oppAction); } return deriv / GetInfosetProb(p_action->GetInfoset()); } template T MixedBehavProfile::DiffRealizProb(const GameNode &p_node, const GameAction &p_oppAction) const { ComputeSolutionData(); T deriv = (T) 1; bool isPrec = false; GameNode node = p_node; while (node->GetParent()) { GameAction prevAction = node->GetPriorAction(); if (prevAction != p_oppAction) { deriv *= GetActionProb(prevAction); } else { isPrec = true; } node = node->GetParent(); } return (isPrec) ? deriv : (T) 0.0; } template T MixedBehavProfile::DiffNodeValue(const GameNode &p_node, const GamePlayer &p_player, const GameAction &p_oppAction) const { ComputeSolutionData(); if (p_node->NumChildren() > 0) { GameInfoset infoset = p_node->GetInfoset(); if (infoset == p_oppAction->GetInfoset()) { // We've encountered the action; since we assume perfect recall, // we won't encounter it again, and the downtree value must // be the same. return m_nodeValues(p_node->GetChild(p_oppAction->GetNumber())->number, p_player->GetNumber()); } else { T deriv = (T) 0; for (int act = 1; act <= infoset->NumActions(); act++) { deriv += (DiffNodeValue(p_node->GetChild(act), p_player, p_oppAction) * GetActionProb(infoset->GetAction(act))); } return deriv; } } else { // If we reach a terminal node and haven't encountered p_oppAction, // derivative wrt this path is zero. return (T) 0; } } //======================================================================== // MixedBehavProfile: Cached profile information //======================================================================== template void MixedBehavProfile::ComputeSolutionDataPass2(const GameNode &node) const { if (node->outcome) { for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { m_nodeValues(node->number, pl) += node->outcome->GetPayoff(pl); } } GameInfoset iset = node->infoset; if (iset) { T infosetProb = (T) 0; for (int i = 1; i <= iset->NumMembers(); i++) { infosetProb += m_realizProbs[iset->GetMember(i)->number]; } if (infosetProb != infosetProb * (T) 0) { m_beliefs[node->number] = m_realizProbs[node->number] / infosetProb; } // push down payoffs from outcomes attached to non-terminal nodes for (int child = 1; child <= node->NumChildren(); child++) { m_nodeValues.SetRow(node->GetChild(child)->number, m_nodeValues.Row(node->number)); } for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { m_nodeValues(node->number, pl) = (T) 0; } for (int child = 1; child <= node->NumChildren(); child++) { GameNode childNode = node->GetChild(child); ComputeSolutionDataPass2(childNode); GameAction act = childNode->GetPriorAction(); for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { m_nodeValues(node->number, pl) += GetActionProb(act) * m_nodeValues(childNode->number, pl); } if (!iset->IsChanceInfoset()) { T &cpay = m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->m_number); if (infosetProb != infosetProb * (T) 0) { cpay += m_beliefs[node->number] * m_nodeValues(childNode->number, iset->GetPlayer()->GetNumber()); } else { cpay = (T) 0; } } } } } // compute realization probabilities for nodes and isets. template void MixedBehavProfile::ComputeSolutionDataPass1(const GameNode &node) const { if (node->GetParent()) { m_realizProbs[node->number] = m_realizProbs[node->GetParent()->number] * GetActionProb(node->GetPriorAction()); } else { m_realizProbs[node->number] = (T) 1; } if (node->GetInfoset()) { for (int i = 1; i <= node->NumChildren(); i++) { ComputeSolutionDataPass1(node->GetChild(i)); } } } template void MixedBehavProfile::ComputeSolutionData(void) const { if (!m_cacheValid) { m_actionValues = (T) 0; m_nodeValues = (T) 0; m_infosetValues = (T) 0; m_gripe = (T) 0; ComputeSolutionDataPass1(m_support.GetGame()->GetRoot()); ComputeSolutionDataPass2(m_support.GetGame()->GetRoot()); // At this point, mark the cache as value, so calls to GetInfosetValue() // don't create a loop. m_cacheValid = true; for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { for (int iset = 1; iset <= m_support.GetGame()->NumInfosets()[pl]; iset++) { GameInfoset infoset = m_support.GetGame()->GetPlayer(pl)->GetInfoset(iset); m_infosetValues(infoset->GetPlayer()->GetNumber(), infoset->GetNumber()) = (T) 0; for (int act = 1; act <= infoset->NumActions(); act++) { GameAction action = infoset->GetAction(act); m_infosetValues(infoset->GetPlayer()->GetNumber(), infoset->GetNumber()) += GetActionProb(action) * ActionValue(action); } for (int act = 1; act <= infoset->NumActions(); act++) { GameAction action = infoset->GetAction(act); m_gripe(action->GetInfoset()->GetPlayer()->GetNumber(), action->GetInfoset()->GetNumber(), action->m_number) = (ActionValue(action) - GetInfosetValue(infoset)) * GetInfosetProb(infoset); } } } } } template bool MixedBehavProfile::IsDefinedAt(GameInfoset p_infoset) const { for (int act = 1; act <= p_infoset->NumActions(); act++) { if (GetActionProb(p_infoset->GetAction(act)) > (T) 0) { return true; } } return false; } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/behavitr.cc0000644000076500007650000001141411435216101015267 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/behavitr.cc // Implementation of extensive form action iterators // // 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. // // // This file is part of Gambit // Copyright (c) 2002, The Gambit Project // // 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 "libgambit.h" namespace Gambit { BehavIterator::BehavIterator(const BehavSupport &p_support) : m_atEnd(false), m_support(p_support), m_currentBehav(p_support.GetGame()->NumInfosets()), m_profile(p_support.GetGame()), m_frozenPlayer(0), m_frozenInfoset(0), m_numActiveInfosets(m_support.GetGame()->NumPlayers()) { for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { GamePlayer player = m_support.GetGame()->GetPlayer(pl); m_numActiveInfosets[pl] = 0; Array activeForPl(player->NumInfosets()); for (int iset = 1; iset <= player->NumInfosets(); iset++) { activeForPl[iset] = m_support.MayReach(player->GetInfoset(iset)); m_numActiveInfosets[pl]++; } m_isActive.Append(activeForPl); } First(); } BehavIterator::BehavIterator(const BehavSupport &p_support, const GameAction &p_action) : m_atEnd(false), m_support(p_support), m_currentBehav(p_support.GetGame()->NumInfosets()), m_profile(p_support.GetGame()), m_frozenPlayer(p_action->GetInfoset()->GetPlayer()->GetNumber()), m_frozenInfoset(p_action->GetInfoset()->GetNumber()), m_numActiveInfosets(m_support.GetGame()->NumPlayers()) { for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { GamePlayer player = m_support.GetGame()->GetPlayer(pl); m_numActiveInfosets[pl] = 0; Array activeForPl(player->NumInfosets()); for (int iset = 1; iset <= player->NumInfosets(); iset++) { activeForPl[iset] = p_support.MayReach(player->GetInfoset(iset)); m_numActiveInfosets[pl]++; } m_isActive.Append(activeForPl); } m_currentBehav(p_action->GetInfoset()->GetPlayer()->GetNumber(), p_action->GetInfoset()->GetNumber()) = p_support.GetIndex(p_action); m_profile.SetAction(p_action); First(); } void BehavIterator::First(void) { for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { for (int iset = 1; iset <= m_support.GetGame()->GetPlayer(pl)->NumInfosets(); iset++) { if (pl != m_frozenPlayer && iset != m_frozenInfoset) { m_currentBehav(pl, iset) = 1; if (m_isActive[pl][iset]) { m_profile.SetAction(m_support.GetAction(pl, iset, 1)); } } } } } void BehavIterator::operator++(void) { int pl = m_support.GetGame()->NumPlayers(); while (pl > 0 && m_numActiveInfosets[pl] == 0) --pl; if (pl == 0) { m_atEnd = true; return; } int iset = m_support.GetGame()->GetPlayer(pl)->NumInfosets(); while (true) { if (m_isActive[pl][iset] && (pl != m_frozenPlayer || iset != m_frozenInfoset)) if (m_currentBehav(pl, iset) < m_support.NumActions(pl, iset)) { m_profile.SetAction(m_support.GetAction(pl, iset, ++m_currentBehav(pl, iset))); return; } else { m_currentBehav(pl, iset) = 1; m_profile.SetAction(m_support.GetAction(pl, iset, 1)); } iset--; if (iset == 0) { do { --pl; } while (pl > 0 && m_numActiveInfosets[pl] == 0); if (pl == 0) { m_atEnd = true; return; } iset = m_support.GetGame()->GetPlayer(pl)->NumInfosets(); } } } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/behavitr.h0000644000076500007650000000520511435216101015132 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/behavitr.h // Interface to extensive form action iterators // // 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 LIBGAMBIT_BEHAVITR_H #define LIBGAMBIT_BEHAVITR_H #include "behavspt.h" namespace Gambit { // // N.B.: Currently, the contingency iterator only allows one information // set to be "frozen". There is a list of "active" information // sets, which are those whose actions are cycled over, the idea // being that behavior at inactive information sets is irrelevant. // // Iterating across all contingencies can be achieved by freezing // player number 0 (this is the default state on initialization) // class BehavIterator { private: bool m_atEnd; BehavSupport m_support; PVector m_currentBehav; PureBehavProfile m_profile; int m_frozenPlayer, m_frozenInfoset; Array > m_isActive; Array m_numActiveInfosets; /// Reset the iterator to the first contingency (this is called by ctors) void First(void); public: /// @name Lifecycle //@{ /// Construct a new iterator on the support, with no actions held fixed BehavIterator(const BehavSupport &); /// Construct a new iterator on the support, holding the action fixed BehavIterator(const BehavSupport &, const GameAction &); //@} /// @name Iteration and data access //@{ /// Advance to the next contingency (prefix version) void operator++(void); /// Advance to the next contingency (postfix version) void operator++(int) { ++(*this); } /// Has iterator gone past the end? bool AtEnd(void) const { return m_atEnd; } /// Get the current behavior profile const PureBehavProfile &operator*(void) const { return m_profile; } /// Get the current behavior profile const PureBehavProfile *const operator->(void) const { return &m_profile; } //@} }; } // end namespace Gambit #endif // LIBGAMBIT_BEHAVITR_H gambit-0.2010.09.01/src/libgambit/behavspt.cc0000644000076500007650000005070711435216101015307 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/behavspt.cc // Implementation of supports for extensive forms // // 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 "libgambit.h" namespace Gambit { //======================================================================== // BehavSupport: Lifecycle //======================================================================== BehavSupport::BehavSupport(const Game &p_efg) : m_efg(p_efg), m_infosetActive(0, p_efg->NumPlayers()), m_nonterminalActive(0, p_efg->NumPlayers()) { for (int pl = 1; pl <= p_efg->NumPlayers(); pl++) { m_actions.Append(Array >()); GamePlayer player = p_efg->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); m_actions[pl].Append(Array()); for (int act = 1; act <= infoset->NumActions(); act++) { m_actions[pl][iset].Append(infoset->GetAction(act)); } } } // Initialize the list of reachable information sets and nodes for (int pl = 0; pl <= GetGame()->NumPlayers(); pl++) { GamePlayer player = (pl == 0) ? GetGame()->GetChance() : GetGame()->GetPlayer(pl); List is_players_infoset_active; List > is_players_node_active; for (int iset = 1; iset <= player->NumInfosets(); iset++) { is_players_infoset_active.Append(false); List is_infosets_node_active; for (int n = 1; n <= player->GetInfoset(iset)->NumMembers() ; n++) is_infosets_node_active.Append(false); is_players_node_active.Append(is_infosets_node_active); } m_infosetActive[pl] = is_players_infoset_active; m_nonterminalActive[pl] = is_players_node_active; } ActivateSubtree(GetGame()->GetRoot()); } //======================================================================== // BehavSupport: Operator overloading //======================================================================== bool BehavSupport::operator==(const BehavSupport &p_support) const { return (m_actions == p_support.m_actions); } //======================================================================== // BehavSupport: General information //======================================================================== PVector BehavSupport::NumActions(void) const { PVector answer(m_efg->NumInfosets()); for (int pl = 1; pl <= m_efg->NumPlayers(); pl++) { for (int iset = 1; iset <= m_efg->GetPlayer(pl)->NumInfosets(); iset++) { answer(pl, iset) = NumActions(pl, iset); } } return answer; } int BehavSupport::GetIndex(const GameAction &a) const { if (a->GetInfoset()->GetGame() != m_efg) throw MismatchException(); int pl = a->GetInfoset()->GetPlayer()->GetNumber(); if (pl == 0) { // chance action; all chance actions are always in the support return a->GetNumber(); } else { return m_actions[pl][a->GetInfoset()->GetNumber()].Find(a); } } int BehavSupport::NumDegreesOfFreedom(void) const { int answer = 0; PVector reachable(GetGame()->NumInfosets()); reachable = 0; ReachableInfosets(GetGame()->GetRoot(), reachable); for (int i = 1; i <= reachable.Length(); i++) { answer += reachable[i]; } return answer; } bool BehavSupport::HasActiveActionAt(const GameInfoset &infoset) const { return (m_actions[infoset->GetPlayer()->GetNumber()][infoset->GetNumber()].Length() > 0); } bool BehavSupport::HasActiveActionsAtAllInfosets(void) const { for (int pl = 1; pl <= m_actions.Length(); pl++) { for (int iset = 1; iset <= m_actions[pl].Length(); iset++) { if (m_actions[pl][iset].Length() == 0) return false; } } return true; } bool BehavSupport::RemoveAction(const GameAction &s) { List startlist(ReachableMembers(s->GetInfoset())); for (int i = 1; i <= startlist.Length(); i++) DeactivateSubtree(startlist[i]->GetChild(s->GetNumber())); GameInfoset infoset = s->GetInfoset(); GamePlayer player = infoset->GetPlayer(); Array &actions = m_actions[player->GetNumber()][infoset->GetNumber()]; if (!actions.Contains(s)) { return false; } else if (actions.Length() == 1) { actions.Remove(actions.Find(s)); return false; } else { actions.Remove(actions.Find(s)); return true; } } bool BehavSupport::RemoveAction(const GameAction &s, List &list) { List startlist(ReachableMembers(s->GetInfoset())); for (int i = 1; i <= startlist.Length(); i++) { DeactivateSubtree(startlist[i]->GetChild(s->GetNumber()), list); } // the following returns false if s was not in the support return RemoveAction(s); } void BehavSupport::AddAction(const GameAction &s) { GameInfoset infoset = s->GetInfoset(); GamePlayer player = infoset->GetPlayer(); Array &actions = m_actions[player->GetNumber()][infoset->GetNumber()]; int act = 1; while (act <= actions.Length()) { if (actions[act] == s) { break; } else if (actions[act]->GetNumber() > s->GetNumber()) { actions.Insert(s, act); break; } act++; } if (act > actions.Length()) { actions.Append(s); } List startlist(ReachableMembers(s->GetInfoset())); for (int i = 1; i <= startlist.Length(); i++) DeactivateSubtree(startlist[i]); } int BehavSupport::NumSequences(int j) const { if (j < 1 || j > m_efg->NumPlayers()) return 1; List isets = ReachableInfosets(m_efg->GetPlayer(j)); int num = 1; for(int i = 1; i <= isets.Length(); i++) num+=NumActions(isets[i]->GetPlayer()->GetNumber(), isets[i]->GetNumber()); return num; } int BehavSupport::NumSequences(void) const { int total = 0; for (int i = 1 ; i <= m_efg->NumPlayers(); i++) total += NumSequences(i); return total; } List BehavSupport::ReachableNonterminalNodes(const GameNode &n) const { List answer; if (!n->IsTerminal()) { int pl = n->GetInfoset()->GetPlayer()->GetNumber(); int iset = n->GetInfoset()->GetNumber(); for (int i = 1; i <= NumActions(pl, iset); i++) { GameNode nn = n->GetChild(GetAction(pl, iset, i)->GetNumber()); if (!nn->IsTerminal()) { answer.Append(nn); answer += ReachableNonterminalNodes(nn); } } } return answer; } List BehavSupport::ReachableInfosets(const GamePlayer &p) const { Array isets; for (int iset = 1; iset <= p->NumInfosets(); iset++) { isets.Append(p->GetInfoset(iset)); } List answer; for (int i = isets.First(); i <= isets.Last(); i++) if (MayReach(isets[i])) answer.Append(isets[i]); return answer; } void BehavSupport::ReachableInfosets(const GameNode &p_node, PVector &p_reached) const { if (p_node->NumChildren() == 0) return; GameInfoset infoset = p_node->GetInfoset(); if (!infoset->GetPlayer()->IsChance()) { p_reached(infoset->GetPlayer()->GetNumber(), infoset->GetNumber()) = 1; for (int act = 1; act <= NumActions(infoset); act++) { ReachableInfosets(p_node->GetChild(GetAction(infoset, act)->GetNumber()), p_reached); } } else { for (int act = 1; act <= infoset->NumActions(); act++) { ReachableInfosets(p_node->GetChild(act), p_reached); } } } bool BehavSupport::MayReach(const GameInfoset &i) const { for (int j = 1; j <= i->NumMembers(); j++) if (MayReach(i->GetMember(j))) return true; return false; } bool BehavSupport::MayReach(const GameNode &n) const { if (n == m_efg->GetRoot()) return true; else { if (!Contains(n->GetPriorAction())) return false; else return MayReach(n->GetParent()); } } // This class iterates // over contingencies that are relevant once a particular node // has been reached. class BehavConditionalIterator { private: bool m_atEnd; BehavSupport m_support; PVector m_currentBehav; PureBehavProfile m_profile; PVector m_isActive; Array m_numActiveInfosets; /// Reset the iterator to the first contingency (this is called by ctors) void First(void); public: /// @name Lifecycle //@{ BehavConditionalIterator(const BehavSupport &, const PVector &); //@} /// @name Iteration and data access //@{ /// Advance to the next contingency (prefix version) void operator++(void); /// Advance to the next contingency (postfix version) void operator++(int) { ++(*this); } /// Has iterator gone past the end? bool AtEnd(void) const { return m_atEnd; } /// Get the current behavior profile const PureBehavProfile &operator*(void) const { return m_profile; } /// Get the current behavior profile const PureBehavProfile *const operator->(void) const { return &m_profile; } //@} }; BehavConditionalIterator::BehavConditionalIterator(const BehavSupport &p_support, const PVector &p_active) : m_atEnd(false), m_support(p_support), m_profile(m_support.GetGame()), m_currentBehav(m_support.GetGame()->NumInfosets()), m_isActive(p_active), m_numActiveInfosets(m_support.GetGame()->NumPlayers()) { for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { m_numActiveInfosets[pl] = 0; GamePlayer player = m_support.GetGame()->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { if (m_isActive(pl, iset)) { m_numActiveInfosets[pl]++; } } } First(); } void BehavConditionalIterator::First(void) { for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { for (int iset = 1; iset <= m_support.GetGame()->GetPlayer(pl)->NumInfosets(); iset++) { m_currentBehav(pl, iset) = 1; if (m_isActive(pl, iset)) { m_profile.SetAction(m_support.GetAction(pl, iset, 1)); } } } } void BehavConditionalIterator::operator++(void) { int pl = m_support.GetGame()->NumPlayers(); while (pl > 0 && m_numActiveInfosets[pl] == 0) --pl; if (pl == 0) { m_atEnd = true; return; } int iset = m_support.GetGame()->GetPlayer(pl)->NumInfosets(); while (true) { if (m_isActive(pl, iset)) { if (m_currentBehav(pl, iset) < m_support.NumActions(pl, iset)) { m_profile.SetAction(m_support.GetAction(pl, iset, ++m_currentBehav(pl, iset))); return; } else { m_currentBehav(pl, iset) = 1; m_profile.SetAction(m_support.GetAction(pl, iset, 1)); } } iset--; if (iset == 0) { do { --pl; } while (pl > 0 && m_numActiveInfosets[pl] == 0); if (pl == 0) { m_atEnd = true; return; } iset = m_support.GetGame()->GetPlayer(pl)->NumInfosets(); } } } bool BehavSupport::Dominates(const GameAction &a, const GameAction &b, bool p_strict, bool p_conditional) const { GameInfoset infoset = a->GetInfoset(); if (infoset != b->GetInfoset()) { throw UndefinedException(); } GamePlayer player = infoset->GetPlayer(); int pl = player->GetNumber(); bool equal = true; if (!p_conditional) { for (BehavIterator iter(*this, a); !iter.AtEnd(); iter++) { Rational ap = iter->GetActionValue(a); Rational bp = iter->GetActionValue(b); if (p_strict) { if (ap <= bp) { return false; } } else { if (ap < bp) { return false; } else if (ap > bp) { equal = false; } } } } else { List nodelist = ReachableMembers(infoset); if (nodelist.Length() == 0) { // This may not be a good idea; I suggest checking for this // prior to entry for (int i = 1; i <= infoset->NumMembers(); i++) { nodelist.Append(infoset->GetMember(i)); } } for (int n = 1; n <= nodelist.Length(); n++) { PVector reachable(GetGame()->NumInfosets()); reachable = 0; ReachableInfosets(nodelist[n]->GetChild(a->GetNumber()), reachable); ReachableInfosets(nodelist[n]->GetChild(b->GetNumber()), reachable); for (BehavConditionalIterator iter(*this, reachable); !iter.AtEnd(); iter++) { Rational ap = iter->GetNodeValue(nodelist[n]->GetChild(a->GetNumber()), pl); Rational bp = iter->GetNodeValue(nodelist[n]->GetChild(b->GetNumber()), pl); if (p_strict) { if (ap <= bp) { return false; } } else { if (ap < bp) { return false; } else if (ap > bp) { equal = false; } } } } } if (p_strict) { return true; } else { return !equal; } } bool SomeElementDominates(const BehavSupport &S, const Array &array, const GameAction &a, const bool strong, const bool conditional) { for (int i = 1; i <= array.Length(); i++) if (array[i] != a) if (S.Dominates(array[i],a,strong,conditional)) { return true; } return false; } bool BehavSupport::IsDominated(const GameAction &a, bool strong, bool conditional) const { int pl = a->GetInfoset()->GetPlayer()->GetNumber(); int iset = a->GetInfoset()->GetNumber(); Array array(m_actions[pl][iset]); return SomeElementDominates(*this,array,a,strong,conditional); } bool InfosetHasDominatedElement(const BehavSupport &S, const GameInfoset &p_infoset, bool strong, bool conditional) { int pl = p_infoset->GetPlayer()->GetNumber(); int iset = p_infoset->GetNumber(); Array actions; for (int act = 1; act <= S.NumActions(pl, iset); act++) { actions.Append(S.GetAction(pl, iset, act)); } for (int i = 1; i <= actions.Length(); i++) if (SomeElementDominates(S,actions,actions[i], strong,conditional)) return true; return false; } bool ElimDominatedInInfoset(const BehavSupport &S, BehavSupport &T, int pl, int iset, bool strong, bool conditional) { Array actions; for (int act = 1; act <= S.NumActions(pl, iset); act++) { actions.Append(S.GetAction(pl, iset, act)); } Array is_dominated(actions.Length()); for (int k = 1; k <= actions.Length(); k++) is_dominated[k] = false; for (int i = 1; i <= actions.Length(); i++) for (int j = 1; j <= actions.Length(); j++) if (i != j && !is_dominated[i] && !is_dominated[j]) if (S.Dominates(actions[i], actions[j], strong, conditional)) { is_dominated[j] = true; } bool action_was_eliminated = false; int k = 1; while (k <= actions.Length() && !action_was_eliminated) { if (is_dominated[k]) action_was_eliminated = true; else k++; } while (k <= actions.Length()) { if (is_dominated[k]) T.RemoveAction(actions[k]); k++; } return action_was_eliminated; } bool ElimDominatedForPlayer(const BehavSupport &S, BehavSupport &T, const int pl, int &cumiset, const bool strong, const bool conditional) { bool action_was_eliminated = false; for (int iset = 1; iset <= S.GetGame()->GetPlayer(pl)->NumInfosets(); iset++, cumiset++) { if (ElimDominatedInInfoset(S, T, pl, iset, strong, conditional)) action_was_eliminated = true; } return action_was_eliminated; } BehavSupport BehavSupport::Undominated(bool strong, bool conditional, const Array &players, std::ostream &) const { BehavSupport T(*this); int cumiset = 0; for (int i = 1; i <= players.Length(); i++) { int pl = players[i]; ElimDominatedForPlayer(*this, T, pl, cumiset, strong, conditional); } return T; } // Utilities bool BehavSupport::HasActiveMembers(int pl, int iset) const { for (int i = 1; i <= m_nonterminalActive[pl][iset].Length(); i++) { if (m_nonterminalActive[pl][iset][i]) { return true; } } return false; } void BehavSupport::activate(const GameNode &n) { m_nonterminalActive[n->GetPlayer()->GetNumber()] [n->GetInfoset()->GetNumber()] [n->NumberInInfoset()] = true; } void BehavSupport::deactivate(const GameNode &n) { m_nonterminalActive[n->GetPlayer()->GetNumber()] [n->GetInfoset()->GetNumber()] [n->NumberInInfoset()] = false; } void BehavSupport::activate(const GameInfoset &i) { m_infosetActive[i->GetPlayer()->GetNumber()][i->GetNumber()] = true; } void BehavSupport::deactivate(const GameInfoset &i) { m_infosetActive[i->GetPlayer()->GetNumber()][i->GetNumber()] = false; } void BehavSupport::ActivateSubtree(const GameNode &n) { if (!n->IsTerminal()) { activate(n); activate(n->GetInfoset()); if (n->GetInfoset()->GetPlayer()->IsChance()) { for (int i = 1; i <= n->NumChildren(); i++) { ActivateSubtree(n->GetChild(i)); } } else { const Array &actions(m_actions[n->GetInfoset()->GetPlayer()->GetNumber()][n->GetInfoset()->GetNumber()]); for (int i = 1; i <= actions.Length(); i++) { ActivateSubtree(n->GetChild(actions[i]->GetNumber())); } } } } void BehavSupport::DeactivateSubtree(const GameNode &n) { if (!n->IsTerminal()) { // THIS ALL LOOKS FISHY deactivate(n); if ( !HasActiveMembers(n->GetInfoset()->GetPlayer()->GetNumber(), n->GetInfoset()->GetNumber())) { deactivate(n->GetInfoset()); } Array actions(m_actions[n->GetInfoset()->GetPlayer()->GetNumber()][n->GetInfoset()->GetNumber()]); for (int i = 1; i <= actions.Length(); i++) { DeactivateSubtree(n->GetChild(actions[i]->GetNumber())); } } } void BehavSupport::DeactivateSubtree(const GameNode &n, List &list) { if (!n->IsTerminal()) { deactivate(n); if (!HasActiveMembers(n->GetInfoset()->GetPlayer()->GetNumber(), n->GetInfoset()->GetNumber())) { list.Append(n->GetInfoset()); deactivate(n->GetInfoset()); } Array actions(m_actions[n->GetInfoset()->GetPlayer()->GetNumber()][n->GetInfoset()->GetNumber()]); for (int i = 1; i <= actions.Length(); i++) { DeactivateSubtree(n->GetChild(actions[i]->GetNumber()), list); } } } List BehavSupport::ReachableMembers(const GameInfoset &i) const { List answer; int pl = i->GetPlayer()->GetNumber(); int iset = i->GetNumber(); for (int j = 1; j <= i->NumMembers(); j++) if (m_nonterminalActive[pl][iset][j]) answer.Append(i->GetMember(j)); return answer; } List BehavSupport::ReachableNonterminalNodes(void) const { List answer; for (int pl = 1; pl <= GetGame()->NumPlayers(); pl++) { GamePlayer p = GetGame()->GetPlayer(pl); for (int iset = 1; iset <= p->NumInfosets(); iset++) answer += ReachableMembers(p->GetInfoset(iset)); } return answer; } int BehavSupport::NumActiveMembers(const GameInfoset &p_infoset) const { int answer = 0; int pl = p_infoset->GetPlayer()->GetNumber(); int iset = p_infoset->GetNumber(); for (int i = 1; i <= m_nonterminalActive[pl][iset].Length(); i++) { if (m_nonterminalActive[pl][iset][i]) { answer++; } } return answer; } bool BehavSupport::IsActive(const GameInfoset &i) const { return m_infosetActive[i->GetPlayer()->GetNumber()][i->GetNumber()]; } bool BehavSupport::IsActive(const GameNode &n) const { return m_nonterminalActive[n->GetInfoset()->GetPlayer()->GetNumber()] [n->GetInfoset()->GetNumber()][n->NumberInInfoset()]; } bool BehavSupport::HasActiveActionsAtActiveInfosets(void) const { for (int pl = 1; pl <= GetGame()->NumPlayers(); pl++) { for (int iset = 1; iset <= GetGame()->GetPlayer(pl)->NumInfosets(); iset++) { if (m_infosetActive[pl][iset] && NumActions(pl, iset) == 0) { return false; } } } return true; } bool BehavSupport::HasActiveActionsAtActiveInfosetsAndNoOthers(void) const { for (int pl = 1; pl <= GetGame()->NumPlayers(); pl++) { for (int iset = 1; iset <= GetGame()->GetPlayer(pl)->NumInfosets(); iset++) { if (m_infosetActive[pl][iset] && NumActions(pl, iset) == 0) { return false; } if (!m_infosetActive[pl][iset] && NumActions(pl, iset) > 0) { return false; } } } return true; } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/behavspt.h0000644000076500007650000001411511435216101015142 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/behavspt.h // Interface to supports for extensive forms // // 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 LIBGAMBIT_BEHAVSPT_H #define LIBGAMBIT_BEHAVSPT_H #include "game.h" namespace Gambit { /// This class represents a subset of the actions in an extensive game. /// It is enforced that each player has at least one action at each /// information set; thus, the actions in a support can be viewed as /// a restriction of a game to a subset of its actions. This is useful /// for eliminating dominated strategies from consideration, and in /// computational approaches that enumerate possible equilibrium /// supports. class BehavSupport { protected: Game m_efg; Array > > m_actions; Array > m_infosetActive; Array > > m_nonterminalActive; void activate(const GameNode &); void deactivate(const GameNode &); void activate(const GameInfoset &); void deactivate(const GameInfoset &); bool HasActiveMembers(int pl, int iset) const; void ActivateSubtree(const GameNode &); void DeactivateSubtree(const GameNode &); void DeactivateSubtree(const GameNode &, List &); public: /// @name Lifecycle //@{ /// Constructor. By default, a support contains all strategies. BehavSupport(const Game &); ~BehavSupport() { } //@} /// @name Operator overloading //@{ /// Test for the equality of two supports (same actions at all infosets) bool operator==(const BehavSupport &) const; bool operator!=(const BehavSupport &p_support) const { return !(*this == p_support); } /// @name General information //@{ /// Returns the game on which the support is defined. Game GetGame(void) const { return m_efg; } /// Returns the number of actions in the information set int NumActions(const GameInfoset &p_infoset) const { return m_actions[p_infoset->GetPlayer()->GetNumber()][p_infoset->GetNumber()].Length(); } int NumActions(int pl, int iset) const { return m_actions[pl][iset].Length(); } /// Returns the number of actions in the support for all information sets PVector NumActions(void) const; /// Returns the action at the specified position in the support GameAction GetAction(const GameInfoset &p_infoset, int p_act) const { return m_actions[p_infoset->GetPlayer()->GetNumber()][p_infoset->GetNumber()][p_act]; } GameAction GetAction(int pl, int iset, int act) const { return m_actions[pl][iset][act]; } /// Returns the position of the action in the support. int GetIndex(const GameAction &) const; /// Returns whether the action is in the support. bool Contains(const GameAction &p_action) const { return (GetIndex(p_action) != 0); } /// The dimension of a behavior strategy at reachable information sets int NumDegreesOfFreedom(void) const; /// Does the information set have at least one active action? bool HasActiveActionAt(const GameInfoset &) const; /// Do all information sets have at least one active action? bool HasActiveActionsAtAllInfosets(void) const; /// Total number of sequences int NumSequences(void) const; /// Number of sequences for a player int NumSequences(int pl) const; /// Is the information set active (i.e., reachable)? bool IsActive(const GameInfoset &) const; /// How many active members are there in the information set? int NumActiveMembers(const GameInfoset &) const; /// Is the node active (i.e., reachable)? bool IsActive(const GameNode &) const; /// Do all active information sets have actions in the support? bool HasActiveActionsAtActiveInfosets(void) const; /// Do only active information sets have actions in the support? bool HasActiveActionsAtActiveInfosetsAndNoOthers(void) const; //@} /// @name Editing the support //@{ /// Adds the action to the support; no effect if action is present already void AddAction(const GameAction &); /// Removes the action from the support; returns true if successful. bool RemoveAction(const GameAction &); /// Removes the action and returns the list of information sets /// made unreachable by the action's removal bool RemoveAction(const GameAction &, List &); //@} /// @name Reachability of nodes and information sets //@{ List ReachableNonterminalNodes(void) const; List ReachableNonterminalNodes(const GameNode &) const; /// Sets p_reachable(pl,iset) to 1 if infoset (pl,iset) reachable after p_node void ReachableInfosets(const GameNode &p_node, PVector &p_reachable) const; List ReachableInfosets(const GamePlayer &) const; bool MayReach(const GameNode &) const; bool MayReach(const GameInfoset &) const; List ReachableMembers(const GameInfoset &) const; //@} /// @name Identification of dominated actions //@{ /// Returns true if action a is dominated by action b bool Dominates(const GameAction &a, const GameAction &b, bool p_strict, bool p_conditional) const; /// Returns true if the action is dominated by some other action bool IsDominated(const GameAction &a, bool p_strict, bool p_conditional) const; /// Returns a copy of the support with dominated actions eliminated BehavSupport Undominated(bool p_strict, bool p_conditional, const Array &players, std::ostream &) const; //@} }; } // end namespace Gambit #endif // LIBGAMBIT_BEHAVSPT_H gambit-0.2010.09.01/src/libgambit/dvector.cc0000644000076500007650000000204511435216101015131 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/dvector.cc // Instantiation of doubly partitioned vector types // // 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 "libgambit.h" #include "dvector.imp" template class Gambit::DVector; template class Gambit::DVector; gambit-0.2010.09.01/src/libgambit/dvector.h0000644000076500007650000000441011435216101014771 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/dvector.h // Doubly-partitioned vector class // // 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 LIBGAMBIT_DVECTOR_H #define LIBGAMBIT_DVECTOR_H #include "pvector.h" namespace Gambit { template class DVector : public PVector { private: int sum(int part, const PVector &v) const; void setindex(void); bool Check(const DVector &) const; protected: T ***dvptr; Array dvlen, dvidx; public: DVector(void); DVector(const PVector &sig); DVector(const Vector &val, const PVector &sig); DVector(const DVector &v); virtual ~DVector(); T &operator()(int a, int b, int c); const T &operator()(int a, int b, int c) const; // extract a subvector void CopySubRow(int row, int col, const DVector &v); DVector &operator=(const DVector &v); DVector &operator=(const PVector &v); DVector &operator=(const Vector &v); DVector &operator=(T c); DVector operator+(const DVector &v) const; DVector &operator+=(const DVector &v); DVector operator-(void) const; DVector operator-(const DVector &v) const; DVector &operator-=(const DVector &v); T operator*(const DVector &v) const; DVector &operator*=(const T &c); DVector operator/(const T &c) const; bool operator==(const DVector &v) const; bool operator!=(const DVector &v) const; const Array &DPLengths(void) const; }; } // end namespace Gambit #endif // LIBGAMBIT_DVECTOR_H gambit-0.2010.09.01/src/libgambit/dvector.imp0000644000076500007650000001520211435216101015330 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/dvector.imp // Implementation of doubly-partitioned vector class // // 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 "dvector.h" namespace Gambit { //-------------------------------------------------------------------------- // DVector: Private and protected member functions //-------------------------------------------------------------------------- template int DVector::sum(int part, const PVector &v) const { int s = 0; Array len(v.Lengths()); for (int j = 1; j <= len[part]; j++) s += v(part, j); return s; } template void DVector::setindex(void) { int index = 1; for (int i = 1; i <= dvlen.Length(); i++) { dvptr[i] = this->svptr + index - 1; dvidx[i] = index; index += dvlen[i]; } } template bool DVector::Check(const DVector &v) const { for (int i = 1; i <= dvlen.Length(); i++) if (dvlen[i] != v.dvlen[i]) return false; return true; } //-------------------------------------------------------------------------- // DVector: Constructors, destructor, and constructive operators //-------------------------------------------------------------------------- template DVector::DVector(void) : dvptr(0) { } template DVector::DVector(const PVector &sig) : PVector((Array)sig), dvlen(sig.Lengths().Length()), dvidx(sig.Lengths().Length()) { dvptr = new T **[dvlen.Length()]; dvptr -= 1; for (int i = 1; i <= dvlen.Length(); i++) dvlen[i] = sig.Lengths()[i]; setindex(); } template DVector::DVector(const Vector &val, const PVector &sig) : PVector(val, sig), dvlen(sig.Lengths().Length()), dvidx(sig.Lengths().Length()) { dvptr = new T **[dvlen.Length()]; dvptr -= 1; for (int i = 1; i <= dvlen.Length(); i++) dvlen[i] = sig.Lengths()[i]; setindex(); } template DVector::DVector(const DVector &v) : PVector(v), dvlen(v.dvlen), dvidx(v.dvidx) { dvptr = new T **[dvlen.Length()]; dvptr -= 1; setindex(); } template DVector::~DVector() { if (dvptr) delete [] (dvptr + 1); } template DVector &DVector::operator=(const DVector &v) { if (!Check(v)) { throw DimensionException(); } PVector::operator=(v); return *this; } template DVector &DVector::operator=(const PVector &v) { PVector::operator=(v); return *this; } template DVector &DVector::operator=(const Vector &v) { PVector::operator=(v); return *this; } template DVector &DVector::operator=(T c) { PVector::operator=(c); return *this; } //-------------------------------------------------------------------------- // DVector: Operator definitions //-------------------------------------------------------------------------- template T &DVector::operator()(int a, int b, int c) { if (dvlen.First() > a || a > dvlen.Last()) { throw IndexException(); } if (1 > b || b > dvlen[a]) { throw IndexException(); } if (1 > c || c > this->svlen[dvidx[a] + b - 1]) { throw IndexException(); } return dvptr[a][b][c]; } template const T &DVector::operator()(int a, int b, int c) const { if (dvlen.First() > a || a > dvlen.Last()) { throw IndexException(); } if (1 > b || b > dvlen[a]) { throw IndexException(); } if (1 > c || c > this->svlen[dvidx[a] + b - 1]) { throw IndexException(); } return dvptr[a][b][c]; } template DVector DVector::operator+(const DVector &v) const { if (!Check(v)) { throw DimensionException(); } DVector tmp(*this); tmp.PVector::operator+=(v); return tmp; } template DVector &DVector::operator+=(const DVector &v) { if (!Check(v)) { throw DimensionException(); } PVector::operator+=(v); return *this; } template DVector DVector::operator-(void) const { DVector tmp(*this); for (int i = this->First(); i <= this->Last(); i++) tmp[i] = -tmp[i]; return tmp; } template DVector DVector::operator-(const DVector &v) const { if (!Check(v)) { throw DimensionException(); } DVector tmp(*this); tmp.PVector::operator-=(v); return tmp; } template DVector &DVector::operator-=(const DVector &v) { if (!Check(v)) { throw DimensionException(); } PVector::operator-=(v); return *this; } template T DVector::operator*(const DVector &v) const { if (!Check(v)) { throw DimensionException(); } return (*this).PVector::operator*(v); } template DVector &DVector::operator*=(const T &c) { PVector::operator*=(c); return *this; } template DVector DVector::operator/(const T &c) const { DVector tmp(*this); tmp = tmp.PVector::operator/(c); return tmp; } template bool DVector::operator==(const DVector &v) const { if (!Check(v)) { throw DimensionException(); } return PVector::operator==(v); } template bool DVector::operator!=(const DVector &v) const { return !(*this == v); } //------------------------------------------------------------------------- // DVector: General data access //------------------------------------------------------------------------- template void DVector::CopySubRow(int row, int col, const DVector &v) { if (!Check(v)) { throw DimensionException(); } if (dvlen.First() > row || row > dvlen.Last()) { throw IndexException(); } if (1 > col || col > dvlen[row]) { throw IndexException(); } for (int i = 1; i <= this->svlen[dvidx[row]+col-1]; i++) dvptr[row][col][i] = v.dvptr[row][col][i]; } template const Array &DVector::DPLengths(void) const { return dvlen; } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/file.cc0000644000076500007650000006162611441446351014425 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/file.cc // Parser for reading game savefiles // // 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 #include #include #include #include "libgambit.h" namespace Gambit { /// This extension to the game representation classes allows for efficient /// mass creation of outcomes. For large strategic games, sequentially /// creating outcomes as you find them (in the outcome version of the /// .nfg format) is brutally inefficient. For one 21x21x21x21 game, /// the naive code took about 97s to read the game; with this version, /// it takes about 5s on the same system. class TableFileGameRep : public GameRep { public: /// @name Lifecycle //@{ /// Construct a new table game with the given dimension, plus enough /// outcomes to fill the table TableFileGameRep(const Array &p_dim); //@} /// @name Extensions //@{ /// Delete all outcomes numbered above 'p_nOutcomes' void TruncateOutcomes(int p_nOutcomes); //@} }; TableFileGameRep::TableFileGameRep(const Array &p_dim) : GameRep(p_dim) { m_outcomes = Array(m_results.Length()); for (int i = 1; i <= m_outcomes.Length(); i++) { m_outcomes[i] = new GameOutcomeRep(this, i); } } void TableFileGameRep::TruncateOutcomes(int p_nOutcomes) { if (p_nOutcomes >= m_outcomes.Length()) { return; } Array outcomes(m_outcomes); m_outcomes = Array(p_nOutcomes); for (int i = 1; i <= p_nOutcomes; i++) { m_outcomes[i] = outcomes[i]; } // We just use 'delete' here, instead of Invalidate(), because this // code is only intended to be called in the file reader, and therefore // there should be no other references to these outcomes elsewhere for (int i = p_nOutcomes + 1; i <= outcomes.Length(); delete outcomes[i++]); } } namespace { // This anonymous namespace encapsulates the file-parsing code using namespace Gambit; typedef enum { TOKEN_NUMBER = 0, TOKEN_TEXT = 1, TOKEN_SYMBOL = 2, TOKEN_LBRACE = 3, TOKEN_RBRACE = 4, TOKEN_COMMA = 5, TOKEN_EOF = 6 } GameFileToken; //! //! This parser class implements the semantics of Gambit savefiles, //! including the nonsignificance of whitespace and the possibility of //! escaped-quotes within text labels. //! class GameParserState { private: std::istream &m_file; int m_currentLine; GameFileToken m_lastToken; std::string m_lastText; public: GameParserState(std::istream &p_file) : m_file(p_file), m_currentLine(1) { } GameFileToken GetNextToken(void); GameFileToken GetCurrentToken(void) const { return m_lastToken; } int GetCurrentLine(void) const { return m_currentLine; } const std::string &GetLastText(void) const { return m_lastText; } }; GameFileToken GameParserState::GetNextToken(void) { char c = ' '; if (m_file.eof()) { return (m_lastToken = TOKEN_EOF); } while (isspace(c)) { m_file.get(c); if (!m_file.good()) { return (m_lastToken = TOKEN_EOF); } else if (c == '\n') { m_currentLine++; } } if (c == '{') { return (m_lastToken = TOKEN_LBRACE); } else if (c == '}') { return (m_lastToken = TOKEN_RBRACE); } else if (c == ',') { return (m_lastToken = TOKEN_COMMA); } else if (isdigit(c) || c == '-' || c == '+') { std::string buf; buf += c; m_file.get(c); while (!m_file.eof() && m_file.good() && isdigit(c)) { buf += c; m_file.get(c); } if (m_file.eof() || !m_file.good()) { m_lastText = buf; return (m_lastToken = TOKEN_NUMBER); } if (c == '.') { buf += c; m_file.get(c); while (isdigit(c)) { buf += c; m_file.get(c); } if (c == 'e' || c == 'E') { buf += c; m_file.get(c); if (c == '+' && c == '-' && !isdigit(c)) { throw InvalidFileException(); } buf += c; m_file.get(c); while (isdigit(c)) { buf += c; m_file.get(c); } } m_file.unget(); m_lastText = buf; return (m_lastToken = TOKEN_NUMBER); } else if (c == '/') { buf += c; m_file.get(c); while (isdigit(c)) { buf += c; m_file.get(c); } m_file.unget(); m_lastText = buf; return (m_lastToken = TOKEN_NUMBER); } else if (c == 'e' || c == 'E') { buf += c; m_file.get(c); if (c == '+' && c == '-' && !isdigit(c)) { throw InvalidFileException(); } buf += c; m_file.get(c); while (isdigit(c)) { buf += c; m_file.get(c); } m_file.unget(); m_lastText = buf; return (m_lastToken = TOKEN_NUMBER); } else { m_file.unget(); m_lastText = buf; return (m_lastToken = TOKEN_NUMBER); } } else if (c == '.') { std::string buf; buf += c; m_file.get(c); while (isdigit(c)) { buf += c; m_file.get(c); } m_file.unget(); m_lastText = buf; return (m_lastToken = TOKEN_NUMBER); } else if (c == '"') { // We need to do a little magic here, since escaped quotes inside // the string are treated as quotes (not end-of-string) m_file.unget(); char a; m_lastText = ""; do { m_file.get(a); if (isspace(a) && a=='\n') { m_currentLine++; } } while (isspace(a)); if (a == '\"') { bool lastslash = false; m_file.get(a); while (a != '\"' || lastslash) { if (lastslash && a == '"') m_lastText += '"'; else if (lastslash) { m_lastText += '\\'; m_lastText += a; } else if (a != '\\') m_lastText += a; lastslash = (a == '\\'); m_file.get(a); } } else { do { m_lastText += a; m_file.get(a); if (isspace(a) && a=='\n') { m_currentLine++; } } while (!isspace(a)); } return (m_lastToken = TOKEN_TEXT); } m_lastText = ""; while (!isspace(c) && !m_file.eof()) { m_lastText += c; m_file.get(c); } return (m_lastToken = TOKEN_SYMBOL); } class TableFilePlayer { public: std::string m_name; Array m_strategies; TableFilePlayer *m_next; TableFilePlayer(void); }; TableFilePlayer::TableFilePlayer(void) : m_next(0) { } class TableFileGame { public: std::string m_title, m_comment; TableFilePlayer *m_firstPlayer, *m_lastPlayer; int m_numPlayers; TableFileGame(void); ~TableFileGame(); void AddPlayer(const std::string &); int NumPlayers(void) const { return m_numPlayers; } int NumStrategies(int pl) const; std::string GetPlayer(int pl) const; std::string GetStrategy(int pl, int st) const; }; TableFileGame::TableFileGame(void) : m_firstPlayer(0), m_lastPlayer(0), m_numPlayers(0) { } TableFileGame::~TableFileGame() { if (m_firstPlayer) { TableFilePlayer *player = m_firstPlayer; while (player) { TableFilePlayer *nextPlayer = player->m_next; delete player; player = nextPlayer; } } } void TableFileGame::AddPlayer(const std::string &p_name) { TableFilePlayer *player = new TableFilePlayer; player->m_name = p_name; if (m_firstPlayer) { m_lastPlayer->m_next = player; m_lastPlayer = player; } else { m_firstPlayer = player; m_lastPlayer = player; } m_numPlayers++; } int TableFileGame::NumStrategies(int p_player) const { TableFilePlayer *player = m_firstPlayer; int pl = 1; while (player && pl < p_player) { player = player->m_next; pl++; } if (!player) { return 0; } else { return player->m_strategies.Length(); } } std::string TableFileGame::GetPlayer(int p_player) const { TableFilePlayer *player = m_firstPlayer; int pl = 1; while (player && pl < p_player) { player = player->m_next; pl++; } if (!player) { return ""; } else { return player->m_name; } } std::string TableFileGame::GetStrategy(int p_player, int p_strategy) const { TableFilePlayer *player = m_firstPlayer; int pl = 1; while (player && pl < p_player) { player = player->m_next; pl++; } if (!player) { return ""; } else { return player->m_strategies[p_strategy]; } } void ReadPlayers(GameParserState &p_state, TableFileGame &p_data) { if (p_state.GetNextToken() != TOKEN_LBRACE) { throw InvalidFileException(); } while (p_state.GetNextToken() == TOKEN_TEXT) { p_data.AddPlayer(p_state.GetLastText()); } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { throw InvalidFileException(); } p_state.GetNextToken(); } void ReadStrategies(GameParserState &p_state, TableFileGame &p_data) { if (p_state.GetCurrentToken() != TOKEN_LBRACE) { throw InvalidFileException(); } p_state.GetNextToken(); if (p_state.GetCurrentToken() == TOKEN_LBRACE) { TableFilePlayer *player = p_data.m_firstPlayer; while (p_state.GetCurrentToken() == TOKEN_LBRACE) { if (!player) { // Not enough players for number of strategy entries throw InvalidFileException(); } while (p_state.GetNextToken() == TOKEN_TEXT) { player->m_strategies.Append(p_state.GetLastText()); } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { throw InvalidFileException(); } p_state.GetNextToken(); player = player->m_next; } if (player) { // Players with strategies undefined throw InvalidFileException(); } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { throw InvalidFileException(); } p_state.GetNextToken(); } else if (p_state.GetCurrentToken() == TOKEN_NUMBER) { TableFilePlayer *player = p_data.m_firstPlayer; while (p_state.GetCurrentToken() == TOKEN_NUMBER) { if (!player) { // Not enough players for number of strategy entries throw InvalidFileException(); } for (int st = 1; st <= atoi(p_state.GetLastText().c_str()); st++) { player->m_strategies.Append(ToText(Integer(st))); } p_state.GetNextToken(); player = player->m_next; } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { throw InvalidFileException(); } if (player) { // Players with strategies undefined throw InvalidFileException(); } p_state.GetNextToken(); } else { throw InvalidFileException(); } } void ParseNfgHeader(GameParserState &p_state, TableFileGame &p_data) { if (p_state.GetNextToken() != TOKEN_NUMBER || p_state.GetLastText() != "1") { throw InvalidFileException(); } if (p_state.GetNextToken() != TOKEN_SYMBOL || (p_state.GetLastText() != "D" && p_state.GetLastText() != "R")) { throw InvalidFileException(); } if (p_state.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(); } p_data.m_title = p_state.GetLastText(); ReadPlayers(p_state, p_data); ReadStrategies(p_state, p_data); if (p_state.GetCurrentToken() == TOKEN_TEXT) { // Read optional comment p_data.m_comment = p_state.GetLastText(); p_state.GetNextToken(); } } void ReadOutcomeList(GameParserState &p_parser, TableFileGameRep *p_nfg) { if (p_parser.GetNextToken() == TOKEN_RBRACE) { // Special case: empty outcome list p_parser.GetNextToken(); return; } if (p_parser.GetCurrentToken() != TOKEN_LBRACE) { throw InvalidFileException(); } int nOutcomes = 0; while (p_parser.GetCurrentToken() == TOKEN_LBRACE) { nOutcomes++; int pl = 1; if (p_parser.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(); } GameOutcome outcome; try { outcome = p_nfg->GetOutcome(nOutcomes); } catch (IndexException &) { // It might happen that the file contains more outcomes than // contingencies. If so, just create them on the fly. outcome = p_nfg->NewOutcome(); } outcome->SetLabel(p_parser.GetLastText()); p_parser.GetNextToken(); try { while (p_parser.GetCurrentToken() == TOKEN_NUMBER) { outcome->SetPayoff(pl++, p_parser.GetLastText()); if (p_parser.GetNextToken() == TOKEN_COMMA) { p_parser.GetNextToken(); } } } catch (IndexException &) { // This would be triggered by too many payoffs throw InvalidFileException(); } if (pl <= p_nfg->NumPlayers() || p_parser.GetCurrentToken() != TOKEN_RBRACE) { throw InvalidFileException(); } p_parser.GetNextToken(); } p_nfg->TruncateOutcomes(nOutcomes); if (p_parser.GetCurrentToken() != TOKEN_RBRACE) { throw InvalidFileException(); } p_parser.GetNextToken(); } void ParseOutcomeBody(GameParserState &p_parser, TableFileGameRep *p_nfg) { ReadOutcomeList(p_parser, p_nfg); StrategyIterator iter(StrategySupport(static_cast(p_nfg))); while (p_parser.GetCurrentToken() != TOKEN_EOF) { if (p_parser.GetCurrentToken() != TOKEN_NUMBER) { throw InvalidFileException(); } int outcomeId = atoi(p_parser.GetLastText().c_str()); if (outcomeId > 0) { iter->SetOutcome(p_nfg->GetOutcome(outcomeId)); } else { iter->SetOutcome(0); } p_parser.GetNextToken(); iter++; } } void ParsePayoffBody(GameParserState &p_parser, TableFileGameRep *p_nfg) { StrategyIterator iter(StrategySupport(static_cast(p_nfg))); int pl = 1; while (p_parser.GetCurrentToken() != TOKEN_EOF) { if (pl == 1) { iter->SetOutcome(p_nfg->NewOutcome()); } if (p_parser.GetCurrentToken() == TOKEN_NUMBER) { iter->GetOutcome()->SetPayoff(pl, p_parser.GetLastText()); } else { throw InvalidFileException(); } if (++pl > p_nfg->NumPlayers()) { iter++; pl = 1; } p_parser.GetNextToken(); } } Game BuildNfg(GameParserState &p_parser, TableFileGame &p_data) { Array dim(p_data.NumPlayers()); for (int pl = 1; pl <= dim.Length(); pl++) { dim[pl] = p_data.NumStrategies(pl); } TableFileGameRep *nfg = new TableFileGameRep(dim); // Assigning this to the container assures that, if something goes // wrong, the class will automatically be cleaned up Game game = nfg; nfg->SetTitle(p_data.m_title); nfg->SetComment(p_data.m_comment); for (int pl = 1; pl <= dim.Length(); pl++) { nfg->GetPlayer(pl)->SetLabel(p_data.GetPlayer(pl)); for (int st = 1; st <= dim[pl]; st++) { nfg->GetPlayer(pl)->GetStrategy(st)->SetLabel(p_data.GetStrategy(pl,st)); } } if (p_parser.GetCurrentToken() == TOKEN_LBRACE) { ParseOutcomeBody(p_parser, nfg); } else if (p_parser.GetCurrentToken() == TOKEN_NUMBER) { ParsePayoffBody(p_parser, nfg); } else { throw InvalidFileException(); } return game; } //========================================================================= // Temporary representation classes //========================================================================= #include "map.h" class TreeData { public: Map m_outcomeMap; Map m_chanceInfosetMap; List > m_infosetMap; TreeData(void) : m_outcomeMap(0), m_chanceInfosetMap(0) { } ~TreeData() { } }; void ReadPlayers(GameParserState &p_state, Game p_game, TreeData &p_treeData) { if (p_state.GetNextToken() != TOKEN_LBRACE) { throw InvalidFileException(); } while (p_state.GetNextToken() == TOKEN_TEXT) { p_game->NewPlayer()->SetLabel(p_state.GetLastText()); p_treeData.m_infosetMap.Append(Map(0)); } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { throw InvalidFileException(); } } // // Precondition: Parser state should be expecting the integer index // of the outcome in a node entry // // Postcondition: Parser state is past the outcome entry and should be // pointing to the 'c', 'p', or 't' token starting the // next node declaration. // void ParseOutcome(GameParserState &p_state, Game p_game, TreeData &p_treeData, GameNode p_node) { if (p_state.GetCurrentToken() != TOKEN_NUMBER) { throw InvalidFileException(); } int outcomeId = atoi(p_state.GetLastText().c_str()); p_state.GetNextToken(); if (p_state.GetCurrentToken() == TOKEN_TEXT) { // This node entry contains information about the outcome GameOutcome outcome; if (p_treeData.m_outcomeMap.IsDefined(outcomeId)) { outcome = p_treeData.m_outcomeMap.Lookup(outcomeId); } else { outcome = p_game->NewOutcome(); p_treeData.m_outcomeMap.Define(outcomeId, outcome); } outcome->SetLabel(p_state.GetLastText()); p_node->SetOutcome(outcome); if (p_state.GetNextToken() != TOKEN_LBRACE) { throw InvalidFileException(); } p_state.GetNextToken(); for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { if (p_state.GetCurrentToken() == TOKEN_NUMBER) { outcome->SetPayoff(pl, p_state.GetLastText()); } else { throw InvalidFileException(); } // Commas are optional between payoffs if (p_state.GetNextToken() == TOKEN_COMMA) { p_state.GetNextToken(); } } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { throw InvalidFileException(); } p_state.GetNextToken(); } else if (outcomeId != 0) { // The node entry does not contain information about the outcome. // This means the outcome better have been defined already; // if not, raise an error. if (p_treeData.m_outcomeMap.IsDefined(outcomeId)) { p_node->SetOutcome(p_treeData.m_outcomeMap.Lookup(outcomeId)); } else { throw InvalidFileException(); } } } void ParseNode(GameParserState &p_state, Game p_game, GameNode p_node, TreeData &p_treeData); // // Precondition: parser state is expecting the node label // // Postcondition: parser state is pointing at the 'c', 'p', or 't' // beginning the next node entry // void ParseChanceNode(GameParserState &p_state, Game p_game, GameNode p_node, TreeData &p_treeData) { if (p_state.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(); } p_node->SetLabel(p_state.GetLastText()); if (p_state.GetNextToken() != TOKEN_NUMBER) { throw InvalidFileException(); } int infosetId = atoi(p_state.GetLastText().c_str()); GameInfoset infoset; if (p_treeData.m_chanceInfosetMap.IsDefined(infosetId)) { infoset = p_treeData.m_chanceInfosetMap.Lookup(infosetId); } p_state.GetNextToken(); if (p_state.GetCurrentToken() == TOKEN_TEXT) { // Information set data is specified List actions, probs; std::string label = p_state.GetLastText(); if (p_state.GetNextToken() != TOKEN_LBRACE) { throw InvalidFileException(); } p_state.GetNextToken(); do { if (p_state.GetCurrentToken() != TOKEN_TEXT) { throw InvalidFileException(); } actions.Append(p_state.GetLastText()); p_state.GetNextToken(); if (p_state.GetCurrentToken() == TOKEN_NUMBER) { probs.Append(p_state.GetLastText()); } else { throw InvalidFileException(); } p_state.GetNextToken(); } while (p_state.GetCurrentToken() != TOKEN_RBRACE); p_state.GetNextToken(); if (!infoset) { infoset = p_node->AppendMove(p_game->GetChance(), actions.Length()); p_treeData.m_chanceInfosetMap.Define(infosetId, infoset); infoset->SetLabel(label); for (int act = 1; act <= actions.Length(); act++) { infoset->GetAction(act)->SetLabel(actions[act]); infoset->SetActionProb(act, probs[act]); } } else { // TODO: Verify actions match up to previous specifications p_node->AppendMove(infoset); } } else if (infoset) { p_node->AppendMove(infoset); } else { // Referencing an undefined infoset is an error throw InvalidFileException(); } ParseOutcome(p_state, p_game, p_treeData, p_node); for (int i = 1; i <= p_node->NumChildren(); i++) { ParseNode(p_state, p_game, p_node->GetChild(i), p_treeData); } } void ParsePersonalNode(GameParserState &p_state, Game p_game, GameNode p_node, TreeData &p_treeData) { if (p_state.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(); } p_node->SetLabel(p_state.GetLastText()); if (p_state.GetNextToken() != TOKEN_NUMBER) { throw InvalidFileException(); } int playerId = atoi(p_state.GetLastText().c_str()); // This will throw an exception if the player ID is not valid GamePlayer player = p_game->GetPlayer(playerId); Map &infosetMap = p_treeData.m_infosetMap[playerId]; if (p_state.GetNextToken() != TOKEN_NUMBER) { throw InvalidFileException(); } int infosetId = atoi(p_state.GetLastText().c_str()); GameInfoset infoset; if (infosetMap.IsDefined(infosetId)) { infoset = infosetMap.Lookup(infosetId); } p_state.GetNextToken(); if (p_state.GetCurrentToken() == TOKEN_TEXT) { // Information set data is specified List actions; std::string label = p_state.GetLastText(); if (p_state.GetNextToken() != TOKEN_LBRACE) { throw InvalidFileException(); } p_state.GetNextToken(); do { if (p_state.GetCurrentToken() != TOKEN_TEXT) { throw InvalidFileException(); } actions.Append(p_state.GetLastText()); p_state.GetNextToken(); } while (p_state.GetCurrentToken() != TOKEN_RBRACE); p_state.GetNextToken(); if (!infoset) { infoset = p_node->AppendMove(player, actions.Length()); infosetMap.Define(infosetId, infoset); infoset->SetLabel(label); for (int act = 1; act <= actions.Length(); act++) { infoset->GetAction(act)->SetLabel(actions[act]); } } else { // TODO: Verify actions match up to previous specifications p_node->AppendMove(infoset); } } else if (infoset) { p_node->AppendMove(infoset); } else { // Referencing an undefined infoset is an error throw InvalidFileException(); } ParseOutcome(p_state, p_game, p_treeData, p_node); for (int i = 1; i <= p_node->NumChildren(); i++) { ParseNode(p_state, p_game, p_node->GetChild(i), p_treeData); } } void ParseTerminalNode(GameParserState &p_state, Game p_game, GameNode p_node, TreeData &p_treeData) { if (p_state.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(); } p_node->SetLabel(p_state.GetLastText()); p_state.GetNextToken(); ParseOutcome(p_state, p_game, p_treeData, p_node); } void ParseNode(GameParserState &p_state, Game p_game, GameNode p_node, TreeData &p_treeData) { if (p_state.GetLastText() == "c") { ParseChanceNode(p_state, p_game, p_node, p_treeData); } else if (p_state.GetLastText() == "p") { ParsePersonalNode(p_state, p_game, p_node, p_treeData); } else if (p_state.GetLastText() == "t") { ParseTerminalNode(p_state, p_game, p_node, p_treeData); } else { throw InvalidFileException(); } } void ParseEfg(GameParserState &p_state, Game p_game, TreeData &p_treeData) { if (p_state.GetNextToken() != TOKEN_NUMBER || p_state.GetLastText() != "2") { throw InvalidFileException(); } if (p_state.GetNextToken() != TOKEN_SYMBOL || (p_state.GetLastText() != "D" && p_state.GetLastText() != "R")) { throw InvalidFileException(); } if (p_state.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(); } p_game->SetTitle(p_state.GetLastText()); ReadPlayers(p_state, p_game, p_treeData); if (p_state.GetNextToken() == TOKEN_TEXT) { // Read optional comment p_game->SetComment(p_state.GetLastText()); p_state.GetNextToken(); } ParseNode(p_state, p_game, p_game->GetRoot(), p_treeData); } } // end of anonymous namespace namespace Gambit { //========================================================================= // ReadGame: Global visible function to read an .efg or .nfg file //========================================================================= Game ReadGame(std::istream &p_file) throw (InvalidFileException) { GameParserState parser(p_file); try { if (parser.GetNextToken() != TOKEN_SYMBOL) { throw InvalidFileException(); } if (parser.GetLastText() == "NFG") { TableFileGame data; ParseNfgHeader(parser, data); return BuildNfg(parser, data); } else if (parser.GetLastText() == "EFG") { TreeData treeData; Game game(new GameRep); ParseEfg(parser, game, treeData); game->Canonicalize(); return game; } else { throw InvalidFileException(); } } catch (...) { throw InvalidFileException(); } } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/game.cc0000644000076500007650000012731011441453421014404 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/game.cc // Implementation of extensive form game representation // // 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 #include #include "libgambit.h" namespace Gambit { //======================================================================== // class GameOutcomeRep //======================================================================== GameOutcomeRep::GameOutcomeRep(GameRep *p_game, int p_number) : m_game(p_game), m_number(p_number), m_payoffs(m_game->NumPlayers()) { } //======================================================================== // class GameActionRep //======================================================================== bool GameActionRep::Precedes(const GameNode &n) const { GameNode node = n; while (node != node->GetGame()->GetRoot()) { if (node->GetPriorAction() == this) { return true; } else { node = node->GetParent(); } } return false; } void GameActionRep::DeleteAction(void) { if (m_infoset->NumActions() == 1) throw UndefinedException(); int where; for (where = 1; where <= m_infoset->m_actions.Length() && m_infoset->m_actions[where] != this; where++); m_infoset->RemoveAction(where); for (int i = 1; i <= m_infoset->m_members.Length(); i++) { m_infoset->m_members[i]->children[where]->DeleteTree(); m_infoset->m_members[i]->children.Remove(where)->Invalidate(); } m_infoset->m_efg->ClearComputedValues(); } //======================================================================== // class GameInfosetRep //======================================================================== GameInfosetRep::GameInfosetRep(GameRep *p_efg, int p_number, GamePlayerRep *p_player, int p_actions) : m_efg(p_efg), m_number(p_number), m_player(p_player), m_actions(p_actions), flag(0) { while (p_actions) { m_actions[p_actions] = new GameActionRep(p_actions, "", this); p_actions--; } m_player->m_infosets.Append(this); if (p_player->IsChance()) { for (int act = 1; act <= m_actions.Length(); act++) { m_probs.Append(ToText(Rational(1, m_actions.Length()))); } } } GameInfosetRep::~GameInfosetRep() { for (int act = 1; act <= m_actions.Length(); m_actions[act++]->Invalidate()); } void GameInfosetRep::SetPlayer(GamePlayer p_player) { if (p_player->GetGame() != m_efg) throw MismatchException(); if (m_player->IsChance() || p_player->IsChance()) throw UndefinedException(); if (m_player == p_player) return; m_player->m_infosets.Remove(m_player->m_infosets.Find(this)); m_player = p_player; p_player->m_infosets.Append(this); m_efg->ClearComputedValues(); } bool GameInfosetRep::Precedes(GameNode p_node) const { while (p_node != p_node->GetGame()->GetRoot()) { if (p_node->GetInfoset() == this) { return true; } else { p_node = p_node->GetParent(); } } return false; } GameAction GameInfosetRep::InsertAction(GameAction p_action /* =0 */) { if (p_action && p_action->GetInfoset() != this) throw MismatchException(); int where = m_actions.Length() + 1; if (p_action) { for (where = 1; m_actions[where] != p_action; where++); } GameActionRep *action = new GameActionRep(where, "", this); m_actions.Insert(action, where); if (m_player->IsChance()) { m_probs.Insert(Number("0"), where); } for (int act = 1; act <= m_actions.Length(); act++) { m_actions[act]->m_number = act; } for (int i = 1; i <= m_members.Length(); i++) { m_members[i]->children.Insert(new GameNodeRep(m_efg, m_members[i]), where); } m_efg->ClearComputedValues(); return action; } void GameInfosetRep::RemoveAction(int which) { m_actions.Remove(which)->Invalidate(); for (; which <= m_actions.Length(); which++) m_actions[which]->m_number = which; if (m_player->IsChance()) { m_probs.Remove(which); } } void GameInfosetRep::SetActionProb(int act, const std::string &p_value) { m_probs[act] = p_value; m_efg->ClearComputedValues(); } void GameInfosetRep::RemoveMember(GameNodeRep *p_node) { m_members.Remove(m_members.Find(p_node)); if (m_members.Length() == 0) { m_player->m_infosets.Remove(m_player->m_infosets.Find(this)); for (int i = 1; i <= m_player->m_infosets.Length(); i++) { m_player->m_infosets[i]->m_number = i; } Invalidate(); } } void GameInfosetRep::Reveal(GamePlayer p_player) { for (int act = 1; act <= m_actions.Length(); act++) { GameActionRep *action = m_actions[act]; for (int iset = 1; iset <= p_player->m_infosets.Length(); iset++) { // make copy of members to iterate correctly // (since the information set may be changed in the process) Array members = p_player->m_infosets[iset]->m_members; // This information set holds all members of information set // which follow 'action'. GameInfoset newiset = 0; for (int m = 1; m <= members.Length(); m++) { if (action->Precedes(members[m])) { if (!newiset) { newiset = members[m]->LeaveInfoset(); } else { members[m]->SetInfoset(newiset); } } } } } m_efg->ClearComputedValues(); } //======================================================================== // class GameStrategyRep //======================================================================== void GameStrategyRep::DeleteStrategy(void) { if (m_player->GetGame()->IsTree()) throw UndefinedException(); if (m_player->NumStrategies() == 1) return; m_player->m_strategies.Remove(m_player->m_strategies.Find(this)); for (int st = 1; st <= m_player->m_strategies.Length(); st++) { m_player->m_strategies[st]->m_number = st; } //m_player->m_game->RebuildTable(); this->Invalidate(); } //======================================================================== // class GamePlayerRep //======================================================================== GamePlayerRep::GamePlayerRep(GameRep *p_game, int p_id, int p_strats) : m_game(p_game), m_number(p_id), m_strategies(p_strats) { for (int j = 1; j <= p_strats; j++) { m_strategies[j] = new GameStrategyRep(this); m_strategies[j]->m_number = j; } } GamePlayerRep::~GamePlayerRep() { for (int j = 1; j <= m_infosets.Length(); m_infosets[j++]->Invalidate()); for (int j = 1; j <= m_strategies.Length(); m_strategies[j++]->Invalidate()); } GameStrategy GamePlayerRep::NewStrategy(void) { if (m_game->IsTree()) throw UndefinedException(); GameStrategyRep *strategy = new GameStrategyRep(this); m_strategies.Append(strategy); strategy->m_number = m_strategies.Length(); strategy->m_offset = -1; // this flags this action as new m_game->RebuildTable(); return strategy; } void GamePlayerRep::MakeStrategy(void) { Array c(NumInfosets()); for (int i = 1; i <= NumInfosets(); i++) { if (GetInfoset(i)->flag == 1) c[i] = GetInfoset(i)->whichbranch; else c[i] = 0; } GameStrategyRep *strategy = new GameStrategyRep(this); m_strategies.Append(strategy); strategy->m_number = m_strategies.Length(); strategy->m_behav = c; strategy->m_label = ""; // We generate a default labeling -- probably should be changed in future if (strategy->m_behav.Length() > 0) { for (int iset = 1; iset <= strategy->m_behav.Length(); iset++) { if (strategy->m_behav[iset] > 0) { strategy->m_label += ToText(strategy->m_behav[iset]); } else { strategy->m_label += "*"; } } } else { strategy->m_label = "*"; } } void GamePlayerRep::MakeReducedStrats(GameNodeRep *n, GameNodeRep *nn) { int i; GameNodeRep *m, *mm; if (!n->GetParent()) n->ptr = 0; if (n->NumChildren() > 0) { if (n->infoset->m_player == this) { if (n->infoset->flag == 0) { // we haven't visited this infoset before n->infoset->flag = 1; for (i = 1; i <= n->NumChildren(); i++) { GameNodeRep *m = n->GetChild(i); n->whichbranch = m; n->infoset->whichbranch = i; MakeReducedStrats(m, nn); } n->infoset->flag = 0; } else { // we have visited this infoset, take same action MakeReducedStrats(n->children[n->infoset->whichbranch], nn); } } else { n->ptr = NULL; if (nn != NULL) n->ptr = nn->m_parent; n->whichbranch = n->children[1]; if (n->infoset) n->infoset->whichbranch = 0; MakeReducedStrats(n->children[1], n->children[1]); } } else if (nn) { for (; ; nn = nn->m_parent->ptr->whichbranch) { m = nn->GetNextSibling(); if (m || nn->m_parent->ptr == NULL) break; } if (m) { mm = m->m_parent->whichbranch; m->m_parent->whichbranch = m; MakeReducedStrats(m, m); m->m_parent->whichbranch = mm; } else { MakeStrategy(); } } else { MakeStrategy(); } } //======================================================================== // class GameNodeRep //======================================================================== GameNodeRep::GameNodeRep(GameRep *e, GameNodeRep *p) : number(0), m_efg(e), infoset(0), m_parent(p), outcome(0) { } GameNodeRep::~GameNodeRep() { for (int i = children.Length(); i; children[i--]->Invalidate()); } GameNode GameNodeRep::GetNextSibling(void) const { if (!m_parent) return 0; if (m_parent->children.Find(const_cast(this)) == m_parent->children.Length()) return 0; else return m_parent->children[m_parent->children.Find(const_cast(this)) + 1]; } GameNode GameNodeRep::GetPriorSibling(void) const { if (!m_parent) return 0; if (m_parent->children.Find(const_cast(this)) == 1) return 0; else return m_parent->children[m_parent->children.Find(const_cast(this)) - 1]; } GameAction GameNodeRep::GetPriorAction(void) const { if (!m_parent) { return 0; } GameInfosetRep *infoset = GetParent()->GetInfoset(); for (int i = 1; i <= infoset->NumActions(); i++) { if (this == GetParent()->GetChild(i)) { return infoset->GetAction(i); } } return 0; } void GameNodeRep::DeleteOutcome(GameOutcomeRep *outc) { if (outc == outcome) outcome = 0; for (int i = 1; i <= children.Length(); i++) children[i]->DeleteOutcome(outc); } void GameNodeRep::SetOutcome(const GameOutcome &p_outcome) { if (p_outcome != outcome) { outcome = p_outcome; m_efg->ClearComputedValues(); } } bool GameNodeRep::IsSuccessorOf(GameNode p_node) const { GameNode n = const_cast(this); while (n && n != p_node) n = n->m_parent; return (n == p_node); } bool GameNodeRep::IsSubgameRoot(void) const { // First take care of a couple easy cases if (children.Length() == 0 || infoset->NumMembers() > 1) return false; if (!m_parent) return true; // A node is a subgame root if and only if in every information set, // either all members succeed the node in the tree, // or all members do not succeed the node in the tree. for (int pl = 1; pl <= m_efg->NumPlayers(); pl++) { GamePlayerRep *player = m_efg->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfosetRep *infoset = player->GetInfoset(iset); bool precedes = infoset->GetMember(1)->IsSuccessorOf(const_cast(this)); for (int mem = 2; mem <= infoset->NumMembers(); mem++) { if (infoset->GetMember(mem)->IsSuccessorOf(const_cast(this)) != precedes) { return false; } } } } return true; } void GameNodeRep::DeleteParent(void) { if (!m_parent) return; GameNodeRep *oldParent = m_parent; oldParent->children.Remove(oldParent->children.Find(this)); oldParent->DeleteTree(); m_parent = oldParent->m_parent; if (m_parent) { m_parent->children[m_parent->children.Find(oldParent)] = this; } else { m_efg->m_root = this; } oldParent->Invalidate(); m_efg->ClearComputedValues(); } void GameNodeRep::DeleteTree(void) { for (int i = 1; i <= children.Length(); i++) { children[i]->DeleteTree(); children[i]->Invalidate(); } children = Array(); if (infoset) { infoset->RemoveMember(this); infoset = 0; } outcome = 0; m_label = ""; m_efg->ClearComputedValues(); } void GameNodeRep::CopySubtree(GameNodeRep *src, GameNodeRep *stop) { if (src == stop) { outcome = src->outcome; return; } if (src->children.Length()) { AppendMove(src->infoset); for (int i = 1; i <= src->children.Length(); i++) { children[i]->CopySubtree(src->children[i], stop); } } m_label = src->m_label; outcome = src->outcome; } void GameNodeRep::CopyTree(GameNode p_src) { if (p_src->GetGame() != m_efg) throw MismatchException(); if (p_src == this || children.Length() > 0) return; if (p_src->children.Length()) { AppendMove(p_src->infoset); for (int i = 1; i <= p_src->children.Length(); i++) { children[i]->CopySubtree(p_src->children[i], this); } m_efg->ClearComputedValues(); } } void GameNodeRep::MoveTree(GameNode p_src) { if (p_src->GetGame() != m_efg) throw MismatchException(); if (p_src == this || children.Length() > 0 || IsSuccessorOf(p_src)) { return; } if (p_src->m_parent == m_parent) { int srcChild = p_src->m_parent->children.Find(p_src); int destChild = p_src->m_parent->children.Find(this); p_src->m_parent->children[srcChild] = this; p_src->m_parent->children[destChild] = p_src; } else { GameNodeRep *parent = p_src->m_parent; parent->children[parent->children.Find(p_src)] = this; m_parent->children[m_parent->children.Find(this)] = p_src; p_src->m_parent = m_parent; m_parent = parent; } m_label = ""; outcome = 0; m_efg->ClearComputedValues(); } void GameNodeRep::SetInfoset(GameInfoset p_infoset) { if (p_infoset->GetGame() != m_efg) throw MismatchException(); if (!infoset || infoset == p_infoset) return; if (p_infoset->m_actions.Length() != children.Length()) throw MismatchException(); infoset->RemoveMember(this); p_infoset->AddMember(this); infoset = p_infoset; m_efg->ClearComputedValues(); } GameInfoset GameNodeRep::LeaveInfoset(void) { if (!infoset) return 0; GameInfosetRep *oldInfoset = infoset; if (oldInfoset->m_members.Length() == 1) return oldInfoset; GamePlayerRep *player = oldInfoset->m_player; oldInfoset->RemoveMember(this); infoset = new GameInfosetRep(m_efg, player->m_infosets.Length() + 1, player, children.Length()); infoset->AddMember(this); for (int i = 1; i <= oldInfoset->m_actions.Length(); i++) { infoset->m_actions[i]->SetLabel(oldInfoset->m_actions[i]->GetLabel()); } m_efg->ClearComputedValues(); return infoset; } GameInfoset GameNodeRep::AppendMove(GamePlayer p_player, int p_actions) { if (p_actions <= 0 || children.Length() > 0) throw UndefinedException(); if (p_player->GetGame() != m_efg) throw MismatchException(); return AppendMove(new GameInfosetRep(m_efg, p_player->m_infosets.Length() + 1, p_player, p_actions)); } GameInfoset GameNodeRep::AppendMove(GameInfoset p_infoset) { if (children.Length() > 0) throw UndefinedException(); if (p_infoset->GetGame() != m_efg) throw MismatchException(); infoset = p_infoset; infoset->AddMember(this); for (int i = 1; i <= p_infoset->NumActions(); i++) { children.Append(new GameNodeRep(m_efg, this)); } m_efg->ClearComputedValues(); return infoset; } GameInfoset GameNodeRep::InsertMove(GamePlayer p_player, int p_actions) { if (p_actions <= 0) throw UndefinedException(); if (p_player->GetGame() != m_efg) throw MismatchException(); return InsertMove(new GameInfosetRep(m_efg, p_player->m_infosets.Length() + 1, p_player, p_actions)); } GameInfoset GameNodeRep::InsertMove(GameInfoset p_infoset) { if (p_infoset->GetGame() != m_efg) throw MismatchException(); GameNodeRep *newNode = new GameNodeRep(m_efg, m_parent); newNode->infoset = p_infoset; p_infoset->AddMember(newNode); if (m_parent) { m_parent->children[m_parent->children.Find(this)] = newNode; } else { m_efg->m_root = newNode; } newNode->children.Append(this); m_parent = newNode; for (int i = 1; i < p_infoset->NumActions(); i++) { newNode->children.Append(new GameNodeRep(m_efg, newNode)); } m_efg->ClearComputedValues(); return p_infoset; } //======================================================================== // class PureStrategyProfile //======================================================================== //------------------------------------------------------------------------ // PureStrategyProfile: Lifecycle //------------------------------------------------------------------------ PureStrategyProfile::PureStrategyProfile(const Game &p_nfg) : m_index(1L), m_nfg(p_nfg), m_profile(m_nfg->NumPlayers()) { for (int pl = 1; pl <= m_nfg->NumPlayers(); pl++) { m_profile[pl] = m_nfg->GetPlayer(pl)->GetStrategy(1); m_index += m_profile[pl]->m_offset; } } //------------------------------------------------------------------------ // PureStrategyProfile: Data access and manipulation //------------------------------------------------------------------------ void PureStrategyProfile::SetStrategy(const GameStrategy &s) { m_index += s->m_offset - m_profile[s->GetPlayer()->GetNumber()]->m_offset; m_profile[s->GetPlayer()->GetNumber()] = s; } GameOutcome PureStrategyProfile::GetOutcome(void) const { if (m_nfg->IsTree()) { throw UndefinedException(); } else { return m_nfg->m_results[m_index]; } } void PureStrategyProfile::SetOutcome(GameOutcome p_outcome) { if (m_nfg->IsTree()) { throw UndefinedException(); } else { m_nfg->m_results[m_index] = p_outcome; } } template T PureStrategyProfile::GetPayoff(int pl) const { if (m_nfg->IsTree()) { PureBehavProfile behav(m_nfg); for (int i = 1; i <= m_nfg->NumPlayers(); i++) { GamePlayer player = m_nfg->GetPlayer(i); for (int iset = 1; iset <= player->NumInfosets(); iset++) { int act = m_profile[i]->m_behav[iset]; if (act) { behav.SetAction(player->GetInfoset(iset)->GetAction(act)); } } } return behav.GetPayoff(pl); } else { GameOutcomeRep *outcome = m_nfg->m_results[m_index]; if (outcome) { return outcome->GetPayoff(pl); } else { return (T) 0; } } } // Explicit instantiations template double PureStrategyProfile::GetPayoff(int pl) const; template Rational PureStrategyProfile::GetPayoff(int pl) const; template<> std::string PureStrategyProfile::GetPayoff(int pl) const { if (m_nfg->IsTree()) { return ToText(GetPayoff(pl)); } else { GameOutcomeRep *outcome = m_nfg->m_results[m_index]; if (outcome) { return outcome->GetPayoff(pl); } else { return "0"; } } } template T PureStrategyProfile::GetStrategyValue(const GameStrategy &p_strategy) const { if (m_nfg->IsTree()) { PureStrategyProfile copy(*this); copy.SetStrategy(p_strategy); return copy.GetPayoff(p_strategy->GetPlayer()->GetNumber()); } else { int player = p_strategy->GetPlayer()->GetNumber(); GameOutcomeRep *outcome = m_nfg->m_results[m_index - m_profile[player]->m_offset + p_strategy->m_offset]; if (outcome) { return outcome->GetPayoff(player); } else { return 0; } } } // Explicit instantiations template double PureStrategyProfile::GetStrategyValue(const GameStrategy &) const; template Rational PureStrategyProfile::GetStrategyValue(const GameStrategy &) const; //======================================================================== // class PureBehavProfile //======================================================================== //------------------------------------------------------------------------ // PureBehavProfile: Lifecycle //------------------------------------------------------------------------ PureBehavProfile::PureBehavProfile(Game p_efg) : m_efg(p_efg), m_profile(m_efg->NumPlayers()) { for (int pl = 1; pl <= m_efg->NumPlayers(); pl++) { GamePlayerRep *player = m_efg->GetPlayer(pl); m_profile[pl] = Array(player->NumInfosets()); for (int iset = 1; iset <= player->NumInfosets(); iset++) { m_profile[pl][iset] = player->GetInfoset(iset)->GetAction(1); } } } //------------------------------------------------------------------------ // PureBehavProfile: Data access and manipulation //------------------------------------------------------------------------ GameAction PureBehavProfile::GetAction(const GameInfoset &infoset) const { return m_profile[infoset->GetPlayer()->GetNumber()][infoset->GetNumber()]; } void PureBehavProfile::SetAction(const GameAction &action) { m_profile[action->GetInfoset()->GetPlayer()->GetNumber()] [action->GetInfoset()->GetNumber()] = action; } template T PureBehavProfile::GetNodeValue(const GameNode &p_node, int pl) const { T payoff(0); if (p_node->outcome) { payoff += p_node->outcome->GetPayoff(pl); } if (!p_node->IsTerminal()) { if (p_node->GetInfoset()->IsChanceInfoset()) { for (int i = 1; i <= p_node->NumChildren(); i++) { GameInfosetRep *infoset = p_node->GetInfoset(); payoff += (infoset->GetActionProb(i) * GetNodeValue(p_node->children[i], pl)); } } else { int player = p_node->GetPlayer()->GetNumber(); int iset = p_node->GetInfoset()->GetNumber(); payoff += GetNodeValue(p_node->children[m_profile[player][iset]->GetNumber()], pl); } } return payoff; } // Explicit instantiations template double PureBehavProfile::GetNodeValue(const GameNode &, int pl) const; template Rational PureBehavProfile::GetNodeValue(const GameNode &, int pl) const; template T PureBehavProfile::GetActionValue(const GameAction &p_action) const { PureBehavProfile copy(*this); copy.SetAction(p_action); return copy.GetPayoff(p_action->GetInfoset()->GetPlayer()->GetNumber()); } // Explicit instantiations template double PureBehavProfile::GetActionValue(const GameAction &) const; template Rational PureBehavProfile::GetActionValue(const GameAction &) const; //======================================================================== // class GameRep //======================================================================== //------------------------------------------------------------------------ // GameRep: Lifecycle //------------------------------------------------------------------------ GameRep::GameRep(void) : m_computedValues(false), m_chance(new GamePlayerRep(this, 0)), m_root(new GameNodeRep(this, 0)) { } /// This convenience function computes the Cartesian product of the /// elements in dim. static int Product(const Array &dim) { int accum = 1; for (int i = 1; i <= dim.Length(); accum *= dim[i++]); return accum; } GameRep::GameRep(const Array &dim) : m_computedValues(true), m_chance(0), m_root(0) { m_results = Array(Product(dim)); for (int pl = 1; pl <= dim.Length(); pl++) { m_players.Append(new GamePlayerRep(this, pl, dim[pl])); m_players[pl]->m_label = ToText(pl); for (int st = 1; st <= m_players[pl]->NumStrategies(); st++) { m_players[pl]->m_strategies[st]->m_label = ToText(st); } } IndexStrategies(); for (int cont = 1; cont <= m_results.Length(); m_results[cont++] = 0); } GameRep::~GameRep() { if (m_root) m_root->Invalidate(); if (m_chance) m_chance->Invalidate(); for (int pl = 1; pl <= m_players.Length(); m_players[pl++]->Invalidate()); for (int outc = 1; outc <= m_outcomes.Length(); m_outcomes[outc++]->Invalidate()); } /// /// Creates a copy of the game as a new, separate GameRep object. /// /// NOTE: For now, this takes the "easy" way of writing the game out /// in text representation, and reading it back in. For most applications, /// this would be adequate performance. However, it might be nice someday /// to directly do the copying without going through the text translation. /// Game GameRep::Copy(void) const { std::ostringstream os; if (m_root) { WriteEfgFile(os); } else { WriteNfgFile(os); } std::istringstream is(os.str()); return ReadGame(is); } //------------------------------------------------------------------------ // GameRep: General data access //------------------------------------------------------------------------ namespace { class NotZeroSumException : public Exception { public: virtual ~NotZeroSumException() { } std::string GetDescription(void) const { return "Game is not constant sum"; } }; Rational SubtreeSum(const GameNode &p_node) { Rational sum(0); if (p_node->NumChildren() > 0) { sum = SubtreeSum(p_node->GetChild(1)); for (int i = 2; i <= p_node->NumChildren(); i++) { if (SubtreeSum(p_node->GetChild(i)) != sum) { throw NotZeroSumException(); } } } if (p_node->GetOutcome()) { for (int pl = 1; pl <= p_node->GetGame()->NumPlayers(); pl++) { sum += p_node->GetOutcome()->GetPayoff(pl); } } return sum; } } bool GameRep::IsConstSum(void) const { if (m_root) { try { SubtreeSum(m_root); return true; } catch (NotZeroSumException) { return false; } } else { PureStrategyProfile profile(const_cast(this)); Rational sum(0); for (int pl = 1; pl <= m_players.Length(); pl++) { sum += profile.GetPayoff(pl); } for (StrategyIterator iter(StrategySupport(const_cast(this))); !iter.AtEnd(); iter++) { Rational newsum(0); for (int pl = 1; pl <= m_players.Length(); pl++) { newsum += iter->GetPayoff(pl); } if (newsum != sum) { return false; } } return true; } } Rational GameRep::GetMinPayoff(int player) const { int index, p, p1, p2; if (m_outcomes.Length() == 0) return Rational(0); if (player) { p1 = p2 = player; } else { p1 = 1; p2 = NumPlayers(); } Rational minpay = m_outcomes[1]->GetPayoff(p1); for (index = 1; index <= m_outcomes.Length(); index++) { for (p = p1; p <= p2; p++) { if (m_outcomes[index]->GetPayoff(p) < minpay) { minpay = m_outcomes[index]->GetPayoff(p); } } } return minpay; } Rational GameRep::GetMaxPayoff(int player) const { int index, p, p1, p2; if (m_outcomes.Length() == 0) return Rational(0); if (player) { p1 = p2 = player; } else { p1 = 1; p2 = NumPlayers(); } Rational maxpay = m_outcomes[1]->GetPayoff(p1); for (index = 1; index <= m_outcomes.Length(); index++) { for (p = p1; p <= p2; p++) if (m_outcomes[index]->GetPayoff(p) > maxpay) maxpay = m_outcomes[index]->GetPayoff(p); } return maxpay; } bool GameRep::IsPerfectRecall(GameInfoset &s1, GameInfoset &s2) const { if (!IsTree()) return true; for (int pl = 1; pl <= m_players.Length(); pl++) { GamePlayerRep *player = m_players[pl]; for (int i = 1; i <= player->NumInfosets(); i++) { GameInfosetRep *iset1 = player->GetInfoset(i); for (int j = 1; j <= player->NumInfosets(); j++) { GameInfosetRep *iset2 = player->GetInfoset(j); bool precedes = false; int action = 0; for (int m = 1; m <= iset2->NumMembers(); m++) { int n; for (n = 1; n <= iset1->NumMembers(); n++) { if (iset2->GetMember(m)->IsSuccessorOf(iset1->GetMember(n)) && iset1->GetMember(n) != iset2->GetMember(m)) { precedes = true; for (int act = 1; act <= iset1->NumActions(); act++) { if (iset2->GetMember(m)->IsSuccessorOf(iset1->GetMember(n)->GetChild(act))) { if (action != 0 && action != act) { s1 = iset1; s2 = iset2; return false; } action = act; } } break; } } if (i == j && precedes) { s1 = iset1; s2 = iset2; return false; } if (n > iset1->NumMembers() && precedes) { s1 = iset1; s2 = iset2; return false; } } } } } return true; } //------------------------------------------------------------------------ // GameRep: Managing the representation //------------------------------------------------------------------------ void GameRep::NumberNodes(GameNodeRep *n, int &index) { n->number = index++; for (int child = 1; child <= n->children.Length(); NumberNodes(n->children[child++], index)); } void GameRep::Canonicalize(void) { if (!m_root) return; int nodeindex = 1; NumberNodes(m_root, nodeindex); for (int pl = 0; pl <= m_players.Length(); pl++) { GamePlayerRep *player = (pl) ? m_players[pl] : m_chance; // Sort nodes within information sets according to ID. // Coded using a bubble sort for simplicity; large games might // find a quicksort worthwhile. for (int iset = 1; iset <= player->m_infosets.Length(); iset++) { GameInfosetRep *infoset = player->m_infosets[iset]; for (int i = 1; i < infoset->m_members.Length(); i++) { for (int j = 1; j < infoset->m_members.Length() - i; j++) { if (infoset->m_members[j+1]->number < infoset->m_members[j]->number) { GameNodeRep *tmp = infoset->m_members[j]; infoset->m_members[j] = infoset->m_members[j+1]; infoset->m_members[j+1] = tmp; } } } } // Sort information sets by the smallest ID among their members // Coded using a bubble sort for simplicity; large games might // find a quicksort worthwhile. for (int i = 1; i < player->m_infosets.Length(); i++) { for (int j = 1; j < player->m_infosets.Length() - i; j++) { int a = ((player->m_infosets[j+1]->m_members.Length()) ? player->m_infosets[j+1]->m_members[1]->number : 0); int b = ((player->m_infosets[j]->m_members.Length()) ? player->m_infosets[j]->m_members[1]->number : 0); if (a < b || b == 0) { GameInfosetRep *tmp = player->m_infosets[j]; player->m_infosets[j] = player->m_infosets[j+1]; player->m_infosets[j+1] = tmp; } } } // Reassign information set IDs for (int iset = 1; iset <= player->m_infosets.Length(); iset++) { player->m_infosets[iset]->m_number = iset; } } } void GameRep::ClearComputedValues(void) const { if (!m_root) return; for (int pl = 1; pl <= m_players.Length(); pl++) { while (m_players[pl]->m_strategies.Length() > 0) { m_players[pl]->m_strategies.Remove(1)->Invalidate(); } } m_computedValues = false; } void GameRep::BuildComputedValues(void) { if (m_computedValues) return; Canonicalize(); if (!IsTree()) return; for (int pl = 1; pl <= m_players.Length(); pl++) { m_players[pl]->MakeReducedStrats(m_root, 0); } for (int pl = 1, id = 1; pl <= m_players.Length(); pl++) { for (int st = 1; st <= m_players[pl]->m_strategies.Length(); m_players[pl]->m_strategies[st++]->m_id = id++); } m_computedValues = true; } //------------------------------------------------------------------------ // GameRep: Writing data files //------------------------------------------------------------------------ static std::string EscapeQuotes(const std::string &s) { std::string ret; for (unsigned int i = 0; i < s.length(); i++) { if (s[i] == '"') ret += '\\'; ret += s[i]; } return ret; } static void PrintActions(std::ostream &p_stream, GameInfosetRep *p_infoset) { p_stream << "{ "; for (int act = 1; act <= p_infoset->NumActions(); act++) { p_stream << '"' << EscapeQuotes(p_infoset->GetAction(act)->GetLabel()) << "\" "; if (p_infoset->IsChanceInfoset()) { p_stream << p_infoset->GetActionProb(act) << ' '; } } p_stream << "}"; } static void WriteEfgFile(std::ostream &f, GameNodeRep *n) { if (n->NumChildren() == 0) { f << "t \"" << EscapeQuotes(n->GetLabel()) << "\" "; if (n->GetOutcome()) { f << n->GetOutcome()->GetNumber() << " \"" << EscapeQuotes(n->GetOutcome()->GetLabel()) << "\" "; f << "{ "; for (int pl = 1; pl <= n->GetGame()->NumPlayers(); pl++) { f << n->GetOutcome()->GetPayoff(pl); if (pl < n->GetGame()->NumPlayers()) { f << ", "; } else { f << " }\n"; } } } else { f << "0\n"; } return; } if (n->GetInfoset()->IsChanceInfoset()) { f << "c \""; } else { f << "p \""; } f << EscapeQuotes(n->GetLabel()) << "\" "; if (!n->GetInfoset()->IsChanceInfoset()) { f << n->GetInfoset()->GetPlayer()->GetNumber() << ' '; } f << n->GetInfoset()->GetNumber() << " \"" << EscapeQuotes(n->GetInfoset()->GetLabel()) << "\" "; PrintActions(f, n->GetInfoset()); f << " "; if (n->GetOutcome()) { f << n->GetOutcome()->GetNumber() << " \"" << EscapeQuotes(n->GetOutcome()->GetLabel()) << "\" "; f << "{ "; for (int pl = 1; pl <= n->GetGame()->NumPlayers(); pl++) { f << n->GetOutcome()->GetPayoff(pl); if (pl < n->GetGame()->NumPlayers()) f << ", "; else f << " }\n"; } } else f << "0\n"; for (int i = 1; i <= n->NumChildren(); WriteEfgFile(f, n->GetChild(i++))); } void GameRep::WriteEfgFile(std::ostream &p_file) const { if (!IsTree()) throw UndefinedException(); p_file << "EFG 2 R"; p_file << " \"" << EscapeQuotes(GetTitle()) << "\" { "; for (int i = 1; i <= m_players.Length(); i++) p_file << '"' << EscapeQuotes(m_players[i]->m_label) << "\" "; p_file << "}\n"; p_file << "\"" << EscapeQuotes(GetComment()) << "\"\n\n"; Gambit::WriteEfgFile(p_file, m_root); } void GameRep::WriteEfgFile(std::ostream &p_file, const GameNode &p_root) const { if (!IsTree()) throw UndefinedException(); p_file << "EFG 2 R"; p_file << " \"" << EscapeQuotes(GetTitle()) << "\" { "; for (int i = 1; i <= m_players.Length(); i++) p_file << '"' << EscapeQuotes(m_players[i]->m_label) << "\" "; p_file << "}\n"; p_file << "\"" << EscapeQuotes(GetComment()) << "\"\n\n"; Gambit::WriteEfgFile(p_file, p_root); } void GameRep::WriteNfgFile(std::ostream &p_file) const { if (IsTree()) { // FIXME: Building computed values is logically const. const_cast(this)->BuildComputedValues(); } p_file << "NFG 1 R"; p_file << " \"" << EscapeQuotes(GetTitle()) << "\" { "; for (int i = 1; i <= NumPlayers(); i++) p_file << '"' << EscapeQuotes(GetPlayer(i)->GetLabel()) << "\" "; p_file << "}\n\n{ "; for (int i = 1; i <= NumPlayers(); i++) { GamePlayerRep *player = GetPlayer(i); p_file << "{ "; for (int j = 1; j <= player->NumStrategies(); j++) p_file << '"' << EscapeQuotes(player->GetStrategy(j)->GetLabel()) << "\" "; p_file << "}\n"; } p_file << "}\n"; p_file << "\"" << EscapeQuotes(m_comment) << "\"\n\n"; if (IsTree()) { // For trees, we write the payoff version, since there need not be // a one-to-one correspondence between outcomes and entries, when there // are chance moves. StrategyIterator iter(Game(const_cast(this))); for (; !iter.AtEnd(); iter++) { for (int pl = 1; pl <= NumPlayers(); pl++) { p_file << iter->GetPayoff(pl) << " "; } p_file << "\n"; } } else { int ncont = 1; for (int i = 1; i <= NumPlayers(); i++) { ncont *= m_players[i]->m_strategies.Length(); } p_file << "{\n"; for (int outc = 1; outc <= m_outcomes.Length(); outc++) { p_file << "{ \"" << EscapeQuotes(m_outcomes[outc]->m_label) << "\" "; for (int pl = 1; pl <= m_players.Length(); pl++) { p_file << (const std::string &) m_outcomes[outc]->m_payoffs[pl]; if (pl < m_players.Length()) { p_file << ", "; } else { p_file << " }\n"; } } } p_file << "}\n"; for (int cont = 1; cont <= ncont; cont++) { if (m_results[cont] != 0) { p_file << m_results[cont]->m_number << ' '; } else { p_file << "0 "; } } } p_file << '\n'; } //------------------------------------------------------------------------ // GameRep: Dimensions of the game //------------------------------------------------------------------------ PVector GameRep::NumActions(void) const { if (!IsTree()) throw UndefinedException(); Array foo(m_players.Length()); int i; for (i = 1; i <= m_players.Length(); i++) foo[i] = m_players[i]->m_infosets.Length(); PVector bar(foo); for (i = 1; i <= m_players.Length(); i++) { for (int j = 1; j <= m_players[i]->m_infosets.Length(); j++) { bar(i, j) = m_players[i]->m_infosets[j]->NumActions(); } } return bar; } PVector GameRep::NumMembers(void) const { if (!IsTree()) throw UndefinedException(); Array foo(m_players.Length()); for (int i = 1; i <= m_players.Length(); i++) { foo[i] = m_players[i]->NumInfosets(); } PVector bar(foo); for (int i = 1; i <= m_players.Length(); i++) { for (int j = 1; j <= m_players[i]->NumInfosets(); j++) { bar(i, j) = m_players[i]->m_infosets[j]->NumMembers(); } } return bar; } Array GameRep::NumStrategies(void) const { Array dim(m_players.Length()); for (int pl = 1; pl <= m_players.Length(); pl++) { dim[pl] = m_players[pl]->m_strategies.Length(); } return dim; } GameStrategy GameRep::GetStrategy(int p_index) const { for (int pl = 1, i = 1; pl <= m_players.Length(); pl++) { for (int st = 1; st <= m_players[pl]->m_strategies.Length(); st++, i++) { if (p_index == i) { return m_players[pl]->m_strategies[st]; } } } throw IndexException(); } int GameRep::BehavProfileLength(void) const { if (!IsTree()) throw UndefinedException(); int sum = 0; for (int i = 1; i <= m_players.Length(); i++) for (int j = 1; j <= m_players[i]->m_infosets.Length(); j++) sum += m_players[i]->m_infosets[j]->m_actions.Length(); return sum; } int GameRep::MixedProfileLength(void) const { int strats = 0; for (int i = 1; i <= m_players.Length(); strats += m_players[i++]->m_strategies.Length()); return strats; } //------------------------------------------------------------------------ // GameRep: Players //------------------------------------------------------------------------ GamePlayer GameRep::NewPlayer(void) { if (m_root) { GamePlayerRep *player = new GamePlayerRep(this, m_players.Length() + 1); m_players.Append(player); for (int outc = 1; outc <= m_outcomes.Last(); outc++) { m_outcomes[outc]->m_payoffs.Append(Number()); } ClearComputedValues(); return player; } else { GamePlayerRep *player = new GamePlayerRep(this, m_players.Length() + 1, 1); m_players.Append(player); for (int outc = 1; outc <= m_outcomes.Length(); outc++) { m_outcomes[outc]->m_payoffs.Append(Number()); } return player; } } //------------------------------------------------------------------------ // GameRep: Information sets //------------------------------------------------------------------------ GameInfoset GameRep::GetInfoset(int p_index) const { if (!IsTree()) throw UndefinedException(); int index = 1; for (int pl = 1; pl <= m_players.Length(); pl++) { GamePlayerRep *player = m_players[pl]; for (int iset = 1; iset <= player->NumInfosets(); iset++) { if (index++ == p_index) { return player->GetInfoset(iset); } } } throw IndexException(); } Array GameRep::NumInfosets(void) const { if (!IsTree()) throw UndefinedException(); Array foo(m_players.Length()); for (int i = 1; i <= foo.Length(); i++) { foo[i] = m_players[i]->NumInfosets(); } return foo; } GameAction GameRep::GetAction(int p_index) const { int index = 1; for (int pl = 1; pl <= m_players.Length(); pl++) { GamePlayerRep *player = m_players[pl]; for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfosetRep *infoset = player->GetInfoset(iset); for (int act = 1; act <= infoset->NumActions(); act++) { if (index++ == p_index) { return infoset->GetAction(act); } } } } throw IndexException(); } //------------------------------------------------------------------------ // GameRep: Outcomes //------------------------------------------------------------------------ GameOutcome GameRep::NewOutcome(void) { m_outcomes.Append(new GameOutcomeRep(this, m_outcomes.Length() + 1)); return m_outcomes[m_outcomes.Last()]; } void GameRep::DeleteOutcome(const GameOutcome &p_outcome) { if (m_root) { m_root->DeleteOutcome(p_outcome); } else { for (int i = 1; i <= m_results.Length(); i++) { if (m_results[i] == p_outcome) { m_results[i] = 0; } } } m_outcomes.Remove(m_outcomes.Find(p_outcome))->Invalidate(); for (int outc = 1; outc <= m_outcomes.Length(); outc++) { m_outcomes[outc]->m_number = outc; } ClearComputedValues(); } //------------------------------------------------------------------------ // GameRep: Nodes //------------------------------------------------------------------------ static int CountNodes(GameNodeRep *p_node) { int num = 1; for (int i = 1; i <= p_node->NumChildren(); num += CountNodes(p_node->GetChild(i++))); return num; } int GameRep::NumNodes(void) const { return CountNodes(m_root); } //------------------------------------------------------------------------ // GameRep: Private auxiliary functions //------------------------------------------------------------------------ void GameRep::IndexStrategies(void) { long offset = 1L; for (int pl = 1; pl <= m_players.Length(); pl++) { for (GameStrategyIterator strategy(m_players[pl]->m_strategies); !strategy.AtEnd(); strategy++) { strategy->m_number = strategy.GetIndex(); strategy->m_offset = (strategy.GetIndex() - 1) * offset; } offset *= m_players[pl]->NumStrategies(); } for (int pl = 1, id = 1; pl <= m_players.Length(); pl++) { for (int st = 1; st <= m_players[pl]->m_strategies.Length(); m_players[pl]->m_strategies[st++]->m_id = id++); } } /// This rebuilds a new table of outcomes after the game has been /// redimensioned (change in the number of strategies). Strategies /// numbered -1 are identified as the new strategies. void GameRep::RebuildTable(void) { long size = 1L; Array offsets(m_players.Length()); for (int pl = 1; pl <= m_players.Length(); pl++) { offsets[pl] = size; size *= m_players[pl]->NumStrategies(); } Array newResults(size); for (int i = 1; i <= newResults.Length(); newResults[i++] = 0); for (StrategyIterator iter(StrategySupport(const_cast(this))); !iter.AtEnd(); iter++) { long newindex = 1L; for (int pl = 1; pl <= m_players.Length(); pl++) { if (iter.m_profile.GetStrategy(pl)->m_offset < 0) { // This is a contingency involving a new strategy... skip newindex = -1L; break; } else { newindex += (iter.m_profile.GetStrategy(pl)->m_number - 1) * offsets[pl]; } } if (newindex >= 1) { newResults[newindex] = m_results[iter.m_profile.m_index]; } } m_results = newResults; IndexStrategies(); } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/game.h0000644000076500007650000006435011441446351014256 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/game.h // Declaration of base class for representing games // // 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 LIBGAMBIT_GAME_H #define LIBGAMBIT_GAME_H #include "dvector.h" #include "number.h" namespace Gambit { /// This is a base class for all game-related objects. Primary among /// its responsibility is maintaining a reference count. Calling code /// which maintains pointers to objects representing parts of a game /// (e.g., nodes) which may be deleted should increment the reference /// count for that object. The library guarantees that any object /// with a positive reference count will not have its memory deleted, /// but will instead be marked as deleted. Calling code should always /// be careful to check the deleted status of the object before any /// operations on it. class GameObject { protected: int m_refCount; bool m_valid; public: /// @name Lifecycle //@{ /// Constructor; initializes reference count GameObject(void) : m_refCount(0), m_valid(true) { } //@} /// @name Validation //@{ /// Is the object still valid? bool IsValid(void) const { return m_valid; } /// Invalidate the object; delete if not referenced elsewhere void Invalidate(void) { if (!m_refCount) delete this; else m_valid = false; } //@} /// @name Reference counting //@{ /// Increment the reference count void IncRef(void) { m_refCount++; } /// Decrement the reference count; delete if reference count is zero. void DecRef(void) { if (!--m_refCount && !m_valid) delete this; } /// Returns the reference count int RefCount(void) const { return m_refCount; } //@} }; /// An exception thrown when attempting to dereference a null pointer class NullException : public Exception { public: virtual ~NullException() { } std::string GetDescription(void) const { return "Dereferencing null pointer"; } }; // // This is a handle class that is used by all calling code to refer to // member objects of games. It takes care of all the reference-counting // considerations. // template class GameObjectPtr { private: T *rep; public: GameObjectPtr(T *r = 0) : rep(r) { if (rep) rep->IncRef(); } GameObjectPtr(const GameObjectPtr &r) : rep(r.rep) { if (rep) rep->IncRef(); } ~GameObjectPtr() { if (rep) rep->DecRef(); } GameObjectPtr &operator=(const GameObjectPtr &r) { if (&r != this) { if (rep) rep->DecRef(); rep = r.rep; if (rep) rep->IncRef(); } return *this; } T *operator->(void) const { if (!rep || !rep->IsValid()) throw NullException(); return rep; } bool operator==(const GameObjectPtr &r) const { return (rep == r.rep); } bool operator==(T *r) const { return (rep == r); } bool operator!=(const GameObjectPtr &r) const { return (rep != r.rep); } bool operator!=(T *r) const { return (rep != r); } operator T *(void) const { return rep; } bool operator!(void) const { return !rep; } }; /// A constant forward iterator on an array of GameObjects template class GameObjectIterator { private: const Array &m_array; int m_index; public: /// @name Lifecycle //@{ /// Constructor GameObjectIterator(const Array &p_array) : m_array(p_array), m_index(m_array.First()) { } //@} /// @name Iteration and data access //@{ /// Advance to the next element (prefix version) void operator++(void) { m_index++; } /// Advance to the next element (postfix version) void operator++(int) { m_index++; } /// Has iterator gone past the end? bool AtEnd(void) const { return m_index > m_array.Last(); } /// Get the current index into the array int GetIndex(void) const { return m_index; } /// Get the current element ///T operator*(void) const { return m_array[m_index]; } /// Get the current element T operator->(void) const { return m_array[m_index]; } /// Get the current element operator T(void) const { return m_array[m_index]; } //@} }; // // Forward declarations of classes defined in this file. // class GameActionRep; typedef GameObjectPtr GameAction; typedef GameObjectIterator GameActionIterator; class GameInfosetRep; typedef GameObjectPtr GameInfoset; typedef GameObjectIterator GameInfosetIterator; class GameStrategyRep; typedef GameObjectPtr GameStrategy; typedef GameObjectIterator GameStrategyIterator; class GamePlayerRep; typedef GameObjectPtr GamePlayer; typedef GameObjectIterator GamePlayerIterator; class GameNodeRep; typedef GameObjectPtr GameNode; class GameRep; typedef GameObjectPtr Game; // // Forward declarations of classes defined elsewhere. // template class MixedStrategyProfile; template class MixedBehavProfile; //======================================================================= // Exceptions thrown from game representation classes //======================================================================= /// Exception thrown when an operation that is undefined is attempted class UndefinedException : public Exception { public: virtual ~UndefinedException() { } std::string GetDescription(void) const { return "Undefined operation on game"; } }; /// Exception thrown on an operation between incompatible objects class MismatchException : public Exception { public: virtual ~MismatchException() { } std::string GetDescription(void) const { return "Operation between objects in different games"; } }; /// Exception thrown on a parse error when reading a game savefile class InvalidFileException : public Exception { public: virtual ~InvalidFileException() { } std::string GetDescription(void) const { return "File not in a recognized format"; } }; //======================================================================= // Classes representing objects in a game //======================================================================= /// This class represents an outcome in a game. An outcome /// specifies a vector of payoffs to players. Payoffs are specified /// using text strings, in either decimal or rational format. All /// payoffs are treated as exact (that is, no conversion to floating /// point is done). class GameOutcomeRep : public GameObject { friend class GameRep; friend class TableFileGameRep; private: GameRep *m_game; int m_number; std::string m_label; Array m_payoffs; /// @name Lifecycle //@{ /// Creates a new outcome object, with payoffs set to zero GameOutcomeRep(GameRep *p_game, int p_number); virtual ~GameOutcomeRep() { } //@} public: /// @name Data access //@{ /// Returns the strategic game on which the outcome is defined. Game GetGame(void) const; /// Returns the index number of the outcome int GetNumber(void) const { return m_number; } /// Returns the text label associated with the outcome const std::string &GetLabel(void) const { return m_label; } /// Sets the text label associated with the outcome void SetLabel(const std::string &p_label) { m_label = p_label; } /// Gets the payoff associated with the outcome to player 'pl' template const T &GetPayoff(int pl) const { return (const T &) m_payoffs[pl]; } /// Sets the payoff to player 'pl' void SetPayoff(int pl, const std::string &p_value) { m_payoffs[pl] = p_value; //m_game->ClearComputedValues(); } //@} }; typedef GameObjectPtr GameOutcome; /// An action at an information set in an extensive game class GameActionRep : public GameObject { friend class GameRep; friend class GameInfosetRep; template friend class MixedBehavProfile; private: int m_number; std::string m_label; GameInfosetRep *m_infoset; GameActionRep(int p_number, const std::string &p_label, GameInfosetRep *p_infoset) : m_number(p_number), m_label(p_label), m_infoset(p_infoset) { } ~GameActionRep() { } public: int GetNumber(void) const { return m_number; } GameInfoset GetInfoset(void) const; const std::string &GetLabel(void) const { return m_label; } void SetLabel(const std::string &p_label) { m_label = p_label; } bool Precedes(const GameNode &) const; void DeleteAction(void); }; /// An information set in an extensive game class GameInfosetRep : public GameObject { friend class GameRep; friend class GameActionRep; friend class GamePlayerRep; friend class GameNodeRep; template friend class MixedBehavProfile; protected: GameRep *m_efg; int m_number; std::string m_label; GamePlayerRep *m_player; Array m_actions; Array m_members; int flag, whichbranch; Array m_probs; GameInfosetRep(GameRep *p_efg, int p_number, GamePlayerRep *p_player, int p_actions); ~GameInfosetRep(); /// Adds the node to the information set void AddMember(GameNodeRep *p_node) { m_members.Append(p_node); } /// Removes the node from the information set, invalidating if emptied void RemoveMember(GameNodeRep *); void RemoveAction(int which); public: Game GetGame(void) const; int GetNumber(void) const { return m_number; } GamePlayer GetPlayer(void) const; void SetPlayer(GamePlayer p); bool IsChanceInfoset(void) const; void SetLabel(const std::string &p_label) { m_label = p_label; } const std::string &GetLabel(void) const { return m_label; } GameAction InsertAction(GameAction p_where = 0); /// @name Actions //@{ /// Returns the number of actions available at the information set int NumActions(void) const { return m_actions.Length(); } /// Returns the p_index'th action at the information set GameAction GetAction(int p_index) const { return m_actions[p_index]; } /// Returns a forward iterator over the available actions GameActionIterator Actions(void) const { return GameActionIterator(m_actions); } //@} int NumMembers(void) const { return m_members.Length(); } GameNode GetMember(int p_index) const { return m_members[p_index]; } bool Precedes(GameNode) const; void SetActionProb(int i, const std::string &p_value); template const T &GetActionProb(int pl) const { return (const T &) m_probs[pl]; } void Reveal(GamePlayer); }; /// \brief A strategy in a game. /// /// This class represents a strategy in a game. /// For strategic games, this object internally stores an offset. /// This offset has the /// property that, for a strategy profile, adding the offsets of the /// strategies gives the index into the strategic game's table to /// find the outcome for that strategy profile, making payoff computation /// relatively efficient. class GameStrategyRep : public GameObject { friend class GameRep; friend class GamePlayerRep; friend class PureStrategyProfile; template friend class MixedStrategyProfile; template friend class MixedBehavProfile; private: int m_number, m_id; GamePlayerRep *m_player; long m_offset; std::string m_label; Array m_behav; /// @name Lifecycle //@{ /// Creates a new strategy for the given player. GameStrategyRep(GamePlayerRep *p_player) : m_number(0), m_id(0), m_player(p_player), m_offset(0L) { } //@} public: /// @name Data access //@{ /// Returns the text label associated with the strategy const std::string &GetLabel(void) const { return m_label; } /// Sets the text label associated with the strategy void SetLabel(const std::string &p_label) { m_label = p_label; } /// Returns the player for whom this is a strategy GamePlayer GetPlayer(void) const; /// Returns the index of the strategy for its player int GetNumber(void) const { return m_number; } /// Returns the global number of the strategy in the game int GetId(void) const { return m_id; } /// Remove this strategy from the game void DeleteStrategy(void); //@} }; /// A player in a game class GamePlayerRep : public GameObject { friend class GameRep; friend class GameInfosetRep; friend class GameStrategyRep; friend class GameNodeRep; template friend class MixedBehavProfile; template friend class MixedStrategyProfile; /// @name Building reduced form strategies //@{ void MakeStrategy(void); void MakeReducedStrats(GameNodeRep *, GameNodeRep *); //@} private: GameRep *m_game; int m_number; std::string m_label; Array m_infosets; Array m_strategies; GamePlayerRep(GameRep *p_game, int p_id) : m_game(p_game), m_number(p_id) { } GamePlayerRep(GameRep *p_game, int p_id, int m_strats); ~GamePlayerRep(); public: int GetNumber(void) const { return m_number; } Game GetGame(void) const; const std::string &GetLabel(void) const { return m_label; } void SetLabel(const std::string &p_label) { m_label = p_label; } bool IsChance(void) const { return (m_number == 0); } /// @name Information sets //@{ /// Returns the number of information sets at which the player makes a choice int NumInfosets(void) const { return m_infosets.Length(); } /// Returns the p_index'th information set GameInfoset GetInfoset(int p_index) const { return m_infosets[p_index]; } /// Returns a forward iterator over the information sets GameInfosetIterator Infosets(void) const { return GameInfosetIterator(m_infosets); } /// @name Strategies //@{ /// Returns the number of strategies available to the player int NumStrategies(void) const { return m_strategies.Length(); } /// Returns the st'th strategy for the player GameStrategy GetStrategy(int st) const { return m_strategies[st]; } /// Returns a forward iterator over the strategies GameStrategyIterator Strategies(void) const { return GameStrategyIterator(m_strategies); } /// Creates a new strategy for the player GameStrategy NewStrategy(void); //@} }; /// A node in an extensive game class GameNodeRep : public GameObject { friend class GameRep; friend class GameActionRep; friend class GameInfosetRep; friend class GamePlayerRep; friend class PureBehavProfile; template friend class MixedBehavProfile; protected: int number; GameRep *m_efg; std::string m_label; GameInfosetRep *infoset; GameNodeRep *m_parent; GameOutcomeRep *outcome; Array children; GameNodeRep *whichbranch, *ptr; GameNodeRep(GameRep *e, GameNodeRep *p); ~GameNodeRep(); void DeleteOutcome(GameOutcomeRep *outc); void CopySubtree(GameNodeRep *, GameNodeRep *); public: Game GetGame(void) const; const std::string &GetLabel(void) const { return m_label; } void SetLabel(const std::string &p_label) { m_label = p_label; } int GetNumber(void) const { return number; } int NumberInInfoset(void) const { return infoset->m_members.Find(const_cast(this)); } int NumChildren(void) const { return children.Length(); } GameInfoset GetInfoset(void) const { return infoset; } void SetInfoset(GameInfoset); GameInfoset LeaveInfoset(void); bool IsTerminal(void) const { return (children.Length() == 0); } GamePlayer GetPlayer(void) const { return (infoset) ? infoset->GetPlayer() : 0; } GameAction GetPriorAction(void) const; // returns null if root node GameNode GetChild(int i) const { return children[i]; } GameNode GetParent(void) const { return m_parent; } GameNode GetNextSibling(void) const; GameNode GetPriorSibling(void) const; GameOutcome GetOutcome(void) const { return outcome; } void SetOutcome(const GameOutcome &p_outcome); bool IsSuccessorOf(GameNode from) const; bool IsSubgameRoot(void) const; void DeleteParent(void); void DeleteTree(void); void CopyTree(GameNode src); void MoveTree(GameNode src); GameInfoset AppendMove(GamePlayer p_player, int p_actions); GameInfoset AppendMove(GameInfoset p_infoset); GameInfoset InsertMove(GamePlayer p_player, int p_actions); GameInfoset InsertMove(GameInfoset p_infoset); }; /// This class represents a strategy profile on a strategic game. /// It specifies exactly one strategy for each player defined on the /// game. /// Note that, although this is in some sense the analog of a node for /// a strategic game, this is not a reference-counted object. class PureStrategyProfile { friend class GameRep; private: long m_index; Game m_nfg; Array m_profile; public: /// @name Lifecycle //@{ /// Construct a new strategy profile on the specified game PureStrategyProfile(const Gambit::Game &); //@} /// @name Data access and manipulation //@{ /// Get the strategy played by player pl const GameStrategy &GetStrategy(int pl) const { return m_profile[pl]; } /// Get the strategy played by the player const GameStrategy &GetStrategy(const GamePlayer &p_player) const { return m_profile[p_player->GetNumber()]; } /// Set the strategy for a player void SetStrategy(const GameStrategy &); /// Get the outcome that results from the profile GameOutcome GetOutcome(void) const; /// Set the outcome that results from the profile void SetOutcome(GameOutcome p_outcome); /// Get the payoff to player pl that results from the profile template T GetPayoff(int pl) const; /// Get the payoff to the player resulting from the profile template T GetPayoff(const GamePlayer &p_player) const { return GetPayoff(p_player->GetNumber()); } /// Get the value of playing strategy against the profile template T GetStrategyValue(const GameStrategy &) const; //@} }; /// This class represents a behavior profile on an extensive game. /// It specifies exactly one strategy for each information set in the /// game. class PureBehavProfile { private: Game m_efg; Array > m_profile; public: /// @name Lifecycle //@{ /// Construct a new behavior profile on the specified game PureBehavProfile(Game); /// @name Data access and manipulation //@{ /// Get the action played at an information set GameAction GetAction(const GameInfoset &) const; /// Set the action played at an information set void SetAction(const GameAction &); /// Get the payoff to player pl that results from the profile template T GetPayoff(int pl) const; /// Get the payoff to the player that results from the profile template T GetPayoff(const GamePlayer &p_player) const { return GetPayoff(p_player->GetNumber()); } /// Get the payoff to player pl conditional on reaching a node template T GetNodeValue(const GameNode &, int pl) const; /// Get the payoff to playing the action, conditional on the profile template T GetActionValue(const GameAction &) const; //@} }; /// This is the class for representing an arbitrary finite game. class GameRep : public GameObject { friend class GameInfosetRep; friend class GamePlayerRep; friend class GameNodeRep; friend class PureStrategyProfile; template friend class MixedBehavProfile; template friend class MixedStrategyProfile; protected: mutable bool m_computedValues; std::string m_title, m_comment; Array m_players; GamePlayerRep *m_chance; Array m_outcomes; GameNodeRep *m_root; Array m_results; /// @name Private auxiliary functions //@{ void NumberNodes(GameNodeRep *, int &); void IndexStrategies(void); void RebuildTable(void); //@} public: /// @name Lifecycle //@{ /// Construct a new trivial game GameRep(void); /// Construct a new table game with the given dimension GameRep(const Array &p_dim); /// Clean up the game virtual ~GameRep(); /// Create a copy of the game, as a new game Game Copy(void) const; //@} /// @name General data access //@{ /// Returns true if the game has a game tree representation bool IsTree(void) const { return (m_root != 0); } /// Get the text label associated with the game const std::string &GetTitle(void) const { return m_title; } /// Set the text label associated with the game void SetTitle(const std::string &p_title) { m_title = p_title; } /// Get the text comment associated with the game const std::string &GetComment(void) const { return m_comment; } /// Set the text comment associated with the game void SetComment(const std::string &p_comment) { m_comment = p_comment; } /// Returns true if the game is constant-sum bool IsConstSum(void) const; /// Returns the smallest payoff in any outcome of the game Rational GetMinPayoff(int pl = 0) const; /// Returns the largest payoff in any outcome of the game Rational GetMaxPayoff(int pl = 0) const; /// Returns true if the game is perfect recall. If not, the specified /// a pair of violating information sets is returned in the parameters. bool IsPerfectRecall(GameInfoset &, GameInfoset &) const; /// Returns true if the game is perfect recall bool IsPerfectRecall(void) const { GameInfoset s, t; return IsPerfectRecall(s, t); } //@} /// @name Managing the representation //@{ /// Renumber all game objects in a canonical way void Canonicalize(void); /// Clear out any computed values void ClearComputedValues(void) const; /// Build any computed values anew void BuildComputedValues(void); /// Have computed values been built? bool HasComputedValues(void) const { return m_computedValues; } //@} /// @name Writing data files //@{ /// Write the game in .efg format to the specified stream void WriteEfgFile(std::ostream &) const; /// Write the subtree starting at node in .efg format to the specified stream void WriteEfgFile(std::ostream &, const GameNode &p_node) const; /// Write the game in .nfg format to the specified stream void WriteNfgFile(std::ostream &) const; //@} /// @name Dimensions of the game //@{ /// The number of actions in each information set PVector NumActions(void) const; /// The number of members in each information set PVector NumMembers(void) const; /// The number of strategies for each player Array NumStrategies(void) const; /// Gets the i'th strategy in the game, numbered globally GameStrategy GetStrategy(int p_index) const; /// Returns the total number of actions in the game int BehavProfileLength(void) const; /// Returns the total number of strategies in the game int MixedProfileLength(void) const; //@} /// @name Players //@{ /// Returns the number of players in the game int NumPlayers(void) const { return m_players.Length(); } /// Returns the pl'th player in the game GamePlayer GetPlayer(int pl) const { return m_players[pl]; } /// Returns an iterator over the players GamePlayerIterator Players(void) const { return GamePlayerIterator(m_players); } /// Returns the chance (nature) player GamePlayer GetChance(void) const { return m_chance; } /// Creates a new player in the game, with no moves GamePlayer NewPlayer(void); //@} /// @name Information sets //@{ /// Returns the iset'th information set in the game (numbered globally) GameInfoset GetInfoset(int iset) const; /// Returns an array with the number of information sets per personal player Array NumInfosets(void) const; /// Returns the act'th action in the game (numbered globally) GameAction GetAction(int act) const; //@} /// @name Outcomes //@{ /// Returns the number of outcomes defined in the game int NumOutcomes(void) const { return m_outcomes.Length(); } /// Returns the index'th outcome defined in the game GameOutcome GetOutcome(int index) const { return m_outcomes[index]; } /// Creates a new outcome in the game GameOutcome NewOutcome(void); /// Deletes the specified outcome from the game void DeleteOutcome(const GameOutcome &); //@} /// @name Nodes //@{ /// Returns the root node of the game GameNode GetRoot(void) const { if (m_root) return m_root; else throw UndefinedException(); } /// Returns the number of nodes in the game int NumNodes(void) const; //@} }; typedef GameObjectPtr Game; /// Convenience function to create new game tree inline Game NewTree(void) { return new GameRep; } /// Convenience function to create new game table inline Game NewTable(const Array &p_dim) { return new GameRep(p_dim); } //======================================================================= // Inline members of game representation classes //======================================================================= // These must be postponed to here in the file because they require // all classes to be defined. inline Game GameOutcomeRep::GetGame(void) const { return m_game; } inline GameInfoset GameActionRep::GetInfoset(void) const { return m_infoset; } inline Game GameInfosetRep::GetGame(void) const { return m_efg; } inline GamePlayer GameInfosetRep::GetPlayer(void) const { return m_player; } inline bool GameInfosetRep::IsChanceInfoset(void) const { return m_player->IsChance(); } inline GamePlayer GameStrategyRep::GetPlayer(void) const { return m_player; } inline Game GamePlayerRep::GetGame(void) const { return m_game; } inline Game GameNodeRep::GetGame(void) const { return m_efg; } template<> inline double PureBehavProfile::GetPayoff(int pl) const { return GetNodeValue(m_efg->GetRoot(), pl); } template<> inline Rational PureBehavProfile::GetPayoff(int pl) const { return GetNodeValue(m_efg->GetRoot(), pl); } template<> inline std::string PureBehavProfile::GetPayoff(int pl) const { return ToText(GetNodeValue(m_efg->GetRoot(), pl)); } //======================================================================= /// Reads a game in .efg or .nfg format from the input stream Game ReadGame(std::istream &) throw (InvalidFileException); } // end namespace gambit #endif // LIBGAMBIT_GAME_H gambit-0.2010.09.01/src/libgambit/integer.cc0000644000076500007650000016063111435216101015126 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/integer.cc // Implementation of an arbitrary-length integer class // // The original copyright and license are included below. /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of the GNU C++ Library. 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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Some of the following algorithms are very loosely based on those from MIT C-Scheme bignum.c, which is Copyright (c) 1987 Massachusetts Institute of Technology with other guidance from Knuth, vol. 2 Thanks to the creators of the algorithms. */ #include #if defined(__GNUG__) && !defined(__APPLE_CC__) #pragma implementation #endif #include "integer.h" #include #include #include #include #include #include namespace Gambit { long lg(unsigned long x) { long l = 0; while (x > 1) { x = x >> 1; ++l; } return l; } #ifndef HUGE_VAL #ifdef HUGE #define HUGE_VAL HUGE #else #define HUGE_VAL DBL_MAX #endif #endif /* Sizes of shifts for multiple-precision arithmetic. These should not be changed unless Integer representation as unsigned shorts is changed in the implementation files. */ #define I_SHIFT (sizeof(short) * CHAR_BIT) #define I_RADIX ((unsigned long)(1L << I_SHIFT)) #define I_MAXNUM ((unsigned long)((I_RADIX - 1))) #define I_MINNUM ((unsigned long)(I_RADIX >> 1)) #define I_POSITIVE 1 #define I_NEGATIVE 0 /* All routines assume SHORT_PER_LONG > 1 */ #define SHORT_PER_LONG ((unsigned)(((sizeof(long) + sizeof(short) - 1) / sizeof(short)))) #define CHAR_PER_LONG ((unsigned)sizeof(long)) /* minimum and maximum sizes for an IntegerRep */ #define MIN_INTREP_SIZE 16 #define MAX_INTREP_SIZE I_MAXNUM #ifndef MALLOC_MIN_OVERHEAD #define MALLOC_MIN_OVERHEAD 4 #endif static IntegerRep _ZeroRep = {1, 0, 1, {0}}; static IntegerRep _OneRep = {1, 0, 1, {1}}; static IntegerRep _MinusOneRep = {1, 0, 0, {1}}; // utilities to extract and transfer bits // get low bits inline static unsigned short extract(unsigned long x) { return (unsigned short) (x & I_MAXNUM); } // transfer high bits to low inline static unsigned long down(unsigned long x) { return (x >> I_SHIFT) & I_MAXNUM; } // transfer low bits to high inline static unsigned long up(unsigned long x) { return x << I_SHIFT; } // compare two equal-length reps static int docmp(const unsigned short* x, const unsigned short* y, int l) { int diff = 0; const unsigned short* xs = &(x[l]); const unsigned short* ys = &(y[l]); while (l-- > 0 && (diff = (*--xs) - (*--ys)) == 0); return diff; } // figure out max length of result of +, -, etc. inline static int calc_len(int len1, int len2, int pad) { return (len1 >= len2)? len1 + pad : len2 + pad; } // ensure len & sgn are correct static void Icheck(IntegerRep* rep) { int l = rep->len; const unsigned short* p = &(rep->s[l]); while (l > 0 && *--p == 0) --l; if ((rep->len = l) == 0) rep->sgn = I_POSITIVE; } // zero out the end of a rep static void Iclear_from(IntegerRep* rep, int p) { unsigned short* cp = &(rep->s[p]); const unsigned short* cf = &(rep->s[rep->len]); while(cp < cf) *cp++ = 0; } // copy parts of a rep void scpy(const unsigned short* src, unsigned short* dest,int nb) { while (--nb >= 0) *dest++ = *src++; } // make sure an argument is valid static inline void nonnil(const IntegerRep* rep) { assert(rep != 0); } // allocate a new Irep. Pad to something close to a power of two. static IntegerRep* Inew(int newlen) { unsigned int siz = sizeof(IntegerRep) + newlen * sizeof(short) + MALLOC_MIN_OVERHEAD; unsigned int allocsiz = MIN_INTREP_SIZE; while (allocsiz < siz) allocsiz <<= 1; // find a power of 2 allocsiz -= MALLOC_MIN_OVERHEAD; assert((unsigned long) allocsiz < MAX_INTREP_SIZE * sizeof(short)); IntegerRep* rep = (IntegerRep *) new char[allocsiz]; rep->sz = (allocsiz - sizeof(IntegerRep) + sizeof(short)) / sizeof(short); return rep; } // allocate: use the bits in src if non-null, clear the rest IntegerRep* Ialloc(IntegerRep* old, const unsigned short* src, int srclen, int newsgn, int newlen) { IntegerRep* rep; if (old == 0 || newlen > old->sz) rep = Inew(newlen); else rep = old; rep->len = newlen; rep->sgn = newsgn; scpy(src, rep->s, srclen); Iclear_from(rep, srclen); if (old != rep && old != 0 && !STATIC_IntegerRep(old)) delete old; return rep; } // allocate and clear IntegerRep* Icalloc(IntegerRep* old, int newlen) { IntegerRep* rep; if (old == 0 || newlen > old->sz) { if (old != 0 && !STATIC_IntegerRep(old)) delete old; rep = Inew(newlen); } else rep = old; rep->len = newlen; rep->sgn = I_POSITIVE; Iclear_from(rep, 0); return rep; } // reallocate IntegerRep* Iresize(IntegerRep* old, int newlen) { IntegerRep* rep; unsigned short oldlen; if (old == 0) { oldlen = 0; rep = Inew(newlen); rep->sgn = I_POSITIVE; } else { oldlen = old->len; if (newlen > old->sz) { rep = Inew(newlen); scpy(old->s, rep->s, oldlen); rep->sgn = old->sgn; if (!STATIC_IntegerRep(old)) delete old; } else rep = old; } rep->len = newlen; Iclear_from(rep, oldlen); return rep; } // same, for straight copy IntegerRep* Icopy(IntegerRep* old, const IntegerRep* src) { if (old == src) return old; IntegerRep* rep; if (src == 0) { if (old == 0) rep = Inew(0); else { rep = old; Iclear_from(rep, 0); } rep->len = 0; rep->sgn = I_POSITIVE; } else { int newlen = src->len; if (old == 0 || newlen > old->sz) { if (old != 0 && !STATIC_IntegerRep(old)) delete old; rep = Inew(newlen); } else rep = old; rep->len = newlen; rep->sgn = src->sgn; scpy(src->s, rep->s, newlen); } return rep; } // allocate & copy space for a long IntegerRep* Icopy_long(IntegerRep* old, long x) { int newsgn = (x >= 0); IntegerRep* rep = Icopy_ulong(old, newsgn ? x : -x); rep->sgn = newsgn; return rep; } IntegerRep* Icopy_ulong(IntegerRep* old, unsigned long x) { unsigned short src[SHORT_PER_LONG]; unsigned short srclen = 0; while (x != 0) { src[srclen++] = extract(x); x = down(x); } IntegerRep* rep; if (old == 0 || srclen > old->sz) { if (old != 0 && !STATIC_IntegerRep(old)) delete old; rep = Inew(srclen); } else rep = old; rep->len = srclen; rep->sgn = I_POSITIVE; scpy(src, rep->s, srclen); return rep; } // special case for zero -- it's worth it! IntegerRep* Icopy_zero(IntegerRep* old) { if (old == 0 || STATIC_IntegerRep(old)) return &_ZeroRep; old->len = 0; old->sgn = I_POSITIVE; return old; } // special case for 1 or -1 IntegerRep* Icopy_one(IntegerRep* old, int newsgn) { if (old == 0 || 1 > old->sz) { if (old != 0 && !STATIC_IntegerRep(old)) delete old; return newsgn==I_NEGATIVE ? &_MinusOneRep : &_OneRep; } old->sgn = newsgn; old->len = 1; old->s[0] = 1; return old; } // convert to a legal two's complement long if possible // if too big, return most negative/positive value long Itolong(const IntegerRep* rep) { if ((unsigned)(rep->len) > (unsigned)(SHORT_PER_LONG)) return (rep->sgn == I_POSITIVE) ? LONG_MAX : LONG_MIN; else if (rep->len == 0) return 0; else if ((unsigned)(rep->len) < (unsigned)(SHORT_PER_LONG)) { unsigned long a = rep->s[rep->len-1]; #ifndef __BCC55__ // This condition is always false under BCC55 if (SHORT_PER_LONG > 2) // normally optimized out { for (int i = rep->len - 2; i >= 0; --i) a = up(a) | rep->s[i]; } #endif // __BCC55__ return (rep->sgn == I_POSITIVE)? a : -((long)a); } else { unsigned long a = rep->s[SHORT_PER_LONG - 1]; if (a >= I_MINNUM) return (rep->sgn == I_POSITIVE) ? LONG_MAX : LONG_MIN; else { a = up(a) | rep->s[SHORT_PER_LONG - 2]; #ifndef __BCC55__ // This condition is always false under BCC55 if (SHORT_PER_LONG > 2) { for (int i = SHORT_PER_LONG - 3; i >= 0; --i) a = up(a) | rep->s[i]; } #endif // __BCC55__ return (rep->sgn == I_POSITIVE)? a : -((long)a); } } } // test whether op long() will work. // careful about asymmetry between LONG_MIN & LONG_MAX int Iislong(const IntegerRep* rep) { unsigned int l = rep->len; if (l < SHORT_PER_LONG) return 1; else if (l > SHORT_PER_LONG) return 0; else if ((unsigned)(rep->s[SHORT_PER_LONG - 1]) < (unsigned)(I_MINNUM)) return 1; else if (rep->sgn == I_NEGATIVE && rep->s[SHORT_PER_LONG - 1] == I_MINNUM) { for (unsigned int i = 0; i < SHORT_PER_LONG - 1; ++i) if (rep->s[i] != 0) return 0; return 1; } else return 0; } // convert to a double double Itodouble(const IntegerRep* rep) { double d = 0.0; double bound = DBL_MAX / 2.0; for (int i = rep->len - 1; i >= 0; --i) { unsigned short a = (unsigned short) (I_RADIX >> 1); while (a != 0) { if (d >= bound) return (rep->sgn == I_NEGATIVE) ? -HUGE_VAL : HUGE_VAL; d *= 2.0; if (rep->s[i] & a) d += 1.0; a >>= 1; } } if (rep->sgn == I_NEGATIVE) return -d; else return d; } // see whether op double() will work- // have to actually try it in order to find out // since otherwise might trigger fp exception int Iisdouble(const IntegerRep* rep) { double d = 0.0; double bound = DBL_MAX / 2.0; for (int i = rep->len - 1; i >= 0; --i) { unsigned short a = (unsigned short) (I_RADIX >> 1); while (a != 0) { if (d > bound || (d == bound && (i > 0 || (rep->s[i] & a)))) return 0; d *= 2.0; if (rep->s[i] & a) d += 1.0; a >>= 1; } } return 1; } // real division of num / den double ratio(const Integer& num, const Integer& den) { Integer q, r; divide(num, den, q, r); double d1 = q.as_double(); if (d1 >= DBL_MAX || d1 <= -DBL_MAX || sign(r) == 0) return d1; else // use as much precision as available for fractional part { double d2 = 0.0; double d3 = 0.0; int cont = 1; for (int i = den.rep->len - 1; i >= 0 && cont; --i) { unsigned short a = (unsigned short) (I_RADIX >> 1); while (a != 0) { if (d2 + 1.0 == d2) // out of precision when we get here { cont = 0; break; } d2 *= 2.0; if (den.rep->s[i] & a) d2 += 1.0; if (i < r.rep->len) { d3 *= 2.0; if (r.rep->s[i] & a) d3 += 1.0; } a >>= 1; } } if (sign(r) < 0) d3 = -d3; return d1 + d3 / d2; } } // comparison functions int compare(const IntegerRep* x, const IntegerRep* y) { int diff = x->sgn - y->sgn; if (diff == 0) { diff = x->len - y->len; if (diff == 0) diff = docmp(x->s, y->s, x->len); if (x->sgn == I_NEGATIVE) diff = -diff; } return diff; } int ucompare(const IntegerRep* x, const IntegerRep* y) { int diff = x->len - y->len; if (diff == 0) { int l = x->len; const unsigned short* xs = &(x->s[l]); const unsigned short* ys = &(y->s[l]); while (l-- > 0 && (diff = (*--xs) - (*--ys)) == 0); } return diff; } int compare(const IntegerRep* x, long y) { int xl = x->len; int xsgn = x->sgn; if (y == 0) { if (xl == 0) return 0; else if (xsgn == I_NEGATIVE) return -1; else return 1; } else { int ysgn = y >= 0; unsigned long uy = (ysgn)? y : -y; int diff = xsgn - ysgn; if (diff == 0) { diff = xl - SHORT_PER_LONG; if (diff <= 0) { unsigned short tmp[SHORT_PER_LONG]; int yl = 0; while (uy != 0) { tmp[yl++] = extract(uy); uy = down(uy); } diff = xl - yl; if (diff == 0) diff = docmp(x->s, tmp, xl); } if (xsgn == I_NEGATIVE) diff = -diff; } return diff; } } int ucompare(const IntegerRep* x, long y) { int xl = x->len; if (y == 0) return xl; else { unsigned long uy = (y >= 0)? y : -y; int diff = xl - SHORT_PER_LONG; if (diff <= 0) { unsigned short tmp[SHORT_PER_LONG]; int yl = 0; while (uy != 0) { tmp[yl++] = extract(uy); uy = down(uy); } diff = xl - yl; if (diff == 0) diff = docmp(x->s, tmp, xl); } return diff; } } // arithmetic functions IntegerRep* add(const IntegerRep* x, int negatex, const IntegerRep* y, int negatey, IntegerRep* r) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; int xsgn = (negatex && xl != 0) ? !x->sgn : x->sgn; int ysgn = (negatey && yl != 0) ? !y->sgn : y->sgn; int xrsame = x == r; int yrsame = y == r; if (yl == 0) r = Ialloc(r, x->s, xl, xsgn, xl); else if (xl == 0) r = Ialloc(r, y->s, yl, ysgn, yl); else if (xsgn == ysgn) { if (xrsame || yrsame) r = Iresize(r, calc_len(xl, yl, 1)); else r = Icalloc(r, calc_len(xl, yl, 1)); r->sgn = xsgn; unsigned short* rs = r->s; const unsigned short* as; const unsigned short* bs; const unsigned short* topa; const unsigned short* topb; if (xl >= yl) { as = (xrsame)? r->s : x->s; topa = &(as[xl]); bs = (yrsame)? r->s : y->s; topb = &(bs[yl]); } else { bs = (xrsame)? r->s : x->s; topb = &(bs[xl]); as = (yrsame)? r->s : y->s; topa = &(as[yl]); } unsigned long sum = 0; while (bs < topb) { sum += (unsigned long)(*as++) + (unsigned long)(*bs++); *rs++ = extract(sum); sum = down(sum); } while (sum != 0 && as < topa) { sum += (unsigned long)(*as++); *rs++ = extract(sum); sum = down(sum); } if (sum != 0) *rs = extract(sum); else if (rs != as) while (as < topa) *rs++ = *as++; } else { int comp = ucompare(x, y); if (comp == 0) r = Icopy_zero(r); else { if (xrsame || yrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); unsigned short* rs = r->s; const unsigned short* as; const unsigned short* bs; const unsigned short* topa; const unsigned short* topb; if (comp > 0) { as = (xrsame)? r->s : x->s; topa = &(as[xl]); bs = (yrsame)? r->s : y->s; topb = &(bs[yl]); r->sgn = xsgn; } else { bs = (xrsame)? r->s : x->s; topb = &(bs[xl]); as = (yrsame)? r->s : y->s; topa = &(as[yl]); r->sgn = ysgn; } unsigned long hi = 1; while (bs < topb) { hi += (unsigned long)(*as++) + I_MAXNUM - (unsigned long)(*bs++); *rs++ = extract(hi); hi = down(hi); } while (hi == 0 && as < topa) { hi = (unsigned long)(*as++) + I_MAXNUM; *rs++ = extract(hi); hi = down(hi); } if (rs != as) while (as < topa) *rs++ = *as++; } } Icheck(r); return r; } IntegerRep* add(const IntegerRep* x, int negatex, long y, IntegerRep* r) { nonnil(x); int xl = x->len; int xsgn = (negatex && xl != 0) ? !x->sgn : x->sgn; int xrsame = x == r; int ysgn = (y >= 0); unsigned long uy = (ysgn)? y : -y; if (y == 0) r = Ialloc(r, x->s, xl, xsgn, xl); else if (xl == 0) r = Icopy_long(r, y); else if (xsgn == ysgn) { if (xrsame) r = Iresize(r, calc_len(xl, SHORT_PER_LONG, 1)); else r = Icalloc(r, calc_len(xl, SHORT_PER_LONG, 1)); r->sgn = xsgn; unsigned short* rs = r->s; const unsigned short* as = (xrsame)? r->s : x->s; const unsigned short* topa = &(as[xl]); unsigned long sum = 0; while (as < topa && uy != 0) { unsigned long u = extract(uy); uy = down(uy); sum += (unsigned long)(*as++) + u; *rs++ = extract(sum); sum = down(sum); } while (sum != 0 && as < topa) { sum += (unsigned long)(*as++); *rs++ = extract(sum); sum = down(sum); } if (sum != 0) *rs = extract(sum); else if (rs != as) while (as < topa) *rs++ = *as++; } else { unsigned short tmp[SHORT_PER_LONG]; int yl = 0; while (uy != 0) { tmp[yl++] = extract(uy); uy = down(uy); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, tmp, yl); if (comp == 0) r = Icopy_zero(r); else { if (xrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); unsigned short* rs = r->s; const unsigned short* as; const unsigned short* bs; const unsigned short* topa; const unsigned short* topb; if (comp > 0) { as = (xrsame)? r->s : x->s; topa = &(as[xl]); bs = tmp; topb = &(bs[yl]); r->sgn = xsgn; } else { bs = (xrsame)? r->s : x->s; topb = &(bs[xl]); as = tmp; topa = &(as[yl]); r->sgn = ysgn; } unsigned long hi = 1; while (bs < topb) { hi += (unsigned long)(*as++) + I_MAXNUM - (unsigned long)(*bs++); *rs++ = extract(hi); hi = down(hi); } while (hi == 0 && as < topa) { hi = (unsigned long)(*as++) + I_MAXNUM; *rs++ = extract(hi); hi = down(hi); } if (rs != as) while (as < topa) *rs++ = *as++; } } Icheck(r); return r; } IntegerRep* multiply(const IntegerRep* x, const IntegerRep* y, IntegerRep* r) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; int rl = xl + yl; int rsgn = x->sgn == y->sgn; int xrsame = x == r; int yrsame = y == r; int xysame = x == y; if (xl == 0 || yl == 0) r = Icopy_zero(r); else if (xl == 1 && x->s[0] == 1) r = Icopy(r, y); else if (yl == 1 && y->s[0] == 1) r = Icopy(r, x); else if (!(xysame && xrsame)) { if (xrsame || yrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); unsigned short* rs = r->s; unsigned short* topr = &(rs[rl]); // use best inner/outer loop params given constraints unsigned short* currentr; const unsigned short* bota; const unsigned short* as; const unsigned short* botb; const unsigned short* topb; if (xrsame) { currentr = &(rs[xl-1]); bota = rs; as = currentr; botb = y->s; topb = &(botb[yl]); } else if (yrsame) { currentr = &(rs[yl-1]); bota = rs; as = currentr; botb = x->s; topb = &(botb[xl]); } else if (xl <= yl) { currentr = &(rs[xl-1]); bota = x->s; as = &(bota[xl-1]); botb = y->s; topb = &(botb[yl]); } else { currentr = &(rs[yl-1]); bota = y->s; as = &(bota[yl-1]); botb = x->s; topb = &(botb[xl]); } while (as >= bota) { unsigned long ai = (unsigned long)(*as--); unsigned short* rs = currentr--; *rs = 0; if (ai != 0) { unsigned long sum = 0; const unsigned short* bs = botb; while (bs < topb) { sum += ai * (unsigned long)(*bs++) + (unsigned long)(*rs); *rs++ = extract(sum); sum = down(sum); } while (sum != 0 && rs < topr) { sum += (unsigned long)(*rs); *rs++ = extract(sum); sum = down(sum); } } } } else // x, y, and r same; compute over diagonals { r = Iresize(r, rl); unsigned short* botr = r->s; unsigned short* topr = &(botr[rl]); unsigned short* rs = &(botr[rl - 2]); const unsigned short* bota = (xrsame)? botr : x->s; const unsigned short* loa = &(bota[xl - 1]); const unsigned short* hia = loa; for (; rs >= botr; --rs) { const unsigned short* h = hia; const unsigned short* l = loa; unsigned long prod = (unsigned long)(*h) * (unsigned long)(*l); *rs = 0; for(;;) { unsigned short* rt = rs; unsigned long sum = prod + (unsigned long)(*rt); *rt++ = extract(sum); sum = down(sum); while (sum != 0 && rt < topr) { sum += (unsigned long)(*rt); *rt++ = extract(sum); sum = down(sum); } if (h > l) { rt = rs; sum = prod + (unsigned long)(*rt); *rt++ = extract(sum); sum = down(sum); while (sum != 0 && rt < topr) { sum += (unsigned long)(*rt); *rt++ = extract(sum); sum = down(sum); } if (--h >= ++l) prod = (unsigned long)(*h) * (unsigned long)(*l); else break; } else break; } if (loa > bota) --loa; else --hia; } } r->sgn = rsgn; Icheck(r); return r; } IntegerRep* multiply(const IntegerRep* x, long y, IntegerRep* r) { nonnil(x); int xl = x->len; if (xl == 0 || y == 0) r = Icopy_zero(r); else if (y == 1) r = Icopy(r, x); else { int ysgn = y >= 0; int rsgn = x->sgn == ysgn; unsigned long uy = (ysgn)? y : -y; unsigned short tmp[SHORT_PER_LONG]; int yl = 0; while (uy != 0) { tmp[yl++] = extract(uy); uy = down(uy); } int rl = xl + yl; int xrsame = x == r; if (xrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); unsigned short* rs = r->s; unsigned short* topr = &(rs[rl]); unsigned short* currentr; const unsigned short* bota; const unsigned short* as; const unsigned short* botb; const unsigned short* topb; if (xrsame) { currentr = &(rs[xl-1]); bota = rs; as = currentr; botb = tmp; topb = &(botb[yl]); } else if (xl <= yl) { currentr = &(rs[xl-1]); bota = x->s; as = &(bota[xl-1]); botb = tmp; topb = &(botb[yl]); } else { currentr = &(rs[yl-1]); bota = tmp; as = &(bota[yl-1]); botb = x->s; topb = &(botb[xl]); } while (as >= bota) { unsigned long ai = (unsigned long)(*as--); unsigned short* rs = currentr--; *rs = 0; if (ai != 0) { unsigned long sum = 0; const unsigned short* bs = botb; while (bs < topb) { sum += ai * (unsigned long)(*bs++) + (unsigned long)(*rs); *rs++ = extract(sum); sum = down(sum); } while (sum != 0 && rs < topr) { sum += (unsigned long)(*rs); *rs++ = extract(sum); sum = down(sum); } } } r->sgn = rsgn; } Icheck(r); return r; } // main division routine static void do_divide(unsigned short* rs, const unsigned short* ys, int yl, unsigned short* qs, int ql) { const unsigned short* topy = &(ys[yl]); unsigned short d1 = ys[yl - 1]; unsigned short d2 = ys[yl - 2]; int l = ql - 1; int i = l + yl; for (; l >= 0; --l, --i) { unsigned short qhat; // guess q if (d1 == rs[i]) qhat = (unsigned short) I_MAXNUM; else { unsigned long lr = up((unsigned long)rs[i]) | rs[i-1]; qhat = (unsigned short) (lr / d1); } for(;;) // adjust q, use docmp to avoid overflow problems { unsigned short ts[3]; unsigned long prod = (unsigned long)d2 * (unsigned long)qhat; ts[0] = extract(prod); prod = down(prod) + (unsigned long)d1 * (unsigned long)qhat; ts[1] = extract(prod); ts[2] = extract(down(prod)); if (docmp(ts, &(rs[i-2]), 3) > 0) --qhat; else break; }; // multiply & subtract const unsigned short* yt = ys; unsigned short* rt = &(rs[l]); unsigned long prod = 0; unsigned long hi = 1; while (yt < topy) { prod = (unsigned long)qhat * (unsigned long)(*yt++) + down(prod); hi += (unsigned long)(*rt) + I_MAXNUM - (unsigned long)(extract(prod)); *rt++ = extract(hi); hi = down(hi); } hi += (unsigned long)(*rt) + I_MAXNUM - (unsigned long)(down(prod)); *rt = extract(hi); hi = down(hi); // off-by-one, add back if (hi == 0) { --qhat; yt = ys; rt = &(rs[l]); hi = 0; while (yt < topy) { hi = (unsigned long)(*rt) + (unsigned long)(*yt++) + down(hi); *rt++ = extract(hi); } *rt = 0; } if (qs != 0) qs[l] = qhat; } } // divide by single digit, return remainder // if q != 0, then keep the result in q, else just compute rem static int unscale(const unsigned short* x, int xl, unsigned short y, unsigned short* q) { if (xl == 0 || y == 1) return 0; else if (q != 0) { unsigned short* botq = q; unsigned short* qs = &(botq[xl - 1]); const unsigned short* xs = &(x[xl - 1]); unsigned long rem = 0; while (qs >= botq) { rem = up(rem) | *xs--; unsigned long u = rem / y; *qs-- = extract(u); rem -= u * y; } int r = extract(rem); return r; } else // same loop, a bit faster if just need rem { const unsigned short* botx = x; const unsigned short* xs = &(botx[xl - 1]); unsigned long rem = 0; while (xs >= botx) { rem = up(rem) | *xs--; unsigned long u = rem / y; rem -= u * y; } int r = extract(rem); return r; } } IntegerRep* div(const IntegerRep* x, const IntegerRep* y, IntegerRep* q) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; // if (yl == 0) (*lib_error_handler)("Integer", "attempted division by zero"); assert(yl != 0); int comp = ucompare(x, y); int xsgn = x->sgn; int ysgn = y->sgn; int samesign = xsgn == ysgn; if (comp < 0) q = Icopy_zero(q); else if (comp == 0) q = Icopy_one(q, samesign); else if (yl == 1) { q = Icopy(q, x); unscale(q->s, q->len, y->s[0], q->s); } else { IntegerRep* yy = 0; IntegerRep* r = 0; unsigned short prescale = (unsigned short) (I_RADIX / (1 + y->s[yl - 1])); if (prescale != 1 || y == q) { yy = multiply(y, ((long)prescale & I_MAXNUM), yy); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { yy = (IntegerRep*)y; r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, yy->s, yl, q->s, ql); if (yy != y && !STATIC_IntegerRep(yy)) delete yy; if (!STATIC_IntegerRep(r)) delete r; } q->sgn = samesign; Icheck(q); return q; } IntegerRep* div(const IntegerRep* x, long y, IntegerRep* q) { nonnil(x); int xl = x->len; // if (y == 0) (*lib_error_handler)("Integer", "attempted division by zero"); assert(y != 0); unsigned short ys[SHORT_PER_LONG]; unsigned long u; int ysgn = y >= 0; if (ysgn) u = y; else u = -y; int yl = 0; while (u != 0) { ys[yl++] = extract(u); u = down(u); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, ys, xl); int xsgn = x->sgn; int samesign = xsgn == ysgn; if (comp < 0) q = Icopy_zero(q); else if (comp == 0) { q = Icopy_one(q, samesign); } else if (yl == 1) { q = Icopy(q, x); unscale(q->s, q->len, ys[0], q->s); } else { IntegerRep* r = 0; unsigned short prescale = (unsigned short) (I_RADIX / (1 + ys[yl - 1])); if (prescale != 1) { unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; ys[0] = extract(prod); prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; ys[1] = extract(prod); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, ys, yl, q->s, ql); if (!STATIC_IntegerRep(r)) delete r; } q->sgn = samesign; Icheck(q); return q; } void divide(const Integer& Ix, long y, Integer& Iq, long& rem) { const IntegerRep* x = Ix.rep; nonnil(x); IntegerRep* q = Iq.rep; int xl = x->len; // if (y == 0) (*lib_error_handler)("Integer", "attempted division by zero"); assert(y != 0); unsigned short ys[SHORT_PER_LONG]; unsigned long u; int ysgn = y >= 0; if (ysgn) u = y; else u = -y; int yl = 0; while (u != 0) { ys[yl++] = extract(u); u = down(u); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, ys, xl); int xsgn = x->sgn; int samesign = xsgn == ysgn; if (comp < 0) { rem = Itolong(x); q = Icopy_zero(q); } else if (comp == 0) { q = Icopy_one(q, samesign); rem = 0; } else if (yl == 1) { q = Icopy(q, x); rem = unscale(q->s, q->len, ys[0], q->s); } else { IntegerRep* r = 0; unsigned short prescale = (unsigned short) (I_RADIX / (1 + ys[yl - 1])); if (prescale != 1) { unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; ys[0] = extract(prod); prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; ys[1] = extract(prod); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, ys, yl, q->s, ql); if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } Icheck(r); rem = Itolong(r); if (!STATIC_IntegerRep(r)) delete r; } rem = abs(rem).as_long(); if (xsgn == I_NEGATIVE) rem = -rem; q->sgn = samesign; Icheck(q); Iq.rep = q; } void divide(const Integer& Ix, const Integer& Iy, Integer& Iq, Integer& Ir) { const IntegerRep* x = Ix.rep; nonnil(x); const IntegerRep* y = Iy.rep; nonnil(y); IntegerRep* q = Iq.rep; IntegerRep* r = Ir.rep; int xl = x->len; int yl = y->len; /* if (yl == 0) (*lib_error_handler)("Integer", "attempted division by zero"); */ assert(yl != 0); int comp = ucompare(x, y); int xsgn = x->sgn; int ysgn = y->sgn; int samesign = xsgn == ysgn; if (comp < 0) { q = Icopy_zero(q); r = Icopy(r, x); } else if (comp == 0) { q = Icopy_one(q, samesign); r = Icopy_zero(r); } else if (yl == 1) { q = Icopy(q, x); int rem = unscale(q->s, q->len, y->s[0], q->s); r = Icopy_long(r, rem); if (rem != 0) r->sgn = xsgn; } else { IntegerRep* yy = 0; unsigned short prescale = (unsigned short) (I_RADIX / (1 + y->s[yl - 1])); if (prescale != 1 || y == q || y == r) { yy = multiply(y, ((long)prescale & I_MAXNUM), yy); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { yy = (IntegerRep*)y; r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } int ql = xl - yl + 1; q = Icalloc(q, ql); do_divide(r->s, yy->s, yl, q->s, ql); if (yy != y && !STATIC_IntegerRep(yy)) delete yy; if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } } q->sgn = samesign; Icheck(q); Iq.rep = q; Icheck(r); Ir.rep = r; } IntegerRep* mod(const IntegerRep* x, const IntegerRep* y, IntegerRep* r) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; // if (yl == 0) (*lib_error_handler)("Integer", "attempted division by zero"); assert(yl != 0); int comp = ucompare(x, y); int xsgn = x->sgn; if (comp < 0) r = Icopy(r, x); else if (comp == 0) r = Icopy_zero(r); else if (yl == 1) { int rem = unscale(x->s, xl, y->s[0], 0); r = Icopy_long(r, rem); if (rem != 0) r->sgn = xsgn; } else { IntegerRep* yy = 0; unsigned short prescale = (unsigned short) (I_RADIX / (1 + y->s[yl - 1])); if (prescale != 1 || y == r) { yy = multiply(y, ((long)prescale & I_MAXNUM), yy); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { yy = (IntegerRep*)y; r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } do_divide(r->s, yy->s, yl, 0, xl - yl + 1); if (yy != y && !STATIC_IntegerRep(yy)) delete yy; if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } } Icheck(r); return r; } IntegerRep* mod(const IntegerRep* x, long y, IntegerRep* r) { nonnil(x); int xl = x->len; // if (y == 0) (*lib_error_handler)("Integer", "attempted division by zero"); assert(y != 0); unsigned short ys[SHORT_PER_LONG]; unsigned long u; int ysgn = y >= 0; if (ysgn) u = y; else u = -y; int yl = 0; while (u != 0) { ys[yl++] = extract(u); u = down(u); } int comp = xl - yl; if (comp == 0) comp = docmp(x->s, ys, xl); int xsgn = x->sgn; if (comp < 0) r = Icopy(r, x); else if (comp == 0) r = Icopy_zero(r); else if (yl == 1) { int rem = unscale(x->s, xl, ys[0], 0); r = Icopy_long(r, rem); if (rem != 0) r->sgn = xsgn; } else { unsigned short prescale = (unsigned short) (I_RADIX / (1 + ys[yl - 1])); if (prescale != 1) { unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; ys[0] = extract(prod); prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; ys[1] = extract(prod); r = multiply(x, ((long)prescale & I_MAXNUM), r); } else { r = Icalloc(r, xl + 1); scpy(x->s, r->s, xl); } do_divide(r->s, ys, yl, 0, xl - yl + 1); if (prescale != 1) { Icheck(r); unscale(r->s, r->len, prescale, r->s); } } Icheck(r); return r; } IntegerRep* lshift(const IntegerRep* x, long y, IntegerRep* r) { nonnil(x); int xl = x->len; if (xl == 0 || y == 0) { r = Icopy(r, x); return r; } int xrsame = x == r; int rsgn = x->sgn; long ay = (y < 0)? -y : y; int bw = (int) (ay / I_SHIFT); int sw = (int) (ay % I_SHIFT); if (y > 0) { int rl = bw + xl + 1; if (xrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); unsigned short* botr = r->s; unsigned short* rs = &(botr[rl - 1]); const unsigned short* botx = (xrsame)? botr : x->s; const unsigned short* xs = &(botx[xl - 1]); unsigned long a = 0; while (xs >= botx) { a = up(a) | ((unsigned long)(*xs--) << sw); *rs-- = extract(down(a)); } *rs-- = extract(a); while (rs >= botr) *rs-- = 0; } else { int rl = xl - bw; if (rl < 0) r = Icopy_zero(r); else { if (xrsame) r = Iresize(r, rl); else r = Icalloc(r, rl); int rw = I_SHIFT - sw; unsigned short* rs = r->s; unsigned short* topr = &(rs[rl]); const unsigned short* botx = (xrsame)? rs : x->s; const unsigned short* xs = &(botx[bw]); const unsigned short* topx = &(botx[xl]); unsigned long a = (unsigned long)(*xs++) >> sw; while (xs < topx) { a |= (unsigned long)(*xs++) << rw; *rs++ = extract(a); a = down(a); } *rs++ = extract(a); if (xrsame) topr = (unsigned short*)topx; while (rs < topr) *rs++ = 0; } } r->sgn = rsgn; Icheck(r); return r; } IntegerRep* lshift(const IntegerRep* x, const IntegerRep* yy, int negatey, IntegerRep* r) { long y = Itolong(yy); if (negatey) y = -y; return lshift(x, y, r); } IntegerRep* bitop(const IntegerRep* x, const IntegerRep* y, IntegerRep* r, char op) { nonnil(x); nonnil(y); int xl = x->len; int yl = y->len; int xsgn = x->sgn; int xrsame = x == r; int yrsame = y == r; if (xrsame || yrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); r->sgn = xsgn; unsigned short* rs = r->s; unsigned short* topr = &(rs[r->len]); const unsigned short* as; const unsigned short* bs; const unsigned short* topb; if (xl >= yl) { as = (xrsame)? rs : x->s; bs = (yrsame)? rs : y->s; topb = &(bs[yl]); } else { bs = (xrsame)? rs : x->s; topb = &(bs[xl]); as = (yrsame)? rs : y->s; } switch (op) { case '&': while (bs < topb) *rs++ = *as++ & *bs++; while (rs < topr) *rs++ = 0; break; case '|': while (bs < topb) *rs++ = *as++ | *bs++; while (rs < topr) *rs++ = *as++; break; case '^': while (bs < topb) *rs++ = *as++ ^ *bs++; while (rs < topr) *rs++ = *as++; break; } Icheck(r); return r; } IntegerRep* bitop(const IntegerRep* x, long y, IntegerRep* r, char op) { nonnil(x); unsigned short tmp[SHORT_PER_LONG]; unsigned long u; int newsgn = (y >= 0); if (newsgn) u = y; else u = -y; int l = 0; while (u != 0) { tmp[l++] = extract(u); u = down(u); } int xl = x->len; int yl = l; int xsgn = x->sgn; int xrsame = x == r; if (xrsame) r = Iresize(r, calc_len(xl, yl, 0)); else r = Icalloc(r, calc_len(xl, yl, 0)); r->sgn = xsgn; unsigned short* rs = r->s; unsigned short* topr = &(rs[r->len]); const unsigned short* as; const unsigned short* bs; const unsigned short* topb; if (xl >= yl) { as = (xrsame)? rs : x->s; bs = tmp; topb = &(bs[yl]); } else { bs = (xrsame)? rs : x->s; topb = &(bs[xl]); as = tmp; } switch (op) { case '&': while (bs < topb) *rs++ = *as++ & *bs++; while (rs < topr) *rs++ = 0; break; case '|': while (bs < topb) *rs++ = *as++ | *bs++; while (rs < topr) *rs++ = *as++; break; case '^': while (bs < topb) *rs++ = *as++ ^ *bs++; while (rs < topr) *rs++ = *as++; break; } Icheck(r); return r; } IntegerRep* Compl(const IntegerRep* src, IntegerRep* r) { nonnil(src); r = Icopy(r, src); unsigned short* s = r->s; unsigned short* top = &(s[r->len - 1]); while (s < top) { unsigned short cmp = ~(*s); *s++ = cmp; } unsigned short a = *s; unsigned short b = 0; while (a != 0) { b <<= 1; if (!(a & 1)) b |= 1; a >>= 1; } *s = b; Icheck(r); return r; } void (setbit)(Integer& x, long b) { if (b >= 0) { int bw = (int) ((unsigned long)b / I_SHIFT); int sw = (int) ((unsigned long)b % I_SHIFT); int xl = x.rep ? x.rep->len : 0; if (xl <= bw) x.rep = Iresize(x.rep, calc_len(xl, bw+1, 0)); x.rep->s[bw] |= (1 << sw); Icheck(x.rep); } } void clearbit(Integer& x, long b) { if (b >= 0) { if (x.rep == 0) x.rep = &_ZeroRep; else { int bw = (int) ((unsigned long)b / I_SHIFT); int sw = (int) ((unsigned long)b % I_SHIFT); if (x.rep->len > bw) x.rep->s[bw] &= ~(1 << sw); } Icheck(x.rep); } } int testbit(const Integer& x, long b) { if (x.rep != 0 && b >= 0) { int bw = (int) ((unsigned long)b / I_SHIFT); int sw = (int) ((unsigned long)b % I_SHIFT); return (bw < x.rep->len && (x.rep->s[bw] & (1 << sw)) != 0); } else return 0; } // A version of knuth's algorithm B / ex. 4.5.3.34 // A better version that doesn't bother shifting all of `t' forthcoming IntegerRep* gcd(const IntegerRep* x, const IntegerRep* y) { nonnil(x); nonnil(y); int ul = x->len; int vl = y->len; if (vl == 0) return Ialloc(0, x->s, ul, I_POSITIVE, ul); else if (ul == 0) return Ialloc(0, y->s, vl, I_POSITIVE, vl); IntegerRep* u = Ialloc(0, x->s, ul, I_POSITIVE, ul); IntegerRep* v = Ialloc(0, y->s, vl, I_POSITIVE, vl); // find shift so that both not even long k = 0; int l = (ul <= vl)? ul : vl; int cont = 1, i; for (i = 0; i < l && cont; ++i) { unsigned long a = (i < ul)? u->s[i] : 0; unsigned long b = (i < vl)? v->s[i] : 0; for (unsigned int j = 0; j < I_SHIFT; ++j) { if ((a | b) & 1) { cont = 0; break; } else { ++k; a >>= 1; b >>= 1; } } } if (k != 0) { u = lshift(u, -k, u); v = lshift(v, -k, v); } IntegerRep* t; if (u->s[0] & 01) t = Ialloc(0, v->s, v->len, !v->sgn, v->len); else t = Ialloc(0, u->s, u->len, u->sgn, u->len); while (t->len != 0) { long s = 0; // shift t until odd cont = 1; int tl = t->len; for (i = 0; i < tl && cont; ++i) { unsigned long a = t->s[i]; for (unsigned int j = 0; j < I_SHIFT; ++j) { if (a & 1) { cont = 0; break; } else { ++s; a >>= 1; } } } if (s != 0) t = lshift(t, -s, t); if (t->sgn == I_POSITIVE) { u = Icopy(u, t); t = add(t, 0, v, 1, t); } else { v = Ialloc(v, t->s, t->len, !t->sgn, t->len); t = add(t, 0, u, 0, t); } } if (!STATIC_IntegerRep(t)) delete t; if (!STATIC_IntegerRep(v)) delete v; if (k != 0) u = lshift(u, k, u); return u; } long lg(const IntegerRep* x) { nonnil(x); int xl = x->len; if (xl == 0) return 0; long l = (xl - 1) * I_SHIFT - 1; unsigned short a = x->s[xl-1]; while (a != 0) { a = a >> 1; ++l; } return l; } IntegerRep* power(const IntegerRep* x, long y, IntegerRep* r) { nonnil(x); int sgn; if (x->sgn == I_POSITIVE || (!(y & 1))) sgn = I_POSITIVE; else sgn = I_NEGATIVE; int xl = x->len; if (y == 0 || (xl == 1 && x->s[0] == 1)) r = Icopy_one(r, sgn); else if (xl == 0 || y < 0) r = Icopy_zero(r); else if (y == 1 || y == -1) r = Icopy(r, x); else { int maxsize = (int) (((lg(x) + 1) * y) / I_SHIFT + 2); // pre-allocate space IntegerRep* b = Ialloc(0, x->s, xl, I_POSITIVE, maxsize); b->len = xl; r = Icalloc(r, maxsize); r = Icopy_one(r, I_POSITIVE); for(;;) { if (y & 1) r = multiply(r, b, r); if ((y >>= 1) == 0) break; else b = multiply(b, b, b); } if (!STATIC_IntegerRep(b)) delete b; } r->sgn = sgn; Icheck(r); return r; } IntegerRep* abs(const IntegerRep* src, IntegerRep* dest) { nonnil(src); if (src != dest) dest = Icopy(dest, src); dest->sgn = I_POSITIVE; return dest; } IntegerRep* negate(const IntegerRep* src, IntegerRep* dest) { nonnil(src); if (src != dest) dest = Icopy(dest, src); if (dest->len != 0) dest->sgn = !dest->sgn; return dest; } #if defined(__GNUG__) && !defined(NO_NRV) Integer sqrt(const Integer& x) { Integer r; int s = sign(x); if (s < 0) x.error("Attempted square root of negative Integer"); if (s != 0) { r >>= (lg(x) / 2); // get close Integer q; div(x, r, q); while (q < r) { r += q; r >>= 1; div(x, r, q); } } return r; } Integer lcm(const Integer& x, const Integer& y) { Integer r; if (!x.initialized() || !y.initialized()) x.error("operation on uninitialized Integer"); Integer g; if (sign(x) == 0 || sign(y) == 0) g = 1; else g = gcd(x, y); div(x, g, r); mul(r, y, r); return r; } #else Integer sqrt(const Integer& x) { Integer r(x); int s = sign(x); if (s < 0) x.error("Attempted square root of negative Integer"); if (s != 0) { r >>= (lg(x) / 2); // get close Integer q; div(x, r, q); while (q < r) { r += q; r >>= 1; div(x, r, q); } } return r; } Integer lcm(const Integer& x, const Integer& y) { Integer r; if (!x.initialized() || !y.initialized()) x.error("operation on uninitialized Integer"); Integer g; if (sign(x) == 0 || sign(y) == 0) g = 1; else g = gcd(x, y); div(x, g, r); mul(r, y, r); return r; } #endif IntegerRep* atoIntegerRep(const char* s, int base) { int sl = strlen(s); IntegerRep* r = Icalloc(0, (int) (sl * (lg(base) + 1) / I_SHIFT + 1)); if (s != 0) { char sgn; while (isspace(*s)) ++s; if (*s == '-') { sgn = I_NEGATIVE; s++; } else if (*s == '+') { sgn = I_POSITIVE; s++; } else sgn = I_POSITIVE; for (;;) { long digit; if (*s >= '0' && *s <= '9') digit = *s - '0'; else if (*s >= 'a' && *s <= 'z') digit = *s - 'a' + 10; else if (*s >= 'A' && *s <= 'Z') digit = *s - 'A' + 10; else break; if (digit >= base) break; r = multiply(r, base, r); r = add(r, 0, digit, r); ++s; } r->sgn = sgn; } return r; } std::string Itoa(const IntegerRep *x, int base, int width) { int fmtlen = (int) ((x->len + 1) * I_SHIFT / lg(base) + 4 + width); std::string fmtbase; for (int i = 0; i < fmtlen; i++) { fmtbase += " "; } return cvtItoa(x, fmtbase, fmtlen, base, 0, width, 0, ' ', 'X', 0); } std::ostream &operator<<(std::ostream &s, const Integer &y) { return s << Itoa(y.rep); } std::string cvtItoa(const IntegerRep *x, std::string fmt, int& fmtlen, int base, int showbase, int width, int align_right, char fillchar, char Xcase, int showpos) { char* e = const_cast(fmt.c_str()) + fmtlen - 1; char* s = e; *--s = 0; if (x->len == 0) *--s = '0'; else { IntegerRep* z = Icopy(0, x); // split division by base into two parts: // first divide by biggest power of base that fits in an unsigned short, // then use straight signed div/mods from there. // find power int bpower = 1; unsigned short b = base; unsigned short maxb = (unsigned short) (I_MAXNUM / base); while (b < maxb) { b *= base; ++bpower; } for(;;) { int rem = unscale(z->s, z->len, b, z->s); Icheck(z); if (z->len == 0) { while (rem != 0) { char ch = rem % base; rem /= base; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } if (!STATIC_IntegerRep(z)) delete z; break; } else { for (int i = 0; i < bpower; ++i) { char ch = rem % base; rem /= base; if (ch >= 10) ch += 'a' - 10; else ch += '0'; *--s = ch; } } } } if (base == 8 && showbase) *--s = '0'; else if (base == 16 && showbase) { *--s = Xcase; *--s = '0'; } if (x->sgn == I_NEGATIVE) *--s = '-'; else if (showpos) *--s = '+'; int w = (int) (e - s - 1); if (!align_right || w >= width) { while (w++ < width) *--s = fillchar; fmtlen = (int) (e - s - 1); return s; } else { char *p = const_cast(fmt.c_str()); #ifdef UNUSED int gap = (int) (s - p); #endif // UNUSED for (char* t = s; *t != 0; ++t, ++p) *p = *t; while (w++ < width) *p++ = fillchar; *p = 0; fmtlen = (int) (p - const_cast(fmt.c_str())); return fmt; } } std::istream &operator>>(std::istream &s, Integer& y) { char sgn = 0; char ch; y.rep = Icopy_zero(y.rep); do { s.get(ch); } while (isspace(ch)); s.unget(); while (s.get(ch)) { if (ch == '-') { if (sgn == 0) sgn = '-'; else break; } else { if (ch >= '0' && ch <= '9') { long digit = ch - '0'; y *= 10; y += digit; } else break; } } s.unget(); if (sgn == '-') y.negate(); return s; } int Integer::OK() const { if (rep != 0) { int l = rep->len; int s = rep->sgn; int v = l <= rep->sz || STATIC_IntegerRep(rep); // length within bounds v &= s == 0 || s == 1; // legal sign Icheck(rep); // and correctly adjusted v &= rep->len == l; v &= rep->sgn == s; if (v) return v; } error("invariant failure"); return 0; } void Integer::error(const char* msg) const { // (*lib_error_handler)("Integer", msg); // gerr << msg << '\n'; } // The following were moved from the header file to stop BC from squealing // endless quantities of warnings Integer::Integer() :rep(&_ZeroRep) {} Integer::Integer(IntegerRep* r) :rep(r) {} Integer::Integer(int y) :rep(Icopy_long(0, (long)y)) {} Integer::Integer(long y) :rep(Icopy_long(0, y)) {} Integer::Integer(unsigned long y) :rep(Icopy_ulong(0, y)) {} Integer::Integer(const Integer& y) :rep(Icopy(0, y.rep)) {} Integer::~Integer() { if (rep && !STATIC_IntegerRep(rep)) delete rep; } Integer &Integer::operator=(const Integer &y) { rep = Icopy(rep, y.rep); return *this; } Integer &Integer::operator=(long y) { rep = Icopy_long(rep, y); return *this; } int Integer::initialized() const { return rep != 0; } // procedural versions int compare(const Integer& x, const Integer& y) { return compare(x.rep, y.rep); } int ucompare(const Integer& x, const Integer& y) { return ucompare(x.rep, y.rep); } int compare(const Integer& x, long y) { return compare(x.rep, y); } int ucompare(const Integer& x, long y) { return ucompare(x.rep, y); } int compare(long x, const Integer& y) { return -compare(y.rep, x); } int ucompare(long x, const Integer& y) { return -ucompare(y.rep, x); } void add(const Integer& x, const Integer& y, Integer& dest) { dest.rep = add(x.rep, 0, y.rep, 0, dest.rep); } void sub(const Integer& x, const Integer& y, Integer& dest) { dest.rep = add(x.rep, 0, y.rep, 1, dest.rep); } void mul(const Integer& x, const Integer& y, Integer& dest) { dest.rep = multiply(x.rep, y.rep, dest.rep); } void div(const Integer& x, const Integer& y, Integer& dest) { dest.rep = div(x.rep, y.rep, dest.rep); } void mod(const Integer& x, const Integer& y, Integer& dest) { dest.rep = mod(x.rep, y.rep, dest.rep); } void lshift(const Integer& x, const Integer& y, Integer& dest) { dest.rep = lshift(x.rep, y.rep, 0, dest.rep); } void rshift(const Integer& x, const Integer& y, Integer& dest) { dest.rep = lshift(x.rep, y.rep, 1, dest.rep); } void pow(const Integer& x, const Integer& y, Integer& dest) { dest.rep = power(x.rep, Itolong(y.rep), dest.rep); // not incorrect } void add(const Integer& x, long y, Integer& dest) { dest.rep = add(x.rep, 0, y, dest.rep); } void sub(const Integer& x, long y, Integer& dest) { dest.rep = add(x.rep, 0, -y, dest.rep); } void mul(const Integer& x, long y, Integer& dest) { dest.rep = multiply(x.rep, y, dest.rep); } void div(const Integer& x, long y, Integer& dest) { dest.rep = div(x.rep, y, dest.rep); } void mod(const Integer& x, long y, Integer& dest) { dest.rep = mod(x.rep, y, dest.rep); } void lshift(const Integer& x, long y, Integer& dest) { dest.rep = lshift(x.rep, y, dest.rep); } void rshift(const Integer& x, long y, Integer& dest) { dest.rep = lshift(x.rep, -y, dest.rep); } void pow(const Integer& x, long y, Integer& dest) { dest.rep = power(x.rep, y, dest.rep); } void abs(const Integer& x, Integer& dest) { dest.rep = abs(x.rep, dest.rep); } void negate(const Integer& x, Integer& dest) { dest.rep = negate(x.rep, dest.rep); } void complement(const Integer& x, Integer& dest) { dest.rep = Compl(x.rep, dest.rep); } void add(long x, const Integer& y, Integer& dest) { dest.rep = add(y.rep, 0, x, dest.rep); } void sub(long x, const Integer& y, Integer& dest) { dest.rep = add(y.rep, 1, x, dest.rep); } void mul(long x, const Integer& y, Integer& dest) { dest.rep = multiply(y.rep, x, dest.rep); } // operator versions bool Integer::operator==(const Integer &y) const { return compare(*this, y) == 0; } bool Integer::operator==(long y) const { return compare(*this, y) == 0; } bool Integer::operator!=(const Integer &y) const { return compare(*this, y) != 0; } bool Integer::operator!=(long y) const { return compare(*this, y) != 0; } bool Integer::operator<(const Integer &y) const { return compare(*this, y) < 0; } bool Integer::operator<(long y) const { return compare(*this, y) < 0; } bool Integer::operator<=(const Integer &y) const { return compare(*this, y) <= 0; } bool Integer::operator<=(long y) const { return compare(*this, y) <= 0; } bool Integer::operator>(const Integer &y) const { return compare(*this, y) > 0; } bool Integer::operator>(long y) const { return compare(*this, y) > 0; } bool Integer::operator>=(const Integer &y) const { return compare(*this, y) >= 0; } bool Integer::operator>=(long y) const { return compare(*this, y) >= 0; } Integer &Integer::operator+=(const Integer &y) { add(*this, y, *this); return *this; } Integer &Integer::operator+=(long y) { add(*this, y, *this); return *this; } void Integer::operator ++ () { add(*this, 1, *this); } Integer &Integer::operator-=(const Integer &y) { sub(*this, y, *this); return *this; } Integer &Integer::operator-=(long y) { sub(*this, y, *this); return *this; } void Integer::operator -- () { add(*this, -1, *this); } Integer &Integer::operator*=(const Integer &y) { mul(*this, y, *this); return *this; } Integer &Integer::operator*=(long y) { mul(*this, y, *this); return *this; } Integer &Integer::operator/=(const Integer &y) { div(*this, y, *this); return *this; } Integer &Integer::operator/=(long y) { div(*this, y, *this); return *this; } Integer &Integer::operator<<=(const Integer &y) { lshift(*this, y, *this); return *this; } Integer &Integer::operator<<=(long y) { lshift(*this, y, *this); return *this; } Integer &Integer::operator>>=(const Integer &y) { rshift(*this, y, *this); return *this; } Integer &Integer::operator>>=(long y) { rshift(*this, y, *this); return *this; } void Integer::abs() { Gambit::abs(*this, *this); } void Integer::negate() { Gambit::negate(*this, *this); } int sign(const Integer& x) { return (x.rep->len == 0) ? 0 : ( (x.rep->sgn == 1) ? 1 : -1 ); } int even(const Integer& y) { return y.rep->len == 0 || !(y.rep->s[0] & 1); } int odd(const Integer& y) { return y.rep->len > 0 && (y.rep->s[0] & 1); } std::string Itoa(const Integer& y, int base, int width) { return Itoa(y.rep, base, width); } long lg(const Integer& x) { return lg(x.rep); } // constructive operations Integer Integer::operator+(const Integer &y) const { Integer r; add(*this, y, r); return r; } Integer Integer::operator+(long y) const { Integer r; add(*this, y, r); return r; } Integer Integer::operator-(const Integer &y) const { Integer r; sub(*this, y, r); return r; } Integer Integer::operator-(long y) const { Integer r; sub(*this, y, r); return r; } Integer Integer::operator*(const Integer &y) const { Integer r; mul(*this, y, r); return r; } Integer Integer::operator*(long y) const { Integer r; mul(*this, y, r); return r; } Integer sqr(const Integer& x) { Integer r; mul(x, x, r); return r; } Integer Integer::operator/(const Integer &y) const { Integer r; div(*this, y, r); return r; } Integer Integer::operator/(long y) const { Integer r; div(*this, y, r); return r; } Integer Integer::operator%(const Integer &y) const { Integer r; mod(*this, y, r); return r; } Integer Integer::operator%(long y) const { Integer r; mod(*this, y, r); return r; } Integer Integer::operator<<(const Integer &y) const { Integer r; lshift(*this, y, r); return r; } Integer Integer::operator<<(long y) const { Integer r; lshift(*this, y, r); return r; } Integer Integer::operator>>(const Integer &y) const { Integer r; rshift(*this, y, r); return r; } Integer Integer::operator>>(long y) const { Integer r; rshift(*this, y, r); return r; } Integer pow(const Integer& x, long y) { Integer r; pow(x, y, r); return r; } Integer Ipow(long x, long y) { Integer r(x); pow(r, y, r); return r; } Integer pow(const Integer& x, const Integer& y) { Integer r; pow(x, y, r); return r; } Integer abs(const Integer& x) { Integer r; abs(x, r); return r; } Integer Integer::operator-(void) const { Integer r; Gambit::negate(*this, r); return r; } Integer atoI(const char* s, int base) { Integer r; r.rep = atoIntegerRep(s, base); return r; } Integer gcd(const Integer& x, const Integer& y) { Integer r; r.rep = gcd(x.rep, y.rep); return r; } Integer &Integer::operator%=(const Integer &y) { *this = *this % y; // mod(*this, y, *this) doesn't work. return *this; } Integer &Integer::operator%=(long y) { *this = *this % y; // mod(*this, y, *this) doesn't work. return *this; } std::string ToText(const Integer &i) { return Itoa(i); } } gambit-0.2010.09.01/src/libgambit/integer.h0000644000076500007650000002361211435216101014765 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/integer.h // Interface to an arbitrary-length integer class // // The original copyright and license are included below. // /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of the GNU C++ Library. 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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef LIBGAMBIT_INTEGER_H #if defined(__GNUG__) && !defined(__APPLE_CC__) #pragma interface #endif #define LIBGAMBIT_INTEGER_H #include namespace Gambit { struct IntegerRep // internal Integer representations { unsigned short len; // current length unsigned short sz; // allocated space (0 means static). short sgn; // 1 means >= 0; 0 means < 0 unsigned short s[1]; // represented as ushort array starting here }; // True if REP is staticly (or manually) allocated, // and should not be deleted by an Integer destructor. #define STATIC_IntegerRep(rep) ((rep)->sz==0) extern IntegerRep* Ialloc(IntegerRep*, const unsigned short *, int, int, int); extern IntegerRep* Icalloc(IntegerRep*, int); extern IntegerRep* Icopy_ulong(IntegerRep*, unsigned long); extern IntegerRep* Icopy_long(IntegerRep*, long); extern IntegerRep* Icopy(IntegerRep*, const IntegerRep*); extern IntegerRep* Iresize(IntegerRep*, int); extern IntegerRep* add(const IntegerRep*, int, const IntegerRep*, int, IntegerRep*); extern IntegerRep* add(const IntegerRep*, int, long, IntegerRep*); extern IntegerRep* multiply(const IntegerRep*, const IntegerRep*, IntegerRep*); extern IntegerRep* multiply(const IntegerRep*, long, IntegerRep*); extern IntegerRep* lshift(const IntegerRep*, long, IntegerRep*); extern IntegerRep* lshift(const IntegerRep*, const IntegerRep*, int, IntegerRep*); extern IntegerRep* bitop(const IntegerRep*, const IntegerRep*, IntegerRep*, char); extern IntegerRep* bitop(const IntegerRep*, long, IntegerRep*, char); extern IntegerRep* power(const IntegerRep*, long, IntegerRep*); extern IntegerRep* div(const IntegerRep*, const IntegerRep*, IntegerRep*); extern IntegerRep* mod(const IntegerRep*, const IntegerRep*, IntegerRep*); extern IntegerRep* div(const IntegerRep*, long, IntegerRep*); extern IntegerRep* mod(const IntegerRep*, long, IntegerRep*); extern IntegerRep* Compl(const IntegerRep*, IntegerRep*); extern IntegerRep* abs(const IntegerRep*, IntegerRep*); extern IntegerRep* negate(const IntegerRep*, IntegerRep*); extern IntegerRep* gcd(const IntegerRep*, const IntegerRep* y); extern int compare(const IntegerRep*, const IntegerRep*); extern int compare(const IntegerRep*, long); extern int ucompare(const IntegerRep*, const IntegerRep*); extern int ucompare(const IntegerRep*, long); extern std::string Itoa(const IntegerRep* x, int base = 10, int width = 0); extern std::string cvtItoa(const IntegerRep* x, std::string fmt, int& fmtlen, int base, int showbase, int width, int align_right, char fillchar, char Xcase, int showpos); extern IntegerRep* atoIntegerRep(const char* s, int base = 10); extern long Itolong(const IntegerRep*); extern double Itodouble(const IntegerRep*); extern int Iislong(const IntegerRep*); extern int Iisdouble(const IntegerRep*); extern long lg(const IntegerRep*); class Integer { protected: IntegerRep *rep; public: /// @name Lifecycle //@{ Integer(void); Integer(int); Integer(long); Integer(unsigned long); Integer(IntegerRep *); Integer(const Integer &); ~Integer(); Integer &operator=(const Integer &); Integer &operator=(long); //@} /// @name Unary operations on self //@{ void operator ++ (); void operator -- (); void negate(); // negate in-place void abs(); // absolute-value in-place //@{ /// @name Comparison operators //@{ bool operator==(const Integer &) const; bool operator==(long) const; bool operator!=(const Integer &) const; bool operator!=(long) const; bool operator< (const Integer &) const; bool operator< (long) const; bool operator<=(const Integer &) const; bool operator<=(long) const; bool operator> (const Integer &) const; bool operator> (long) const; bool operator>=(const Integer &) const; bool operator>=(long) const; //@} /// @name Assignment-based operations //@{ Integer &operator+=(const Integer &); Integer &operator-=(const Integer &); Integer &operator*=(const Integer &); Integer &operator/=(const Integer &); Integer &operator%=(const Integer &); Integer &operator<<=(const Integer &); Integer &operator>>=(const Integer &); Integer &operator+=(long); Integer &operator-=(long); Integer &operator*=(long); Integer &operator/=(long); Integer &operator%=(long); Integer &operator<<=(long); Integer &operator>>=(long); //@} /// @name Operator overloading //@{ Integer operator-(void) const; Integer operator+(const Integer &) const; Integer operator+(long) const; Integer operator-(const Integer &) const; Integer operator-(long) const; Integer operator*(const Integer &) const; Integer operator*(long) const; Integer operator/(const Integer &) const; Integer operator/(long) const; Integer operator%(const Integer &) const; Integer operator%(long) const; Integer operator<<(const Integer &) const; Integer operator<<(long) const; Integer operator>>(const Integer &) const; Integer operator>>(long) const; //@} // builtin Integer functions that must be friends friend long lg (const Integer&); // floor log base 2 of abs(x) friend double ratio(const Integer& x, const Integer& y); // return x/y as a double friend Integer gcd(const Integer&, const Integer&); friend int even(const Integer&); // true if even friend int odd(const Integer&); // true if odd friend int sign(const Integer&); // returns -1, 0, +1 friend void setbit(Integer& x, long b); // set b'th bit of x friend void clearbit(Integer& x, long b); // clear b'th bit friend int testbit(const Integer& x, long b); // return b'th bit // procedural versions of operators friend void abs(const Integer& x, Integer& dest); friend void negate(const Integer& x, Integer& dest); friend void complement(const Integer& x, Integer& dest); friend int compare(const Integer&, const Integer&); friend int ucompare(const Integer&, const Integer&); friend void add(const Integer& x, const Integer& y, Integer& dest); friend void sub(const Integer& x, const Integer& y, Integer& dest); friend void mul(const Integer& x, const Integer& y, Integer& dest); friend void div(const Integer& x, const Integer& y, Integer& dest); friend void mod(const Integer& x, const Integer& y, Integer& dest); friend void divide(const Integer& x, const Integer& y, Integer& q, Integer& r); friend void lshift(const Integer& x, const Integer& y, Integer& dest); friend void rshift(const Integer& x, const Integer& y, Integer& dest); friend void pow(const Integer& x, const Integer& y, Integer& dest); friend int compare(const Integer&, long); friend int ucompare(const Integer&, long); friend void add(const Integer& x, long y, Integer& dest); friend void sub(const Integer& x, long y, Integer& dest); friend void mul(const Integer& x, long y, Integer& dest); friend void div(const Integer& x, long y, Integer& dest); friend void mod(const Integer& x, long y, Integer& dest); friend void divide(const Integer& x, long y, Integer& q, long& r); friend void lshift(const Integer& x, long y, Integer& dest); friend void rshift(const Integer& x, long y, Integer& dest); friend void pow(const Integer& x, long y, Integer& dest); friend int compare(long, const Integer&); friend int ucompare(long, const Integer&); friend void add(long x, const Integer& y, Integer& dest); friend void sub(long x, const Integer& y, Integer& dest); friend void mul(long x, const Integer& y, Integer& dest); // coercion & conversion int fits_in_long() const { return Iislong(rep); } int fits_in_double() const { return Iisdouble(rep); } long as_long() const { return Itolong(rep); } double as_double() const { return Itodouble(rep); } friend std::string Itoa(const Integer& x, int base = 10, int width = 0); friend Integer atoI(const char* s, int base = 10); friend std::istream &operator>>(std::istream &s, Integer& y); friend std::ostream &operator<<(std::ostream &s, const Integer& y); // error detection int initialized() const; void error(const char* msg) const; int OK() const; }; // (These are declared inline) Integer abs(const Integer&); // absolute value Integer sqr(const Integer&); // square Integer pow(const Integer& x, const Integer& y); Integer pow(const Integer& x, long y); Integer Ipow(long x, long y); // x to the y as Integer extern Integer sqrt(const Integer&); // floor of square root extern Integer lcm(const Integer& x, const Integer& y); // least common mult std::string ToText(const Integer &); } // end namespace Gambit #endif // LIBGAMBIT_INTEGER_H gambit-0.2010.09.01/src/libgambit/libgambit.h0000644000076500007650000000675111435216101015267 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/libgambit.h // Top-level include file for libgambit // // 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 LIBGAMBIT_H #define LIBGAMBIT_H #include #include #include #include namespace Gambit { inline void Epsilon(double &v, int i = 8) { v = ::pow(10.0, (double) -i); } template T min(const T &a, const T &b) { if (a < b) return a; else return b; } template T max(const T &a, const T &b) { if (a > b) return a; else return b; } template std::string ToText(const T &p_value) { std::ostringstream s; s << p_value; return s.str(); } inline std::string ToText(double p_value, int p_prec) { std::ostringstream s; s.setf(std::ios::fixed); s << std::setprecision(p_prec) << p_value; return s.str(); } inline double abs(double a) { return (a >= 0.0) ? a : -a; } //======================================================================== // Exception classes //======================================================================== /// A base class for all exceptions class Exception { public: virtual ~Exception() { } virtual std::string GetDescription(void) const = 0; }; /// Exception thrown on out-of-range index class IndexException : public Exception { public: virtual ~IndexException() { } std::string GetDescription(void) const { return "Index out of range"; } }; /// Exception thrown on invalid index ranges class RangeException : public Exception { public: virtual ~RangeException() { } std::string GetDescription(void) const { return "Invalid index range"; } }; /// Exception thrown on dimension mismatches class DimensionException : public Exception { public: virtual ~DimensionException() { } std::string GetDescription(void) const { return "Mismatched dimensions"; } }; /// Exception thrown on invalid value class ValueException : public Exception { public: virtual ~ValueException() { } std::string GetDescription(void) const { return "Invalid value"; } }; /// Exception thrown on attempted division by zero class ZeroDivideException : public Exception { public: virtual ~ZeroDivideException() { } std::string GetDescription(void) const { return "Attmpted division by zero"; } }; } // end namespace Gambit inline int sign(const double &a) { if (a > 0.0) return 1; if (a < 0.0) return -1; return 0; } inline double pow(double x, long y) { return pow(x, (double) y); } #include "array.h" #include "list.h" #include "recarray.h" #include "vector.h" #include "matrix.h" #include "map.h" #include "rational.h" #include "game.h" #include "behavspt.h" #include "behav.h" #include "behavitr.h" #include "stratspt.h" #include "mixed.h" #include "stratitr.h" #endif // LIBGAMBIT_H gambit-0.2010.09.01/src/libgambit/list.h0000644000076500007650000001700511435216101014302 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/list.h // A generic (doubly) linked-list container class // // 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 LIBGAMBIT_LIST_H #define LIBGAMBIT_LIST_H namespace Gambit { template class List { protected: class Node { public: T m_data; Node *m_prev, *m_next; // CONSTRUCTOR Node(const T &p_data, Node *p_prev, Node *p_next); }; int m_length; Node *m_head, *m_tail; int m_currentIndex; Node *m_currentNode; int InsertAt(const T &t, int where); public: List(void); List(const List &); virtual ~List(); List &operator=(const List &); bool operator==(const List &b) const; bool operator!=(const List &b) const; const T &operator[](int) const; T &operator[](int); List operator+(const List& b) const; List& operator+=(const List& b); virtual int Append(const T &); int Insert(const T &, int); virtual T Remove(int); int Find(const T &) const; bool Contains(const T &t) const; int Length(void) const { return m_length; } }; //-------------------------------------------------------------------------- // Node: Member function implementations //-------------------------------------------------------------------------- template List::Node::Node(const T &p_data, typename List::Node *p_prev, typename List::Node *p_next) : m_data(p_data), m_prev(p_prev), m_next(p_next) { } //-------------------------------------------------------------------------- // List: Member function implementations //-------------------------------------------------------------------------- template List::List(void) : m_length(0), m_head(0), m_tail(0), m_currentIndex(0), m_currentNode(0) { } template List::List(const List &b) : m_length(b.m_length) { if (m_length) { Node *n = b.m_head; m_head = new Node(n->m_data, 0, 0); n = n->m_next; m_tail = m_head; while (n) { m_tail->m_next = new Node(n->m_data, m_tail, 0); n = n->m_next; m_tail = m_tail->m_next; } m_currentIndex = 1; m_currentNode = m_head; } else { m_head = m_tail = 0; m_currentIndex = 0; m_currentNode = 0; } } template List::~List() { Node *n = m_head; while (n) { Node *m_next = n->m_next; delete n; n = m_next; } } template int List::InsertAt(const T &t, int num) { if (num < 1 || num > m_length + 1) throw IndexException(); if (!m_length) { m_head = m_tail = new Node(t, 0, 0); m_length = 1; m_currentIndex = 1; m_currentNode = m_head; return m_length; } Node *n; int i; if( num <= 1 ) { n = new Node(t, 0, m_head); m_head->m_prev = n; m_currentNode = m_head = n; m_currentIndex = 1; } else if( num >= m_length + 1) { n = new Node(t, m_tail, 0); m_tail->m_next = n; m_currentNode = m_tail = n; m_currentIndex = m_length + 1; } else { if( num < m_currentIndex ) for (i = m_currentIndex, n = m_currentNode; i > num; i--, n = n->m_prev); else for (i = m_currentIndex, n = m_currentNode; i < num; i++, n = n->m_next); n = new Node(t, n->m_prev, n); m_currentNode = n->m_prev->m_next = n->m_next->m_prev = n; m_currentIndex = num; } m_length++; return num; } //--------------------- visible functions ------------------------ template List &List::operator=(const List &b) { if (this != &b) { Node *n = m_head; while (n) { Node *m_next = n->m_next; delete n; n = m_next; } m_length = b.m_length; m_currentIndex = b.m_currentIndex; if (m_length) { Node *n = b.m_head; m_head = new Node(n->m_data, 0, 0); if (b.m_currentNode == n) m_currentNode = m_head; n = n->m_next; m_tail = m_head; while (n) { m_tail->m_next = new Node(n->m_data, m_tail, 0); if (b.m_currentNode == n) m_currentNode = m_tail->m_next; n = n->m_next; m_tail = m_tail->m_next; } } else m_head = m_tail = 0; } return *this; } template bool List::operator==(const List &b) const { if (m_length != b.m_length) return false; for (Node *m = m_head, *n = b.m_head; m; m = m->m_next, n = n->m_next) if (m->m_data != n->m_data) return false; return true; } template bool List::operator!=(const List &b) const { return !(*this == b); } template const T &List::operator[](int num) const { if (num < 1 || num > m_length) throw IndexException(); int i; Node *n; if( num < m_currentIndex ) for (i = m_currentIndex, n = m_currentNode; i > num; i--, n = n->m_prev); else for (i = m_currentIndex, n = m_currentNode; i < num; i++, n = n->m_next); return n->m_data; } template T &List::operator[](int num) { if (num < 1 || num > m_length) throw IndexException(); Node *n; int i; if( num < m_currentIndex ) for (i = m_currentIndex, n = m_currentNode; i > num; i--, n = n->m_prev); else for (i = m_currentIndex, n = m_currentNode; i < num; i++, n = n->m_next); m_currentIndex = i; m_currentNode = n; return n->m_data; } template List List::operator+(const List &b) const { List result(*this); Node *n = b.m_head; while (n) { result.Append(n->data); n = n->m_next; } return result; } template List &List::operator+=(const List &b) { Node *n = b.m_head; while (n) { Append(n->m_data); n = n->m_next; } return *this; } template int List::Append(const T &t) { return InsertAt(t, m_length + 1); } template int List::Insert(const T &t, int n) { return InsertAt(t, (n < 1) ? 1 : ((n > m_length + 1) ? m_length + 1 : n)); } template T List::Remove(int num) { if (num < 1 || num > m_length) throw IndexException(); Node *n; int i; if( num < m_currentIndex ) for (i = m_currentIndex, n = m_currentNode; i > num; i--, n = n->m_prev); else for (i = m_currentIndex, n = m_currentNode; i < num; i++, n = n->m_next); if (n->m_prev) n->m_prev->m_next = n->m_next; else m_head = n->m_next; if (n->m_next) n->m_next->m_prev = n->m_prev; else m_tail = n->m_prev; m_length--; m_currentIndex = i; m_currentNode = n->m_next; if (m_currentIndex > m_length) { m_currentIndex = m_length; m_currentNode = m_tail; } T ret = n->m_data; delete n; return ret; } template int List::Find(const T &t) const { if (m_length == 0) return 0; Node *n = m_head; for (int i = 1; n; i++, n = n->m_next) if (n->m_data == t) return i; return 0; } template bool List::Contains(const T &t) const { return (Find(t) != 0); } } #endif // LIBGAMBIT_LIST_H gambit-0.2010.09.01/src/libgambit/map.h0000644000076500007650000002450111435216101014103 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/map.h // Declaration of map container types // // 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 LIBGAMBIT_MAP_H #define LIBGAMBIT_MAP_H namespace Gambit { template class MapBase { protected: int length; T _default; K *keys; T *values; // // Insert a new key-value pair at a location in the arrays. // T &Insert(const K &key, int where, const T &value); // // Remove the key-value pair at a location in the arrays, and return the // value which was removed. // T Delete(int where); public: // // This is the basic map constructor. It initializes the map to be the // empty map with no relations defined. // MapBase(const T &d); // // Construct a map to have the same set of relations as another map. // MapBase(const MapBase &); // // This is the map destructor. It deletes all allocated memory, and calls // the destructors for the keys and values which remain in the map at the // time of its deallocation. // virtual ~MapBase(); // // These implement the mapping function which maps a key to a value. If // the map from a key to a value is not defined, a mapping will be defined // from the key to the default value. The IsDefined() member can be used // to determine whether a mapping is defined. // // If the mapping is not defined for the key in the const map case, // the mapping returns the default value and no entry is created in // the map for that key. //+grp virtual T &operator()(const K &key) = 0; virtual T operator()(const K &key) const = 0; //-grp virtual T &Lookup(const K &key) = 0; // // These are the equality and assignment operators for this and all derived // classes. //+grp int operator==(const MapBase &M) const; int operator!=(const MapBase &M) const; MapBase &operator=(const MapBase &M); //-grp // // Returns the default value for the map //+grp T &Default(void); const T &Default(void) const; //-grp // // Returns the number of mappings defined in the map // int Length(void) const; // // Returns nonzero if the key has a mapping defined in the map // virtual int IsDefined(const K &key) const = 0; // // These member functions implement adding and removing mapping from the map //+grp virtual void Define(const K &key, const T &value) = 0; virtual T Remove(const K &key) = 0; //-grp }; // // // // The Map is an ordered map. That is, the index class has all the // usual ordering operators defined upon it (==, !=, <, <=, >, >=). These // are used to sort the map by keys, thus making search-type operations // logarithmic instead of linear. This is a particularly large improvement // when using keys which are costly to compare // template class Map : public MapBase { private: int Locate(const K &key) const; public: // // Construct an ordered map with no mappings and the given default value. // Map(const T &d); // // Construct an ordered map with the same key-value mappings as another // ordered map. // Map(const Map &m); virtual ~Map(); // // These implement the mapping function which maps a key to a value. If // the map from a key to a value is not defined, a mapping will be defined // from the key to the default value. The IsDefined() member can be used // to determine whether a mapping is defined. // // If the mapping is not defined for the key in the const map case, // the mapping returns the default value and no entry is created in // the map for that key. //+grp T &operator()(const K &key); T operator()(const K &key) const; //-grp T &Lookup(const K &key); // // Return nonzero exactly when the key has a defined mapping in the map // int IsDefined(const K &key) const; // // Define a new key-value relation. If the key already exists in the map, // the new value overwrites the old value; otherwise, a new relation is // created. // void Define(const K &key, const T &value); // // Remove the mapping for a key from the relation, and return the value // to which the key was formerly mapped. If the key does not have a defined // mapping, has no effect on the contents of the map, and returns the // T Remove(const K &key); }; //------------------------------------------------------------------------- // MapBase member functions //------------------------------------------------------------------------- template MapBase::MapBase(const T &d) : length(0), _default(d), keys(0), values(0) { } template MapBase::MapBase(const MapBase &m) : length(m.length), _default(m._default) { keys = new K[length]; values = new T[length]; for (int i = 0; i < length; i++) { keys[i] = m.keys[i]; values[i] = m.values[i]; } } template MapBase::~MapBase() { delete [] keys; delete [] values; } template int MapBase::operator==(const MapBase &M) const { if (length != M.length) return 0; for (int i = 0; i < length; i++) if (keys[i] != M.keys[i] || values[i] != M.values[i]) return 0; return (_default == M._default); } template int MapBase::operator!=(const MapBase &M) const { return !(*this == M); } template MapBase &MapBase::operator=(const MapBase &M) { if (this != &M) { length = M.length; if (keys) delete [] keys; if (values) delete [] values; if (M.length) { keys = new K[M.length]; values = new T[M.length]; for (int i = 0; i < length; i++) { keys[i] = M.keys[i]; values[i] = M.values[i]; } } else { keys = 0; values = 0; } _default = M._default; } return *this; } template T &MapBase::Insert(const K &key, int entry, const T &value) { K *new_keys = new K[length + 1]; T *new_values = new T[length + 1]; if (length > 0) { int i; for (i = 0; i < entry; i++) { new_keys[i] = keys[i]; new_values[i] = values[i]; } for (i++; i <= length; i++) { new_keys[i] = keys[i - 1]; new_values[i] = values[i - 1]; } } new_keys[entry] = key; new_values[entry] = value; if (length > 0) { delete [] keys; delete [] values; } keys = new_keys; values = new_values; length++; return values[entry]; } template T MapBase::Delete(int where) { if (length == 1) { T ret = values[0]; delete [] keys; delete [] values; keys = 0; values = 0; length = 0; return ret; } T ret = values[where]; K *new_keys = new K[length - 1]; T *new_values = new T[length - 1]; int i; for (i = 0; i < where; i++) { new_keys[i] = keys[i]; new_values[i] = values[i]; } for (i++; i < length; i++) { new_keys[i - 1] = keys[i]; new_values[i - 1] = values[i]; } delete [] keys; delete [] values; keys = new_keys; values = new_values; length--; return ret; } template T &MapBase::Default(void) { return _default; } template const T &MapBase::Default(void) const { return _default; } template int MapBase::Length(void) const { return length; } //------------------------------------------------------------------------- // Map member functions //------------------------------------------------------------------------- template Map::Map(const T &d) : MapBase(d) { } template Map::Map(const Map &m) : MapBase(m) { } template Map::~Map() { } template int Map::Locate(const K &key) const { int low = 0, high = this->length - 1, mid = 0; while (low <= high) { mid = (low + high) / 2; if (key < this->keys[mid]) high = mid - 1; else if (key > this->keys[mid]) low = mid + 1; else return mid; } return mid; } template T &Map::operator()(const K &key) { int where = Locate(key); if (this->length > 0 && this->keys[where] == key) return this->values[where]; else return Insert(key, ((key < this->keys[where]) ? where : where + 1), this->_default); } template T &Map::Lookup(const K &key) { int where = Locate(key); if (this->length > 0 && this->keys[where] == key) return this->values[where]; else return Insert(key, ((key < this->keys[where]) ? where : where + 1), this->_default); } template T Map::operator()(const K &key) const { int where = Locate(key); if (this->length > 0 && this->keys[where] == key) return this->values[where]; else return this->_default; } template int Map::IsDefined(const K &key) const { if (this->length == 0) return 0; return (this->keys[Locate(key)] == key); } template void Map::Define(const K &key, const T &value) { if (this->length == 0) { Insert(key, 0, value); return; } int where = Locate(key); if (this->keys[where] == key) this->values[where] = value; else Insert(key, ((key < this->keys[where]) ? where : where + 1), value); } template T Map::Remove(const K &key) { int where = Locate(key); if (where >= 0) return this->Delete(where); return this->_default; } } // end namespace Gambit #endif // LIBGAMBIT_MAP_H gambit-0.2010.09.01/src/libgambit/matrix.cc0000644000076500007650000000274111435216101014772 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/matrix.cc // Instantiation of common matrix types // // 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 "libgambit.h" #include "matrix.imp" using namespace Gambit; template class Matrix; template class Matrix; template class Matrix; template class Matrix; template Vector Gambit::operator*(const Vector &, const Matrix &); template Vector Gambit::operator*(const Vector &, const Matrix &); template Vector Gambit::operator*(const Vector &, const Matrix &); template Vector Gambit::operator*(const Vector &, const Matrix &); gambit-0.2010.09.01/src/libgambit/matrix.h0000644000076500007650000000576411435216101014644 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/matrix.h // Interface to a matrix class // // 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 LIBGAMBIT_MATRIX_H #define LIBGAMBIT_MATRIX_H #include "recarray.h" #include "vector.h" namespace Gambit { template Vector operator*(const Vector &, const Matrix &); template class Matrix : public RectArray { friend Vector operator*<>(const Vector &, const Matrix &); public: /// @name Lifecycle //@{ Matrix(void); Matrix(unsigned int rows, unsigned int cols); Matrix(unsigned int rows, unsigned int cols, int minrows); Matrix(int rl, int rh, int cl, int ch); Matrix(const Matrix &); virtual ~Matrix(); Matrix &operator=(const Matrix &); Matrix &operator=(const T &); //@} /// @name Extracting rows and columns //@{ Vector Row(int) const; Vector Column(int) const; //@} /// @name Comparison operators //@{ bool operator==(const Matrix &) const; bool operator!=(const Matrix &) const; bool operator==(const T &) const; bool operator!=(const T &) const; //@} /// @name Additive operators //@{ Matrix operator+(const Matrix &) const; Matrix operator-(const Matrix &) const; Matrix &operator+=(const Matrix &); Matrix &operator-=(const Matrix &); Matrix operator-(void); //@} /// @name Multiplicative operators //@{ /// "in-place" column multiply void CMultiply(const Vector &, Vector &) const; /// "in-place" row (transposed) multiply void RMultiply(const Vector &, Vector &) const; Matrix operator*(const Matrix &) const; Vector operator*(const Vector &) const; Matrix operator*(const T &) const; Matrix &operator*=(const Matrix &); Matrix &operator*=(const T &); Matrix operator/(const T &) const; Matrix &operator/=(const T &); /// Kronecker product Matrix operator&(const Matrix &) const; //@ /// @name Other operations //@{ Matrix Transpose(void) const; /// Set matrix to identity matrix void MakeIdent(void); void Pivot(int, int); //@} }; template Vector operator*(const Vector &, const Matrix &); } // end namespace Gambit #endif // LIBGAMBIT_MATRIX_H gambit-0.2010.09.01/src/libgambit/matrix.imp0000644000076500007650000003121511435216101015170 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/matrix.imp // Implementation of matrix method functions // // 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 "matrix.h" namespace Gambit { //------------------------------------------------------------------------- // Matrix: Constructors, destructors, constructive operators //------------------------------------------------------------------------- template Matrix::Matrix(void) { } template Matrix::Matrix(unsigned int rows, unsigned int cols) : RectArray(rows, cols) { } template Matrix::Matrix(unsigned int rows, unsigned int cols, int minrows) : RectArray(minrows, minrows + rows - 1, 1, cols) { } template Matrix::Matrix(int rl, int rh, int cl, int ch) : RectArray(rl, rh, cl, ch) { } template Matrix::Matrix(const Matrix &M) : RectArray(M) { } template Matrix::~Matrix() { } template Matrix &Matrix::operator=(const Matrix &M) { RectArray::operator=(M); return *this; } template Matrix &Matrix::operator=(const T &c) { for (int i = this->minrow; i <= this->maxrow; i++) for (int j = this->mincol; j <= this->maxcol; j++) (*this)(i, j) = c; return *this; } template Matrix Matrix::operator-(void) { Matrix tmp(this->minrow, this->maxrow, this->mincol, this->maxcol); for (int i = this->minrow; i <= this->maxrow; i++) for (int j = this->mincol; j <= this->maxcol; j++) tmp(i,j)= -(*this)(i,j); return tmp; } //------------------------------------------------------------------------- // Matrix: Additive operators //------------------------------------------------------------------------- template Matrix Matrix::operator+(const Matrix &M) const { if (!CheckBounds(M)) { throw DimensionException(); } Matrix tmp(this->minrow, this->maxrow, this->mincol, this->maxcol); for (int i = this->minrow; i <= this->maxrow; i++) { T *src1 = this->data[i] + this->mincol; T *src2 = M.data[i] + this->mincol; T *dst = tmp.data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) *(dst++)= *(src1++) + *(src2++); //assert((dst - 1) == tmp.data[i] + this->maxcol ); } return tmp; } template Matrix Matrix::operator-(const Matrix &M) const { if (!CheckBounds(M)) { throw DimensionException(); } Matrix tmp(this->minrow, this->maxrow, this->mincol, this->maxcol); for (int i = this->minrow; i <= this->maxrow; i++) { T *src1 = this->data[i] + this->mincol; T *src2 = M.data[i] + this->mincol; T *dst = tmp.data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) *(dst++)= *(src1++) - *(src2++); //assert((dst - 1) == tmp.data[i] + this->maxcol); } return tmp; } template Matrix &Matrix::operator+=(const Matrix &M) { if (!CheckBounds(M)) { throw DimensionException(); } for (int i = this->minrow; i <= this->maxrow; i++) { T *src = M.data[i] + this->mincol; T *dst = this->data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) *(dst++) += *(src++); } return (*this); } template Matrix &Matrix::operator-=(const Matrix &M) { if (!CheckBounds(M)) { throw DimensionException(); } for (int i = this->minrow; i <= this->maxrow; i++) { T *src = M.data[i] + this->mincol; T *dst = this->data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) *(dst++) -= *(src++); //assert((dst - 1) == this->data[i] + this->maxcol); } return (*this); } //------------------------------------------------------------------------- // Matrix: Multiplicative operators //------------------------------------------------------------------------- template void Matrix::CMultiply(const Vector &in, Vector &out) const { if (!CheckRow(in) || !CheckColumn(out)) { throw DimensionException(); } for (int i = this->minrow; i <= this->maxrow; i++) { T sum = (T)0; T *src1 = this->data[i] + this->mincol; T *src2 = in.data + this->mincol; int j = this->maxcol - this->mincol +1; while (j--) sum += *(src1++) * *(src2++); out[i] = sum; } } template Matrix Matrix::operator*(const Matrix &M) const { if (this->mincol != M.minrow || this->maxcol != M.maxrow) { throw DimensionException(); } Matrix tmp(this->minrow, this->maxrow, M.mincol, M.maxcol); Vector column(M.minrow, M.maxrow); Vector result(this->minrow, this->maxrow); for (int j = M.mincol; j <= M.maxcol; j++) { M.GetColumn(j, column); CMultiply(column, result); tmp.SetColumn(j, result); } return tmp; } template Vector Matrix::operator*(const Vector &v) const { if (!CheckRow(v)) { throw DimensionException(); } Vector tmp(this->minrow, this->maxrow); CMultiply(v, tmp); return tmp; } template void Matrix::RMultiply(const Vector &in, Vector &out) const { if (!CheckColumn(in) || !CheckRow(out)) { throw DimensionException(); } out= (T)0; for (int i = this->minrow; i <= this->maxrow; i++) { T k = in[i]; T *src = this->data[i] + this->mincol; T *dst = out.data + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) *(dst++) += *(src++) * k; //assert(src - 1 == this->data[i] + this->maxcol); } } // transposed (row) vector*matrix multiplication operator // a friend function of Matrix template Vector operator*(const Vector &v, const Matrix &M) { if (!M.CheckColumn(v)) { throw DimensionException(); } Vector tmp(M.MinCol(), M.MaxCol()); M.RMultiply(v, tmp); return tmp; } template Matrix Matrix::operator*(const T &s) const { Matrix tmp(this->minrow, this->maxrow, this->mincol, this->maxcol); for (int i = this->minrow; i <= this->maxrow; i++) { T *src = this->data[i] + this->mincol; T *dst = tmp.data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) *(dst++) = *(src++) * s; //assert((src - 1) == this->data[i] + this->maxcol); } return tmp; } // in-place multiplication by square matrix template Matrix &Matrix::operator*=(const Matrix &M) { if (this->mincol != M.minrow || this->maxcol != M.maxrow) { throw DimensionException(); } if (M.minrow != M.mincol || M.maxrow != M.maxcol) { throw DimensionException(); } Vector row(this->mincol, this->maxcol); Vector result(this->mincol, this->maxcol); for (int i = this->minrow; i <= this->maxrow; i++) { GetRow(i, row); M.RMultiply(row, result); SetRow(i, result); } return (*this); } template Matrix &Matrix::operator*=(const T &s) { for (int i = this->minrow; i <= this->maxrow; i++) { T *dst = this->data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) *(dst++) *= s; //assert((dst - 1) == this->data[i] + this->maxcol); } return (*this); } template Matrix Matrix::operator/(const T &s) const { if (s == (T) 0) throw ZeroDivideException(); Matrix tmp(this->minrow, this->maxrow, this->mincol, this->maxcol); for (int i = this->minrow; i <= this->maxrow; i++) { T *src = this->data[i] + this->mincol; T *dst = tmp.data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) *(dst++) = *(src++) / s; //assert((src - 1) == this->data[i] + this->maxcol); } return tmp; } template Matrix &Matrix::operator/=(const T &s) { if (s == (T) 0) throw ZeroDivideException(); for (int i = this->minrow; i <= this->maxrow; i++) { T *dst = this->data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) *(dst++) /= s; //assert((dst - 1) == this->data[i] + this->maxcol); } return (*this); } //------------------------------------------------------------------------- // Matrix: Kronecker Product //------------------------------------------------------------------------- template Matrix Matrix::operator&(const Matrix &M) const { Matrix tmp(1, (this->maxrow - this->minrow + 1)*(M.maxrow - M.minrow + 1), 1, (this->maxcol - this->mincol + 1)*(M.maxcol - M.mincol + 1)); for (int i = 0; i <= this->maxrow - this->minrow; i++) for (int j = 1; j <= M.maxrow - M.minrow + 1; j++) for (int k = 0; k <= this->maxcol - this->mincol; k++) for (int l = 1; l <= M.maxcol - M.mincol + 1; l++) tmp((M.maxrow - M.minrow + 1)*i + j, (M.maxcol - M.mincol + 1)*k + l) = (*this)(i+this->minrow, k+this->mincol) * M(j+M.minrow-1,l+M.mincol-1); return tmp; } //------------------------------------------------------------------------- // Matrix: Transpose //------------------------------------------------------------------------- template Matrix Matrix::Transpose() const { Matrix tmp(this->mincol, this->maxcol, this->minrow, this->maxrow); for (int i = this->minrow; i <= this->maxrow; i++) for (int j = this->mincol; j <= this->maxcol; j++) tmp(j,i) = (*this)(i,j); return tmp; } //------------------------------------------------------------------------- // Matrix: Comparison operators //------------------------------------------------------------------------- template bool Matrix::operator==(const Matrix &M) const { if (!CheckBounds(M)) { throw DimensionException(); } for (int i = this->minrow; i <= this->maxrow; i++) { // inner loop T *src1 = M.data[i] + this->mincol; T *src2 = this->data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) if(*(src1++) != *(src2++)) return false; //assert(src1 - 1 == M.data[i] + this->maxcol); } return true; } template bool Matrix::operator!=(const Matrix &M) const { return !(*this == M); } template bool Matrix::operator==(const T &s) const { for (int i = this->minrow; i <= this->maxrow; i++) { T *src = this->data[i] + this->mincol; int j = this->maxcol - this->mincol + 1; while (j--) if (*(src++) != s) return false; //assert(src - 1 == this->data[i] + this->maxcol); } return true; } template bool Matrix::operator!=(const T &s) const { return !(*this == s); } // Information template Vector Matrix::Row(int i) const { Vector answer(this->mincol, this->maxcol); for (int j = this->mincol; j <= this->maxcol; j++) answer[j] = (*this)(i,j); return answer; } template Vector Matrix::Column(int j) const { Vector answer(this->minrow, this->maxrow); for (int i = this->minrow; i <= this->maxrow; i++) answer[i] = (*this)(i,j); return answer; } // more complex functions template void Matrix::MakeIdent(void) { for (int i = this->minrow; i <= this->maxrow; i++) for (int j = this->mincol; j <= this->maxcol; j++) { if (i == j) (*this)(i,j) = (T) 1; else (*this)(i,j)=(T) 0; } } template void Matrix::Pivot(int row, int col) { if (!this->CheckRow(row) || !this->CheckColumn(col)) { throw IndexException(); } if (this->data[row][col] == (T) 0) throw ZeroDivideException(); T mult= (T)1/this->data[row][col]; for(int j=this->mincol; j<=this->maxcol; j++) this->data[row][j]*= mult; for(int i=this->minrow; i<=this->maxrow; i++) { if(i!=row) { mult= this->data[i][col]; // inner loop T* src= this->data[row] + this->mincol; T* dst= this->data[i] + this->mincol; int j= this->maxcol-this->mincol+1; while( j-- ) *(dst++)-= *(src++) * mult; //assert( dst-1 == this->data[i] + this->maxcol ); // debug // end inner loop } } } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/mixed.cc0000644000076500007650000000210111435216101014562 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/mixed.cc // Instantiation of template classes used in normal forms // // 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 "libgambit.h" #include "mixed.imp" template class Gambit::MixedStrategyProfile; template class Gambit::MixedStrategyProfile; gambit-0.2010.09.01/src/libgambit/mixed.h0000644000076500007650000001225411441446351014447 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/mixed.h // Declaration of mixed strategy profile classes // // 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 LIBGAMBIT_MIXED_H #define LIBGAMBIT_MIXED_H #include "vector.h" namespace Gambit { /// \brief A probability distribtion over strategies in a game /// /// A probability distribution over strategies, such that each player /// independently chooses from among his strategies with specified /// probabilities. template class MixedStrategyProfile : public Vector { private: StrategySupport support; /// @name Private recursive payoff functions //@{ /// Recursive computation of payoff to player pl T GetPayoff(int pl, int index, int i) const; /// Recursive computation of payoff derivative void GetPayoffDeriv(int pl, int const_pl, int cur_pl, long index, const T &prob, T &value) const; /// Recursive computation of payoff second derivative void GetPayoffDeriv(int pl, int const_pl1, int const_pl2, int cur_pl, long index, const T &prob, T &value) const; //@} public: /// @name Lifecycle //@{ /// Construct a mixed strategy profile at the centroid on the support MixedStrategyProfile(const StrategySupport &); /// Convert a behavior strategy profile to a mixed strategy profile MixedStrategyProfile(const MixedBehavProfile &); //@} /// @name Operator overloading //@{ /// Test for the equality of two profiles bool operator==(const MixedStrategyProfile &p_profile) const { return (support == p_profile.support && Vector::operator==(p_profile)); } /// Test for the inequality of two profiles bool operator!=(const MixedStrategyProfile &p_profile) const { return (support != p_profile.support || Vector::operator!=(p_profile)); } /// Vector-style access to probabilities const T &operator[](int i) const { return Array::operator[](i); } /// Vector-style access to probabilities T &operator[](int i) { return Array::operator[](i); } /// Returns the probability the strategy is played const T &operator[](const GameStrategy &p_strategy) const { return Array::operator[](support.m_profileIndex[p_strategy->GetId()]); } /// Returns the probability the strategy is played T &operator[](const GameStrategy &p_strategy) { return Array::operator[](support.m_profileIndex[p_strategy->GetId()]); } //@} /// @name General data access //@{ /// Returns the game on which the profile is defined Game GetGame(void) const { return support.GetGame(); } /// Returns the support on which the profile is defined const StrategySupport &GetSupport(void) const { return support; } /// Sets all strategies for each player to equal probabilities void SetCentroid(void); /// Returns the total number of strategies in the profile int MixedProfileLength(void) const { return Array::Length(); } /// Converts the profile to one on the full support of the game MixedStrategyProfile ToFullSupport(void) const; //@} /// @name Computation of interesting quantities //@{ /// Computes the payoff of the profile to player 'pl' T GetPayoff(int pl) const; /// Computes the payoff of the profile to the player T GetPayoff(const GamePlayer &p_player) const { return GetPayoff(p_player->GetNumber()); } /// \brief Computes the derivative of the player's payoff /// /// Computes the derivative of the payoff to the player with respect /// to the probability the strategy is played T GetPayoffDeriv(int pl, const GameStrategy &) const; /// \brief Computes the second derivative of the player's payoff /// /// Computes the second derivative of the payoff to the player, /// with respect to the probabilities with which the strategies are played T GetPayoffDeriv(int pl, const GameStrategy &, const GameStrategy &) const; /// Computes the payoff to playing the pure strategy against the profile T GetStrategyValue(const GameStrategy &p_strategy) const { return GetPayoffDeriv(p_strategy->GetPlayer()->GetNumber(), p_strategy); } /// \brief Computes the Lyapunov value of the profile /// /// Computes the Lyapunov value of the profile. This is a nonnegative /// value which is zero exactly at Nash equilibria. This version /// implements a positive penalty for profiles which are not on the /// simplotope (useful for penalty-function minimization methods). T GetLiapValue(void) const; //@} }; } // end namespace Gambit #endif // LIBGAMBIT_MIXED_H gambit-0.2010.09.01/src/libgambit/mixed.imp0000644000076500007650000002034611441446351015006 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/mixed.imp // Implementation of mixed strategy profile classes // // 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 "game.h" #include "mixed.h" namespace Gambit { //======================================================================== // MixedStrategyProfile: Lifecycle //======================================================================== template MixedStrategyProfile::MixedStrategyProfile(const StrategySupport &p_support) : Vector(p_support.MixedProfileLength()), support(p_support) { SetCentroid(); } template MixedStrategyProfile::MixedStrategyProfile(const MixedBehavProfile &p_profile) : Vector(p_profile.GetGame()->MixedProfileLength()), support(p_profile.GetGame()) { Game efg = p_profile.GetGame(); for (int pl = 1; pl <= support.GetGame()->NumPlayers(); pl++) { for (int st = 1; st <= support.GetGame()->GetPlayer(pl)->NumStrategies(); st++) { T prob = (T) 1; for (int iset = 1; iset <= efg->GetPlayer(pl)->NumInfosets(); iset++) { if (efg->m_players[pl]->m_strategies[st]->m_behav[iset] > 0) prob *= p_profile(pl, iset, efg->m_players[pl]->m_strategies[st]->m_behav[iset]); } (*this)[support.GetGame()->GetPlayer(pl)->GetStrategy(st)] = prob; } } } //======================================================================== // MixedStrategyProfile: General data access //======================================================================== template void MixedStrategyProfile::SetCentroid(void) { for (GamePlayerIterator player = support.Players(); !player.AtEnd(); player++) { T center = ((T) 1) / ((T) support.NumStrategies(player->GetNumber())); for (SupportStrategyIterator strategy = support.Strategies(player); !strategy.AtEnd(); strategy++) { (*this)[strategy] = center; } } } template MixedStrategyProfile MixedStrategyProfile::ToFullSupport(void) const { MixedStrategyProfile full(support.GetGame()); static_cast &>(full) = (T) 0; for (int pl = 1; pl <= support.GetGame()->NumPlayers(); pl++) { GamePlayer player = support.GetGame()->GetPlayer(pl); for (int st = 1; st <= player->NumStrategies(); st++) { if (support.Contains(player->GetStrategy(st))) { full[player->GetStrategy(st)] = (*this)[player->GetStrategy(st)]; } } } return full; } //======================================================================== // MixedStrategyProfile: Computation of interesting quantities //======================================================================== template T MixedStrategyProfile::GetPayoff(int pl, int index, int current) const { if (current > support.GetGame()->NumPlayers()) { GameOutcomeRep *outcome = support.GetGame()->m_results[index]; if (outcome) { return outcome->GetPayoff(pl); } else { return (T) 0; } } T sum = (T) 0; for (int j = 1; j <= support.NumStrategies(current); j++) { GameStrategyRep *s = support.GetStrategy(current, j); if ((*this)[s] != (T) 0) { sum += ((*this)[s] * GetPayoff(pl, index + s->m_offset, current + 1)); } } return sum; } template T MixedStrategyProfile::GetPayoff(int pl) const { if (support.GetGame()->IsTree()) { return MixedBehavProfile(*this).GetPayoff(pl); } else { return GetPayoff(pl, 1, 1); } } template void MixedStrategyProfile::GetPayoffDeriv(int pl, int const_pl, int cur_pl, long index, const T &prob, T &value) const { if (cur_pl == const_pl) { cur_pl++; } if (cur_pl > support.GetGame()->NumPlayers()) { GameOutcomeRep *outcome = support.GetGame()->m_results[index]; if (outcome) { value += prob * outcome->GetPayoff(pl); } } else { for (int j = 1; j <= support.NumStrategies(cur_pl); j++) { GameStrategyRep *s = support.GetStrategy(cur_pl, j); if ((*this)[s] > (T) 0) GetPayoffDeriv(pl, const_pl, cur_pl + 1, index + s->m_offset, prob * (*this)[s], value); } } } template T MixedStrategyProfile::GetPayoffDeriv(int pl, const GameStrategy &strategy) const { if (support.GetGame()->IsTree()) { MixedStrategyProfile foo(*this); int player1 = strategy->GetPlayer()->GetNumber(); for (int st = 1; st <= support.NumStrategies(player1); st++) { foo[support.GetStrategy(player1, st)] = (T) 0; } foo[strategy] = (T) 1; return foo.GetPayoff(pl); } else { T value = (T) 0; GetPayoffDeriv(pl, strategy->GetPlayer()->GetNumber(), 1, strategy->m_offset + 1, (T) 1, value); return value; } } template void MixedStrategyProfile::GetPayoffDeriv(int pl, int const_pl1, int const_pl2, int cur_pl, long index, const T &prob, T &value) const { while (cur_pl == const_pl1 || cur_pl == const_pl2) { cur_pl++; } if (cur_pl > support.GetGame()->NumPlayers()) { GameOutcomeRep *outcome = support.GetGame()->m_results[index]; if (outcome) { value += prob * outcome->GetPayoff(pl); } } else { for (int j = 1; j <= support.NumStrategies(cur_pl); j++ ) { GameStrategyRep *s = support.GetStrategy(cur_pl, j); if ((*this)[s] > (T) 0) { GetPayoffDeriv(pl, const_pl1, const_pl2, cur_pl + 1, index + s->m_offset, prob * (*this)[s], value); } } } } template T MixedStrategyProfile::GetPayoffDeriv(int pl, const GameStrategy &strategy1, const GameStrategy &strategy2) const { GamePlayerRep *player1 = strategy1->GetPlayer(); GamePlayerRep *player2 = strategy2->GetPlayer(); if (player1 == player2) return (T) 0; if (support.GetGame()->IsTree()) { MixedStrategyProfile foo(*this); for (SupportStrategyIterator strategy = support.Strategies(player1); !strategy.AtEnd(); strategy++) { foo[strategy] = (T) 0; } foo[strategy1] = (T) 1; for (SupportStrategyIterator strategy = support.Strategies(player2); !strategy.AtEnd(); strategy++) { foo[strategy] = (T) 0; } foo[strategy2] = (T) 1; return foo.GetPayoff(pl); } else { T value = (T) 0; GetPayoffDeriv(pl, player1->GetNumber(), player2->GetNumber(), 1, strategy1->m_offset + strategy2->m_offset + 1, (T) 1, value); return value; } } template T MixedStrategyProfile::GetLiapValue(void) const { static const T BIG1 = (T) 100; static const T BIG2 = (T) 100; T liapValue = (T) 0; for (GamePlayerIterator player = support.Players(); !player.AtEnd(); player++) { // values of the player's strategies Array values(support.NumStrategies(player->GetNumber())); T avg = (T) 0, sum = (T) 0; for (SupportStrategyIterator strategy = support.Strategies(player); !strategy.AtEnd(); strategy++) { const T &prob = (*this)[strategy]; values[support.GetIndex(strategy)] = GetStrategyValue(strategy); avg += prob * values[support.GetIndex(strategy)]; sum += prob; if (prob < (T) 0) { liapValue += BIG1*prob*prob; // penalty for negative probabilities } } for (int st = 1; st <= values.Length(); st++) { T regret = values[st] - avg; if (regret > (T) 0) { liapValue += regret*regret; // penalty if not best response } } // penalty if sum does not equal to one liapValue += BIG2*(sum - (T) 1.0)*(sum - (T) 1.0); } return liapValue; } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/number.h0000644000076500007650000000347011435216101014620 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/number.h // A simple class for storing numerical data in a game // // 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 LIBGAMBIT_NUMBER_H #define LIBGAMBIT_NUMBER_H namespace Gambit { /// This simple class stores a numerical datum. class Number { private: std::string m_text; Rational m_rational; double m_double; public: Number(void) : m_text("0"), m_rational(0), m_double(0.0) { } Number(const std::string &p_text) : m_text(p_text), m_rational(ToRational(p_text)), m_double((double) m_rational) { } Number &operator=(const std::string &p_text) { // We call ToRational() first because it throws a ValueException // if the conversion of the text fails m_rational = ToRational(p_text); m_text = p_text; m_double = (double) m_rational; return *this; } operator const double &(void) const { return m_double; } operator const Rational &(void) const { return m_rational; } operator const std::string &(void) const { return m_text; } }; } #endif // LIBGAMBIT_NUMBER_H gambit-0.2010.09.01/src/libgambit/pvector.cc0000644000076500007650000000210311435216101015140 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/pvector.cc // Instantiation of partitioned vector types // // 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 "libgambit.h" #include "pvector.imp" template class Gambit::PVector; template class Gambit::PVector; template class Gambit::PVector; gambit-0.2010.09.01/src/libgambit/pvector.h0000644000076500007650000000463111435216101015012 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/pvector.h // Partitioned vector class // // 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 LIBGAMBIT_PVECTOR_H #define LIBGAMBIT_PVECTOR_H #include "vector.h" namespace Gambit { template class PVector : public Vector { private: int sum(const Array &V) const; void setindex(void); protected: T **svptr; Array svlen; int Check(const PVector &v) const; public: // constructors PVector(void); PVector(const Array &sig); PVector(const Vector &val, const Array &sig); PVector(const PVector &v); virtual ~PVector(); // element access operators T& operator()(int a, int b); const T& operator()(int a, int b) const; // extract a subvector Vector GetRow(int row) const; void GetRow(int row, Vector &v) const; void SetRow(int row, const Vector &v); void CopyRow(int row, const PVector &v); // more operators PVector& operator=(const PVector &v); PVector& operator=(const Vector &v); PVector& operator=(T c); PVector operator+(const PVector &v) const; PVector& operator+=(const PVector &v); PVector operator-(void) const; PVector operator-(const PVector &v) const; PVector& operator-=(const PVector &v); T operator*(const PVector &v) const; PVector operator*(const T &c) const; PVector& operator*=(const T c); PVector operator/(T c); bool operator==(const PVector &v) const; bool operator!=(const PVector &v) const; // parameter access functions const Array& Lengths(void) const; }; } // end namespace Gambit #endif // LIBGAMBIT_PVECTOR_H gambit-0.2010.09.01/src/libgambit/pvector.imp0000644000076500007650000001607011435216101015350 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/pvector.imp // Implementation of partitioned vector members // // 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 "pvector.h" namespace Gambit { //------------------------------------------------------------------------- // PVector: Private and protected member functions //------------------------------------------------------------------------- template int PVector::sum(const Array &V) const { int total = 0; for (int i = V.First(); i <= V.Last(); total += V[i++]); return total; } template void PVector::setindex(void) { int index = this->First(); for(int i = 1; i <= svlen.Length(); i++) { svptr[i] = this->data + index - 1; index += svlen[i]; } //assert(index == this->Last() + 1); } template int PVector::Check(const PVector &v) const { if (v.mindex == this->mindex && v.maxdex == this->maxdex) { for (int i = 1; i <= svlen.Length(); i++) if (svlen[i] != v.svlen[i]) return 0; return 1; } return 0; } //------------------------------------------------------------------------- // PVector: Constructors, destructor, and constructive operators //------------------------------------------------------------------------- template PVector::PVector(void) : svptr(0) { } template PVector::PVector(const Array &sig) : Vector(sum(sig)), svlen(sig) { svptr = new T *[sig.Last() - sig.First() + 1]; svptr -= 1; // align things correctly setindex(); } template PVector::PVector(const Vector &val, const Array &sig) : Vector(val), svlen(sig) { //assert(sum(svlen) == val.Length()); svptr = new T *[sig.Last() - sig.First() + 1]; svptr -= 1; setindex(); } template PVector::PVector(const PVector &v) : Vector(v), svlen(v.svlen) { svptr = new T *[v.svlen.Last() - v.svlen.First() + 1]; svptr -= 1; setindex(); } template PVector::~PVector() { if (svptr) delete [] (svptr + 1); } template PVector& PVector::operator=(const PVector &v) { if (!Check(v)) { throw DimensionException(); } Vector::operator=(v); return (*this); } template PVector& PVector::operator=(const Vector &v) { Vector::operator=(v); return (*this); } template PVector& PVector::operator=(T c) { Vector::operator=(c); return (*this); } //------------------------------------------------------------------------- // PVector: Operator definitions //------------------------------------------------------------------------- template T& PVector::operator()(int a, int b) { if (svlen.First() > a || a > svlen.Last()) { throw IndexException(); } if (1 > b || b > svlen[a]) { throw IndexException(); } return svptr[a][b]; } template const T& PVector::operator()(int a, int b) const { if (svlen.First() > a || a > svlen.Last()) { throw IndexException(); } if (1 > b || b > svlen[a]) { throw IndexException(); } return svptr[a][b]; } template PVector PVector::operator+(const PVector &v) const { if (!Check(v)) { throw DimensionException(); } PVector tmp(*this); tmp.Vector::operator+=(v); return tmp; } template PVector& PVector::operator+=(const PVector &v) { if (!Check(v)) { throw DimensionException(); } Vector::operator+=(v); return (*this); } template PVector PVector::operator-(void) const { PVector tmp(*this); for(int i=this->First(); i<=this->Last(); i++) tmp[i]= -tmp[i]; return tmp; } template PVector PVector::operator-(const PVector &v) const { if (!Check(v)) { throw DimensionException(); } PVector tmp(*this); tmp.Vector::operator-=(v); return tmp; } template PVector& PVector::operator-=(const PVector &v) { if (!Check(v)) { throw DimensionException(); } Vector::operator-=(v); return (*this); } template T PVector::operator*(const PVector &v) const { if (!Check(v)) { throw DimensionException(); } return (*this).Vector::operator*(v); } template PVector PVector::operator*(const T &c) const { PVector ret(*this); ret *= c; return ret; } template PVector& PVector::operator*=(const T c) { Vector::operator*=(c); return (*this); } template PVector PVector::operator/(T c) { PVector tmp(*this); tmp= tmp.Vector::operator/(c); return tmp; } template bool PVector::operator==(const PVector &v) const { if (!Check(v)) { throw DimensionException(); } return (*this).Vector::operator==(v); } template bool PVector::operator!=(const PVector &v) const { return !((*this)==v); } //------------------------------------------------------------------------- // PVector: General data access //------------------------------------------------------------------------- template Vector PVector::GetRow(int row) const { if (svlen.First() > row || row > svlen.Last()) { throw IndexException(); } Vector v(1, svlen[row]); for(int i=v.First(); i<=v.Last(); i++) v[i]= (*this)(row,i); return v; } template void PVector::GetRow(int row, Vector &v) const { if (svlen.First() > row || row > svlen.Last()) { throw IndexException(); } if (v.First() != 1 || v.Last() != svlen[row]) { throw DimensionException(); } for(int i=v.First(); i<=v.Last(); i++) v[i]= (*this)(row,i); } template void PVector::SetRow(int row, const Vector &v) { if (svlen.First() > row || row > svlen.Last()) { throw IndexException(); } if (v.First() != 1 || v.Last() != svlen[row]) { throw DimensionException(); } for(int i=v.First(); i<=v.Last(); i++) (*this)(row,i)= v[i]; } template void PVector::CopyRow(int row, const PVector &v) { if (!Check(v)) { throw DimensionException(); } if (svlen.First() > row || row > svlen.Last()) { throw IndexException(); } for (int i = 1; i <= svlen[row]; i++) svptr[row][i] = v.svptr[row][i]; } template const Array &PVector::Lengths(void) const { return svlen; } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/rational.cc0000644000076500007650000003026711435216101015303 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/rational.cc // Implementation of a rational number class // // // The original copyright and license are included below. // /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of the GNU C++ Library. 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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #if defined(__GNUG__) && !defined(__APPLE_CC__) #pragma implementation #endif #include "libgambit.h" #include "rational.h" #include #include #include #include namespace Gambit { void Rational::error(const char* msg) const { // gerr << "Rational class error: " << msg << '\n'; assert(0); } static const Integer _Int_One(1); void Rational::normalize() { int s = sign(den); if (s == 0) error("Zero denominator."); else if (s < 0) { den.negate(); num.negate(); } Integer g = gcd(num, den); if (ucompare(g, _Int_One) != 0) { num /= g; den /= g; } } void add(const Rational& x, const Rational& y, Rational& r) { if (&r != &x && &r != &y) { mul(x.num, y.den, r.num); mul(x.den, y.num, r.den); add(r.num, r.den, r.num); mul(x.den, y.den, r.den); } else { Integer tmp; mul(x.den, y.num, tmp); mul(x.num, y.den, r.num); add(r.num, tmp, r.num); mul(x.den, y.den, r.den); } r.normalize(); } void sub(const Rational& x, const Rational& y, Rational& r) { if (&r != &x && &r != &y) { mul(x.num, y.den, r.num); mul(x.den, y.num, r.den); sub(r.num, r.den, r.num); mul(x.den, y.den, r.den); } else { Integer tmp; mul(x.den, y.num, tmp); mul(x.num, y.den, r.num); sub(r.num, tmp, r.num); mul(x.den, y.den, r.den); } r.normalize(); } void mul(const Rational& x, const Rational& y, Rational& r) { mul(x.num, y.num, r.num); mul(x.den, y.den, r.den); r.normalize(); } void div(const Rational& x, const Rational& y, Rational& r) { if (&r != &x && &r != &y) { mul(x.num, y.den, r.num); mul(x.den, y.num, r.den); } else { Integer tmp; mul(x.num, y.den, tmp); mul(y.num, x.den, r.den); r.num = tmp; } r.normalize(); } void Rational::invert() { Integer tmp = num; num = den; den = tmp; int s = sign(den); if (s == 0) error("Zero denominator."); else if (s < 0) { den.negate(); num.negate(); } } int compare(const Rational& x, const Rational& y) { int xsgn = sign(x.num); int ysgn = sign(y.num); int d = xsgn - ysgn; if (d == 0 && xsgn != 0) d = compare(x.num * y.den, x.den * y.num); return d; } Rational::Rational(double x) { num = 0; den = 1; if (x != 0.0) { int neg = x < 0; if (neg) x = -x; const long shift = 15; // a safe shift per step const double width = 32768.0; // = 2^shift const int maxiter = 20; // ought not be necessary, but just in case, // max 300 bits of precision int expt; double mantissa = frexp(x, &expt); long exponent = expt; double intpart; int k = 0; while (mantissa != 0.0 && k++ < maxiter) { mantissa *= width; mantissa = modf(mantissa, &intpart); num <<= shift; num += (long)intpart; exponent -= shift; } if (exponent > 0) num <<= exponent; else if (exponent < 0) den <<= -exponent; if (neg) num.negate(); } normalize(); } Integer trunc(const Rational& x) { return x.num / x.den ; } Rational pow(const Rational& x, const Integer& y) { long yy = y.as_long(); return pow(x, yy); } Rational Rational::operator-(void) const { Rational r(*this); r.negate(); return r; } Rational abs(const Rational& x) { Rational r(x); if (sign(r.num) < 0) r.negate(); return r; } Rational sqr(const Rational& x) { Rational r; mul(x.num, x.num, r.num); mul(x.den, x.den, r.den); r.normalize(); return r; } Integer floor(const Rational& x) { Integer q; Integer r; divide(x.num, x.den, q, r); if (sign(x.num) < 0 && sign(r) != 0) --q; return q; } Integer ceil(const Rational& x) { Integer q; Integer r; divide(x.num, x.den, q, r); if (sign(x.num) >= 0 && sign(r) != 0) ++q; return q; } Integer round(const Rational& x) { Integer q; Integer r; divide(x.num, x.den, q, r); r <<= 1; if (ucompare(r, x.den) >= 0) { if (sign(x.num) >= 0) ++q; else --q; } return q; } Rational pow(const Rational& x, long y) { Rational r; if (y >= 0) { pow(x.num, y, r.num); pow(x.den, y, r.den); } else { y = -y; pow(x.num, y, r.den); pow(x.den, y, r.num); if (sign(r.den) < 0) { r.num.negate(); r.den.negate(); } } return r; } std::ostream &operator << (std::ostream &s, const Rational& y) { if (y.denominator() == 1L) s << y.numerator(); else { s << y.numerator(); s << "/"; s << y.denominator(); } return s; } std::istream &operator>>(std::istream &f, Rational &y) { char ch = ' '; int sign = 1; Integer num = 0, denom = 1; while (isspace(ch)) { f.get(ch); if (f.eof()) return f; } if (ch == '-') { sign = -1; f.get(ch); } while (ch >= '0' && ch <= '9') { num *= 10; num += (int) (ch - '0'); f.get(ch); } if (ch == '/') { denom = 0; f.get(ch); while (ch >= '0' && ch <= '9') { denom *= 10; denom += (int) (ch - '0'); f.get(ch); } } else if (ch == '.') { denom = 1; f.get(ch); while (ch >= '0' && ch <= '9') { denom *= 10; num *= 10; num += (int) (ch - '0'); f.get(ch); } } f.unget(); y = Rational(num * sign, denom); y.normalize(); return f; } int Rational::OK() const { int v = num.OK() && den.OK(); // have valid num and denom if (v) { v &= sign(den) > 0; // denominator positive; v &= ucompare(gcd(num, den), _Int_One) == 0; // relatively prime } if (!v) error("invariant failure"); return v; } int Rational::fits_in_float() const { return Rational (FLT_MIN) <= *this && *this <= Rational (FLT_MAX); } int Rational::fits_in_double() const { return Rational (DBL_MIN) <= *this && *this <= Rational (DBL_MAX); } // // These were moved from the header file to eliminate warnings // static IntegerRep _ZeroRep = {1, 0, 1, {0}}; static IntegerRep _OneRep = {1, 0, 1, {1}}; Rational::Rational() : num(&_ZeroRep), den(&_OneRep) {} Rational::~Rational() {} Rational::Rational(const Rational& y) :num(y.num), den(y.den) {} Rational::Rational(const Integer& n) :num(n), den(&_OneRep) {} Rational::Rational(const Integer& n, const Integer& d) :num(n),den(d) { normalize(); } Rational::Rational(long n) :num(n), den(&_OneRep) { } Rational::Rational(int n) :num(n), den(&_OneRep) { } Rational::Rational(long n, long d) :num(n), den(d) { normalize(); } Rational::Rational(int n, int d) :num(n), den(d) { normalize(); } Rational &Rational::operator = (const Rational& y) { num = y.num; den = y.den; return *this; } bool Rational::operator==(const Rational &y) const { return compare(num, y.num) == 0 && compare(den, y.den) == 0; } bool Rational::operator!=(const Rational &y) const { return compare(num, y.num) != 0 || compare(den, y.den) != 0; } bool Rational::operator< (const Rational &y) const { return compare(*this, y) < 0; } bool Rational::operator<=(const Rational &y) const { return compare(*this, y) <= 0; } bool Rational::operator> (const Rational &y) const { return compare(*this, y) > 0; } bool Rational::operator>=(const Rational &y) const { return compare(*this, y) >= 0; } int sign(const Rational& x) { return sign(x.num); } void Rational::negate() { num.negate(); } Rational &Rational::operator+=(const Rational& y) { add(*this, y, *this); return *this; } Rational &Rational::operator-=(const Rational& y) { sub(*this, y, *this); return *this; } Rational &Rational::operator*=(const Rational& y) { mul(*this, y, *this); return *this; } Rational &Rational::operator/=(const Rational& y) { div(*this, y, *this); return *this; } const Integer& Rational::numerator() const { return num; } const Integer& Rational::denominator() const { return den; } Rational::operator double(void) const { // We approach this in terms of absolute values because there is // (apparently) a bug in ratio() which yields incorrect results // for some negative numbers (TLT, 27 Feb 2006). Integer x(num), y(den); x.abs(); y.abs(); return sign(*this) * ratio(x, y); } Rational Rational::operator+(const Rational &y) const { Rational r; add(*this, y, r); return r; } Rational Rational::operator-(const Rational &y) const { Rational r; sub(*this, y, r); return r; } Rational Rational::operator*(const Rational &y) const { Rational r; mul(*this, y, r); return r; } Rational Rational::operator/(const Rational &y) const { Rational r; div(*this, y, r); return r; } std::string ToText(const Rational &r) { std::string ret; ret += Itoa(r.numerator()); if (r.denominator() != Integer(1)) { ret += "/"; ret += Itoa(r.denominator()); } return ret; } Rational ToRational(const std::string &f) { char ch = ' '; int sign = 1; unsigned int index = 0, length = f.length(); Integer num = 0, denom = 1; while (isspace(ch) && index<=length) { ch = f[index++]; } if (ch == '-' && index<=length) { sign = -1; ch=f[index++]; } while (ch >= '0' && ch <= '9' && index<=length) { num *= 10; num += (int) (ch - '0'); ch=f[index++]; } if (ch == '/') { denom = 0; ch=f[index++]; while (ch >= '0' && ch <= '9' && index<=length) { denom *= 10; denom += (int) (ch - '0'); ch=f[index++]; } } else if (ch == '.') { denom = 1; ch=f[index++]; while (ch >= '0' && ch <= '9' && index<=length) { denom *= 10; num *= 10; num += (int) (ch - '0'); ch=f[index++]; } if (ch == 'e' || ch == 'E') { int expsign = 1; Integer exponent = 0; ch = f[index++]; if (ch == '-') { expsign = -1; ch = f[index++]; } while (ch >= '0' && ch <= '9' && index <= length) { exponent *= 10; exponent += (int) (ch - '0'); ch = f[index++]; } if (exponent * expsign > 0) { while (exponent > 0) { num *= 10; exponent -= 1; } } else if (exponent * expsign < 0) { while (exponent > 0) { denom *= 10; exponent -= 1; } } } } else if (ch == 'e' || ch == 'E') { int expsign = 1; Integer exponent = 0; ch = f[index++]; if (ch == '-') { expsign = -1; ch = f[index++]; } while (ch >= '0' && ch <= '9' && index <= length) { exponent *= 10; exponent += (int) (ch - '0'); ch = f[index++]; } if (exponent * expsign > 0) { while (exponent > 0) { num *= 10; exponent -= 1; } } else if (exponent * expsign < 0) { while (exponent > 0) { denom *= 10; exponent -= 1; } } } if (ch != '\0') { throw ValueException(); } if (denom != 0) { return Rational(num * sign, denom); } else { return Rational(num * sign); } } Rational ToNumber(const std::string &p_string) { if (p_string.find('.') != (unsigned int) -1 || p_string.find('e') != (unsigned int) -1) { std::istringstream st(p_string); double d; st >> d; return Rational(d); } else { return ToRational(p_string); } } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/rational.h0000644000076500007650000001046011435216101015136 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/rational.h // Interface to a rational number class // // The original copyright and license are included below. // /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of the GNU C++ Library. 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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef LIBGAMBIT_RATIONAL_H #if defined(__GNUG__) && !defined(__APPLE_CC__) #pragma interface #endif #define LIBGAMBIT_RATIONAL_H #include "integer.h" #include namespace Gambit { /// A representation of an arbitrary-precision rational number class Rational { protected: Integer num, den; void normalize(); public: Rational(void); Rational(double); Rational(int); Rational(long n); Rational(int n, int d); Rational(long n, long d); Rational(const Integer& n); Rational(const Integer& n, const Integer& d); Rational(const Rational&); ~Rational(); Rational &operator = (const Rational& y); bool operator==(const Rational &y) const; bool operator!=(const Rational &y) const; bool operator< (const Rational &y) const; bool operator<=(const Rational &y) const; bool operator> (const Rational &y) const; bool operator>=(const Rational &y) const; Rational operator+(const Rational &y) const; Rational operator-(const Rational &y) const; Rational operator*(const Rational &y) const; Rational operator/(const Rational &y) const; Rational &operator+=(const Rational& y); Rational &operator-=(const Rational& y); Rational &operator*=(const Rational& y); Rational &operator/=(const Rational& y); Rational operator-(void) const; // builtin Rational functions void negate(); // x = -x void invert(); // x = 1/x friend int sign(const Rational& x); // -1, 0, or +1 friend Rational abs(const Rational& x); // absolute value friend Rational sqr(const Rational& x); // square friend Rational pow(const Rational& x, long y); friend Rational pow(const Rational& x, const Integer& y); const Integer& numerator() const; const Integer& denominator() const; // coercion & conversion operator double() const; friend Integer floor(const Rational& x); friend Integer ceil(const Rational& x); friend Integer trunc(const Rational& x); friend Integer round(const Rational& x); friend std::istream &operator>>(std::istream &s, Rational& y); friend std::ostream &operator<<(std::ostream &s, const Rational& y); int fits_in_float() const; int fits_in_double() const; // procedural versions of operators friend int compare(const Rational& x, const Rational& y); friend void add(const Rational& x, const Rational& y, Rational& dest); friend void sub(const Rational& x, const Rational& y, Rational& dest); friend void mul(const Rational& x, const Rational& y, Rational& dest); friend void div(const Rational& x, const Rational& y, Rational& dest); // error detection void error(const char* msg) const; int OK() const; }; std::string ToText(const Rational &); inline std::string ToText(const Rational &r, int) { return ToText(r); } Rational ToRational(const std::string &); inline void Epsilon(Rational &v, int /*i*/ = 8) { v = (Rational) 0;} // // This is implemented so as to convert rational numbers to their // floating point equivalent. // inline double ToDouble(const std::string &s) { return (double) ToRational(s); } Rational ToNumber(const std::string &p_string); } // end namespace Gambit #endif // LIBGAMBIT_RATIONAL_H gambit-0.2010.09.01/src/libgambit/recarray.h0000644000076500007650000002650111435216101015140 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/recarray.h // Rectangular array base class // // 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 LIBGAMBIT_RECARRAY_H #define LIBGAMBIT_RECARRAY_H #include "libgambit.h" namespace Gambit { /// This class implements a rectangular (two-dimensional) array template class RectArray { protected: int minrow, maxrow, mincol, maxcol; T **data; public: /// @name Lifecycle //@{ RectArray(void); RectArray(unsigned int nrows, unsigned int ncols); RectArray(int minr, int maxr, int minc, int maxc); RectArray(const RectArray &); virtual ~RectArray(); RectArray &operator=(const RectArray &); //@} /// @name General data access //@{ int NumRows(void) const; int NumColumns(void) const; int MinRow(void) const; int MaxRow(void) const; int MinCol(void) const; int MaxCol(void) const; //@} /// @name Indexing operations //@{ T &operator()(int r, int c); const T &operator()(int r, int c) const; //@} /// @name Row and column rotation operators //@{ void RotateUp(int lo, int hi); void RotateDown(int lo, int hi); void RotateLeft(int lo, int hi); void RotateRight(int lo, int hi); //@} /// @name Row and column manipulation functions //@{ void SwitchRow(int, Array &); void SwitchRows(int, int); void GetRow(int, Array &) const; void SetRow(int, const Array &); void SwitchColumn(int, Array &); void SwitchColumns(int, int); void GetColumn(int, Array &) const; void SetColumn(int, const Array &); /// Returns the transpose of the rectangular array RectArray Transpose(void) const; /// @name Range checking functions; returns true only if valid index/size //@{ /// check for correct row index bool CheckRow(int row) const; /// check row vector for correct column boundaries bool CheckRow(const Array &) const; /// check for correct column index bool CheckColumn(int col) const; /// check column vector for correct row boundaries bool CheckColumn(const Array &) const; /// check row and column indices bool Check(int row, int col) const; /// check matrix for same row and column boundaries bool CheckBounds(const RectArray &) const; //@ }; //------------------------------------------------------------------------ // RectArray: Bounds-checking member functions //------------------------------------------------------------------------ template bool RectArray::CheckRow(int row) const { return (minrow <= row && row <= maxrow); } template bool RectArray::CheckRow(const Array &v) const { return (v.First() == mincol && v.Last() == maxcol); } template bool RectArray::CheckColumn(int col) const { return (mincol <= col && col <= maxcol); } template bool RectArray::CheckColumn(const Array &v) const { return (v.First() == minrow && v.Last() == maxrow); } template bool RectArray::Check(int row, int col) const { return (CheckRow(row) && CheckColumn(col)); } template bool RectArray::CheckBounds(const RectArray &m) const { return (minrow == m.minrow && maxrow == m.maxrow && mincol == m.mincol && maxcol == m.maxcol); } //------------------------------------------------------------------------ // RectArray: Constructors, destructor, constructive operators //------------------------------------------------------------------------ template RectArray::RectArray(void) : minrow(1), maxrow(0), mincol(1), maxcol(0), data(0) { } template RectArray::RectArray(unsigned int rows, unsigned int cols) : minrow(1), maxrow(rows), mincol(1), maxcol(cols) { data = (rows > 0) ? new T *[maxrow] - 1 : 0; for (int i = 1; i <= maxrow; data[i++] = (cols > 0) ? new T[maxcol] - 1 : 0); } template RectArray::RectArray(int minr, int maxr, int minc, int maxc) : minrow(minr), maxrow(maxr), mincol(minc), maxcol(maxc) { data = (maxrow >= minrow) ? new T *[maxrow - minrow + 1] - minrow : 0; for (int i = minrow; i <= maxrow; data[i++] = (maxcol - mincol + 1) ? new T[maxcol - mincol + 1] - mincol : 0); } template RectArray::RectArray(const RectArray &a) : minrow(a.minrow), maxrow(a.maxrow), mincol(a.mincol), maxcol(a.maxcol) { data = (maxrow >= minrow) ? new T *[maxrow - minrow + 1] - minrow : 0; for (int i = minrow; i <= maxrow; i++) { data[i] = (maxcol >= mincol) ? new T[maxcol - mincol + 1] - mincol : 0; for (int j = mincol; j <= maxcol; j++) data[i][j] = a.data[i][j]; } } template RectArray::~RectArray() { for (int i = minrow; i <= maxrow; i++) if (data[i]) delete [] (data[i] + mincol); if (data) delete [] (data + minrow); } template RectArray &RectArray::operator=(const RectArray &a) { if (this != &a) { int i; for (i = minrow; i <= maxrow; i++) if (data[i]) delete [] (data[i] + mincol); if (data) delete [] (data + minrow); minrow = a.minrow; maxrow = a.maxrow; mincol = a.mincol; maxcol = a.maxcol; data = (maxrow >= minrow) ? new T *[maxrow - minrow + 1] - minrow : 0; for (i = minrow; i <= maxrow; i++) { data[i] = (maxcol >= mincol) ? new T[maxcol - mincol + 1] - mincol : 0; for (int j = mincol; j <= maxcol; j++) data[i][j] = a.data[i][j]; } } return *this; } //------------------------------------------------------------------------ // RectArray: Data access members //------------------------------------------------------------------------ template int RectArray::NumRows(void) const { return maxrow - minrow + 1; } template int RectArray::NumColumns(void) const { return maxcol - mincol + 1; } template int RectArray::MinRow(void) const { return minrow; } template int RectArray::MaxRow(void) const { return maxrow; } template int RectArray::MinCol(void) const { return mincol; } template int RectArray::MaxCol(void) const { return maxcol; } template T &RectArray::operator()(int r, int c) { if (!Check(r, c)) throw IndexException(); return data[r][c]; } template const T &RectArray::operator()(int r, int c) const { if (!Check(r, c)) throw IndexException(); return data[r][c]; } //------------------------------------------------------------------------ // RectArray: Row and column rotation //------------------------------------------------------------------------ template void RectArray::RotateUp(int lo, int hi) { if (lo < minrow || hi < lo || maxrow < hi) throw IndexException(); T *temp = data[lo]; for (int k = lo; k < hi; k++) data[k] = data[k + 1]; data[hi] = temp; } template void RectArray::RotateDown(int lo, int hi) { if (lo < minrow || hi < lo || maxrow < hi) throw IndexException(); T *temp = data[hi]; for (int k = hi; k > lo; k--) data[k] = data[k - 1]; data[lo] = temp; } template void RectArray::RotateLeft(int lo, int hi) { if (lo < mincol || hi < lo || maxcol < hi) throw IndexException(); T temp; for (int i = minrow; i <= maxrow; i++) { T *row = data[i]; temp = row[lo]; for (int j = lo; j < hi; j++) row[j] = row[j + 1]; row[hi] = temp; } } template void RectArray::RotateRight(int lo, int hi) { if (lo < mincol || hi < lo || maxcol < hi) throw IndexException(); for (int i = minrow; i <= maxrow; i++) { T *row = data[i]; T temp = row[hi]; for (int j = hi; j > lo; j--) row[j] = row[j - 1]; row[lo] = temp; } } //------------------------------------------------------------------------- // RectArray: Row manipulation functions //------------------------------------------------------------------------- template void RectArray::SwitchRow(int row, Array &v) { if (!CheckRow(row)) throw IndexException(); if (!CheckRow(v)) throw DimensionException(); T *rowptr = data[row]; T tmp; for (int i = mincol; i <= maxcol; i++) { tmp = rowptr[i]; rowptr[i] = v[i]; v[i] = tmp; } } template void RectArray::SwitchRows(int i, int j) { if (!CheckRow(i) || !CheckRow(j)) throw IndexException(); T *temp = data[j]; data[j] = data[i]; data[i] = temp; } template void RectArray::GetRow(int row, Array &v) const { if (!CheckRow(row)) throw IndexException(); if (!CheckRow(v)) throw DimensionException(); T *rowptr = data[row]; for (int i = mincol; i <= maxcol; i++) v[i] = rowptr[i]; } template void RectArray::SetRow(int row, const Array &v) { if (!CheckRow(row)) throw IndexException(); if (!CheckRow(v)) throw DimensionException(); T *rowptr = data[row]; for (int i = mincol; i <= maxcol; i++) rowptr[i] = v[i]; } //------------------------------------------------------------------------- // RectArray: Column manipulation functions //------------------------------------------------------------------------- template void RectArray::SwitchColumn(int col, Array &v) { if (!CheckColumn(col)) throw IndexException(); if (!CheckColumn(v)) throw DimensionException(); for (int i = minrow; i <= maxrow; i++) { T tmp = data[i][col]; data[i][col] = v[i]; v[i] = tmp; } } template void RectArray::SwitchColumns(int a, int b) { if (!CheckColumn(a) || !CheckColumn(b)) throw IndexException(); for (int i = minrow; i <= maxrow; i++) { T tmp = data[i][a]; data[i][a] = data[i][b]; data[i][b] = tmp; } } template void RectArray::GetColumn(int col, Array &v) const { if (!CheckColumn(col)) throw IndexException(); if (!CheckColumn(v)) throw DimensionException(); for (int i = minrow; i <= maxrow; i++) v[i] = data[i][col]; } template void RectArray::SetColumn(int col, const Array &v) { if (!CheckColumn(col)) throw IndexException(); if (!CheckColumn(v)) throw DimensionException(); for (int i = minrow; i <= maxrow; i++) data[i][col] = v[i]; } //------------------------------------------------------------------------- // RectArray: Transpose //------------------------------------------------------------------------- template RectArray RectArray::Transpose(void) const { RectArray tmp(mincol, maxcol, minrow, maxrow); for (int i = minrow; i <= maxrow; i++) for (int j = mincol; j <= maxrow; j++) tmp(j,i) = (*this)(i,j); return tmp; } } // end namespace Gambit #endif // LIBGAMBIT_RECARRAY_H gambit-0.2010.09.01/src/libgambit/sqmatrix.cc0000644000076500007650000000205411435216101015333 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/sqmatrix.cc // Instantiation of common square matrix types // // 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 "sqmatrix.imp" #include "rational.h" template class Gambit::SquareMatrix; template class Gambit::SquareMatrix; gambit-0.2010.09.01/src/libgambit/sqmatrix.h0000644000076500007650000000312411435216101015174 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/sqmatrix.h // Implementation of square matrices // // 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 LIBGAMBIT_SQMATRIX_H #define LIBGAMBIT_SQMATRIX_H #include "matrix.h" namespace Gambit { class SingularMatrixException : public Exception { public: virtual ~SingularMatrixException() { } std::string GetDescription(void) const { return "Attempted to invert a singular matrix"; } }; template class SquareMatrix : public Matrix { public: SquareMatrix(void); SquareMatrix(int size); SquareMatrix(const Matrix &); SquareMatrix(const SquareMatrix &); virtual ~SquareMatrix(); SquareMatrix &operator=(const SquareMatrix &); SquareMatrix Inverse(void) const; T Determinant(void) const; }; } // end namespace Gambit #endif // LIBGAMBIT_SQMATRIX_H gambit-0.2010.09.01/src/libgambit/sqmatrix.imp0000644000076500007650000001165211435216101015537 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/sqmatrix.imp // Implementation of square matrices // // 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 "sqmatrix.h" namespace Gambit { //----------------------------------------------------------------------------- // SquareMatrix: Constructors, destructor, constructive operators //----------------------------------------------------------------------------- template SquareMatrix::SquareMatrix(void) { } template SquareMatrix::SquareMatrix(int size) : Matrix(size, size) { } template SquareMatrix::SquareMatrix(const Matrix &M) : Matrix(M) { } template SquareMatrix::SquareMatrix(const SquareMatrix &M) : Matrix(M) { } template SquareMatrix::~SquareMatrix() { } template SquareMatrix &SquareMatrix::operator=(const SquareMatrix &M) { Matrix::operator=(M); return *this; } //----------------------------------------------------------------------------- // SquareMatrix: Public member functions //----------------------------------------------------------------------------- template SquareMatrix SquareMatrix::Inverse(void) const { if (this->mincol != this->minrow || this->maxcol != this->maxrow) { throw DimensionException(); } SquareMatrix copy(*this); SquareMatrix inv(this->maxrow); // initialize inverse matrix and prescale row vectors for (int i = this->minrow; i <= this->maxrow; i++) { T max= (T) 0; for (int j = this->mincol; j <= this->maxcol; j++) { T abs = copy.data[i][j]; if (abs < (T) 0) abs = -abs; if (abs > max) max = abs; } if (max == (T) 0) { throw SingularMatrixException(); } T scale = (T) 1 / max; for (int j = this->mincol; j <= this->maxcol; j++) { copy.data[i][j] *= scale; if (i == j) inv.data[i][j] = scale; else inv.data[i][j] = (T) 0; } } for (int i = this->mincol; i <= this->maxcol; i++) { // find pivot row T max = copy.data[i][i]; if (max < (T) 0) max = -max; int row = i; for (int j = i + 1; j <= this->maxrow; j++) { T abs = copy.data[j][i]; if (abs < (T) 0) abs = -abs; if (abs > max) { max = abs; row = j; } } if (max <= (T) 0) { throw SingularMatrixException(); } copy.SwitchRows(i, row); inv.SwitchRows(i, row); // scale pivot row T factor = (T) 1 / copy.data[i][i]; for (int k = this->mincol; k <= this->maxcol; k++) { copy.data[i][k] *= factor; inv.data[i][k] *= factor; } // reduce other rows for (int j = this->minrow; j <= this->maxrow; j++) { if (j != i) { T mult = copy.data[j][i]; for (int k = this->mincol; k <= this->maxcol; k++) { copy.data[j][k] -= copy.data[i][k] * mult; inv.data[j][k] -= inv.data[i][k] * mult; } } } } return inv; } template T SquareMatrix::Determinant(void) const { T factor = (T) 1; SquareMatrix M(*this); for (int row = this->minrow; row <= this->maxrow; row++) { // Experience (as of 3/22/99) suggests that, in the interest of // numerical stability, it might be best to do Gaussian // elimination with respect to the row (of those feasible) // whose entry has the largest absolute value. int swap_row = row; for (int i = row+1; i <= this->maxrow; i++) { if (abs(M.data[i][row]) > abs(M.data[swap_row][row])) swap_row = i; } if (swap_row != row) { M.SwitchRows(row, swap_row); for (int j = this->mincol; j <= this->maxcol; j++) M.data[row][j] *= (T) -1; } if (M.data[row][row] == (T)0) return (T)0; // now do row operations to clear the row'th column // below the diagonal for (int row1 = row+1; row1 <= this->maxrow; row1++) { factor = -M.data[row1][row]/M.data[row][row]; for (int i = this->mincol; i <= this->maxcol; i++) M.data[row1][i] += M.data[row][i]*factor; } } // finally we multiply the diagonal elements T det = (T) 1; for (int row = this->minrow; row <= this->maxrow; row++) { det *= M.data[row][row]; } return det; } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/stratitr.cc0000644000076500007650000000753311435216101015346 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/stratitr.cc // Implementation of normal form iterators // // 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 "libgambit.h" namespace Gambit { //=========================================================================== // class StrategyIterator //=========================================================================== //--------------------------------------------------------------------------- // Lifecycle //--------------------------------------------------------------------------- StrategyIterator::StrategyIterator(const StrategySupport &p_support) : m_atEnd(false), m_support(p_support), m_currentStrat(m_support.GetGame()->NumPlayers()), m_profile(m_support.GetGame()), m_frozen1(0), m_frozen2(0) { First(); } StrategyIterator::StrategyIterator(const StrategySupport &p_support, int pl, int st) : m_atEnd(false), m_support(p_support), m_currentStrat(m_support.GetGame()->NumPlayers()), m_profile(m_support.GetGame()), m_frozen1(pl), m_frozen2(0) { m_currentStrat[pl] = st; m_profile.SetStrategy(m_support.GetStrategy(pl, st)); First(); } StrategyIterator::StrategyIterator(const StrategySupport &p_support, const GameStrategy &p_strategy) : m_atEnd(false), m_support(p_support), m_currentStrat(p_support.GetGame()->NumPlayers()), m_profile(p_support.GetGame()), m_frozen1(p_strategy->GetPlayer()->GetNumber()), m_frozen2(0) { m_currentStrat[m_frozen1] = p_strategy->GetNumber(); m_profile.SetStrategy(p_strategy); First(); } StrategyIterator::StrategyIterator(const StrategySupport &p_support, int pl1, int st1, int pl2, int st2) : m_atEnd(false), m_support(p_support), m_currentStrat(m_support.GetGame()->NumPlayers()), m_profile(m_support.GetGame()), m_frozen1(pl1), m_frozen2(pl2) { m_currentStrat[pl1] = st1; m_profile.SetStrategy(m_support.GetStrategy(pl1, st1)); m_currentStrat[pl2] = st2; m_profile.SetStrategy(m_support.GetStrategy(pl2, st2)); First(); } //--------------------------------------------------------------------------- // Iteration //--------------------------------------------------------------------------- void StrategyIterator::First(void) { for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { if (pl == m_frozen1 || pl == m_frozen2) continue; m_profile.SetStrategy(m_support.GetStrategy(pl, 1)); m_currentStrat[pl] = 1; } } void StrategyIterator::operator++(void) { int pl = 1; while (1) { if (pl == m_frozen1 || pl == m_frozen2) { pl++; if (pl > m_support.GetGame()->NumPlayers()) { m_atEnd = true; return; } continue; } if (m_currentStrat[pl] < m_support.NumStrategies(pl)) { m_profile.SetStrategy(m_support.GetStrategy(pl, ++(m_currentStrat[pl]))); return; } m_profile.SetStrategy(m_support.GetStrategy(pl, 1)); m_currentStrat[pl] = 1; pl++; if (pl > m_support.GetGame()->NumPlayers()) { m_atEnd = true; return; } } } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/stratitr.h0000644000076500007650000000553211435216101015205 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/stratitr.h // Normal form iterator class // // 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 LIBGAMBIT_STRATITR_H #define LIBGAMBIT_STRATITR_H #include "game.h" namespace Gambit { /// This class iterates through the contingencies in a strategic game. /// It visits each strategy profile in turn, advancing one contingency /// on each call of NextContingency(). Optionally, the strategy of /// one player may be held fixed during the iteration (by the use of the /// second constructor). class StrategyIterator { friend class GameRep; private: bool m_atEnd; StrategySupport m_support; Array m_currentStrat; PureStrategyProfile m_profile; int m_frozen1, m_frozen2; /// Reset the iterator to the first contingency (this is called by ctors) void First(void); public: /// @name Lifecycle //@{ /// Construct a new iterator on the support, with no strategies held fixed StrategyIterator(const StrategySupport &); /// Construct a new iterator on the support, fixing player pl's strategy StrategyIterator(const StrategySupport &s, int pl, int st); /// Construct a new iterator on the support, fixing the given strategy StrategyIterator(const StrategySupport &, const GameStrategy &); /// Construct a new iterator on the support, fixing two players' strategies StrategyIterator(const StrategySupport &s, int pl1, int st1, int pl2, int st2); //@} /// @name Iteration and data access //@{ /// Advance to the next contingency (prefix version) void operator++(void); /// Advance to the next contingency (postfix version) void operator++(int) { ++(*this); } /// Has iterator gone past the end? bool AtEnd(void) const { return m_atEnd; } /// Get the current strategy profile PureStrategyProfile &operator*(void) { return m_profile; } /// Get the current strategy profile const PureStrategyProfile &operator*(void) const { return m_profile; } /// Get the current strategy profile PureStrategyProfile *const operator->(void) { return &m_profile; } //@} }; } // end namespace Gambit #endif // LIBGAMBIT_STRATITR_H gambit-0.2010.09.01/src/libgambit/stratspt.cc0000644000076500007650000002234411435216101015353 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/stratspt.cc // Implementation of strategy classes for normal forms // // 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 "libgambit.h" namespace Gambit { //=========================================================================== // class StrategySupport //=========================================================================== //--------------------------------------------------------------------------- // Lifecycle //--------------------------------------------------------------------------- StrategySupport::StrategySupport(const Game &p_nfg) : m_nfg(p_nfg), m_profileIndex(p_nfg->MixedProfileLength()) { for (int pl = 1, index = 1; pl <= p_nfg->NumPlayers(); pl++) { m_support.Append(Array()); for (int st = 1; st <= p_nfg->GetPlayer(pl)->NumStrategies(); st++, index++) { m_support[pl].Append(p_nfg->GetPlayer(pl)->GetStrategy(st)); m_profileIndex[index] = index; } } } //--------------------------------------------------------------------------- // General information //--------------------------------------------------------------------------- Array StrategySupport::NumStrategies(void) const { Array a(m_support.Length()); for (int pl = 1; pl <= a.Length(); pl++) { a[pl] = m_support[pl].Length(); } return a; } int StrategySupport::MixedProfileLength(void) const { int total = 0; for (int pl = 1; pl <= m_nfg->NumPlayers(); total += m_support[pl++].Length()); return total; } bool StrategySupport::IsSubsetOf(const StrategySupport &p_support) const { if (m_nfg != p_support.m_nfg) return false; for (int pl = 1; pl <= m_support.Length(); pl++) { if (m_support[pl].Length() > p_support.m_support[pl].Length()) { return false; } else { for (int st = 1; st <= m_support[pl].Length(); st++) { if (!p_support.m_support[pl].Contains(m_support[pl][st])) { return false; } } } } return true; } //--------------------------------------------------------------------------- // Modifying the support //--------------------------------------------------------------------------- void StrategySupport::AddStrategy(const GameStrategy &p_strategy) { // Get the null-pointer checking out of the way once and for all GameStrategyRep *strategy = p_strategy; Array &support = m_support[strategy->GetPlayer()->GetNumber()]; for (int i = 1; i <= support.Length(); i++) { GameStrategyRep *s = support[i]; if (s->GetNumber() == strategy->GetNumber()) { // Strategy already in support; no change return; } if (s->GetNumber() > strategy->GetNumber()) { // Shift all higher-id strategies by one in the profile m_profileIndex[strategy->GetId()] = m_profileIndex[s->GetId()]; for (int id = s->GetId(); id <= m_profileIndex.Length(); id++) { if (m_profileIndex[id] >= 0) m_profileIndex[id]++; } // Insert here support.Insert(strategy, i); return; } } // If we get here, p_strategy has a higher number than anything in the // support for this player; append. GameStrategyRep *last = support[support.Last()]; m_profileIndex[strategy->GetId()] = m_profileIndex[last->GetId()] + 1; for (int id = strategy->GetId()+1; id <= m_profileIndex.Length(); id++) { if (m_profileIndex[id] >= 0) m_profileIndex[id]++; } support.Append(strategy); } bool StrategySupport::RemoveStrategy(const GameStrategy &p_strategy) { GameStrategyRep *strategy = p_strategy; Array &support = m_support[strategy->GetPlayer()->GetNumber()]; if (support.Length() == 1) return false; for (int i = 1; i <= support.Length(); i++) { GameStrategyRep *s = support[i]; if (s == strategy) { support.Remove(i); m_profileIndex[strategy->GetId()] = -1; // Shift strategies left in the profile for (int id = strategy->GetId()+1; id <= m_profileIndex.Length(); id++) { if (m_profileIndex[id] >= 0) m_profileIndex[id]--; } return true; } } return false; } //--------------------------------------------------------------------------- // Identification of dominated strategies //--------------------------------------------------------------------------- bool StrategySupport::Dominates(const GameStrategy &s, const GameStrategy &t, bool p_strict) const { bool equal = true; for (StrategyIterator iter(*this); !iter.AtEnd(); iter++) { Rational ap = iter->GetStrategyValue(s); Rational bp = iter->GetStrategyValue(t); if (p_strict && ap <= bp) { return false; } else if (!p_strict) { if (ap < bp) return false; else if (ap > bp) equal = false; } } return (p_strict || !equal); } bool StrategySupport::IsDominated(const GameStrategy &s, bool p_strict, bool p_external) const { if (p_external) { GamePlayer player = s->GetPlayer(); for (int st = 1; st <= player->NumStrategies(); st++) { if (player->GetStrategy(st) != s && Dominates(player->GetStrategy(st), s, p_strict)) { return true; } } return false; } else { for (int i = 1; i <= NumStrategies(s->GetPlayer()->GetNumber()); i++) { if (GetStrategy(s->GetPlayer()->GetNumber(), i) != s && Dominates(GetStrategy(s->GetPlayer()->GetNumber(), i), s, p_strict)) { return true; } } return false; } } bool StrategySupport::Undominated(StrategySupport &newS, int p_player, bool p_strict, bool p_external) const { Array set((p_external) ? m_nfg->GetPlayer(p_player)->NumStrategies() : NumStrategies(p_player)); if (p_external) { for (int st = 1; st <= set.Length(); st++) { set[st] = m_nfg->GetPlayer(p_player)->GetStrategy(st); } } else { for (int st = 1; st <= set.Length(); st++) { set[st] = GetStrategy(p_player, st); } } int min = 0, dis = set.Length() - 1; while (min <= dis) { int pp; for (pp = 0; pp < min && !Dominates(set[pp+1], set[dis+1], p_strict); pp++); if (pp < min) dis--; else { GameStrategy foo = set[dis+1]; set[dis+1] = set[min+1]; set[min+1] = foo; for (int inc = min + 1; inc <= dis; ) { if (Dominates(set[min+1], set[dis+1], p_strict)) { //p_tracefile << GetStrategy(p_player, set[dis+1])->GetNumber() << " dominated by " << GetStrategy(p_player, set[min+1])->GetNumber() << '\n'; dis--; } else if (Dominates(set[dis+1], set[min+1], p_strict)) { //p_tracefile << GetStrategy(p_player, set[min+1])->GetNumber() << " dominated by " << GetStrategy(p_player, set[dis+1])->GetNumber() << '\n'; foo = set[dis+1]; set[dis+1] = set[min+1]; set[min+1] = foo; dis--; } else { foo = set[dis+1]; set[dis+1] = set[inc+1]; set[inc+1] = foo; inc++; } } min++; } } if (min + 1 <= set.Length()) { for (int i = min + 1; i <= set.Length(); i++) { newS.RemoveStrategy(set[i]); } return true; } else { return false; } } StrategySupport StrategySupport::Undominated(bool p_strict, bool p_external) const { StrategySupport newS(*this); for (int pl = 1; pl <= m_nfg->NumPlayers(); pl++) { Undominated(newS, pl, p_strict, p_external); } return newS; } StrategySupport StrategySupport::Undominated(bool p_strict, const Array &players) const { StrategySupport newS(*this); for (int i = 1; i <= players.Length(); i++) { //tracefile << "Dominated strategies for player " << pl << ":\n"; Undominated(newS, players[i], p_strict); } return newS; } //--------------------------------------------------------------------------- // Identification of overwhelmed strategies //--------------------------------------------------------------------------- bool StrategySupport::Overwhelms(const GameStrategy &s, const GameStrategy &t, bool p_strict) const { StrategyIterator iter(*this); Rational sMin = iter->GetStrategyValue(s); Rational tMax = iter->GetStrategyValue(t); for (; !iter.AtEnd(); iter++) { if (iter->GetStrategyValue(s) < sMin) { sMin = iter->GetStrategyValue(s); } if (iter->GetStrategyValue(t) > tMax) { tMax = iter->GetStrategyValue(t); } if (sMin < tMax || (sMin == tMax && p_strict)) { return false; } } return true; } } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/stratspt.h0000644000076500007650000001377211435216101015222 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/stratspt.h // Interface to strategy classes for normal forms // // 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 LIBGAMBIT_STRATSPT_H #define LIBGAMBIT_STRATSPT_H #include "libgambit.h" namespace Gambit { /// A forward iterator on a strategy support class SupportStrategyIterator { private: const Array &m_support; int m_index; public: /// @name Lifecycle //@{ /// Constructor SupportStrategyIterator(const Array &p_support) : m_support(p_support), m_index(1) { } //@} /// @name Iteration and data access //@{ /// Advance to the next element (prefix version) void operator++(void) { m_index++; } /// Advance to the next element (postfix version) void operator++(int) { m_index++; } /// Has iterator gone past the end? bool AtEnd(void) const { return m_index > m_support.Length(); } /// Get the current index into the array int GetIndex(void) const { return m_index; } /// Get the current element const GameStrategy &operator*(void) const { return m_support[m_index]; } /// Get the current element const GameStrategy &operator->(void) const { return m_support[m_index]; } /// Get the current element operator const GameStrategy &(void) const { return m_support[m_index]; } }; /// \brief A support on a strategic game /// /// This class represents a subset of the strategies in strategic game. /// It is enforced that each player has at least one strategy; thus, /// the strategies in a support can be viewed as a restriction of a game /// to a subset of its strategies. This is useful for eliminating /// dominated strategies from consideration, and in computational /// approaches that enumerate possible equilibrium supports. /// /// Within the support, strategies are maintained in the same order /// in which they appear in the underlying game. class StrategySupport { template friend class MixedStrategyProfile; protected: Game m_nfg; Array > m_support; /// The index into a strategy profile for a strategy (-1 if not in support) Array m_profileIndex; bool Undominated(StrategySupport &newS, int p_player, bool p_strict, bool p_external = false) const; public: /// @name Lifecycle //@{ /// Constructor. By default, a support contains all strategies. StrategySupport(const Game &); //@} /// @name Operator overloading //@{ /// Test for the equality of two supports (same strategies for all players) bool operator==(const StrategySupport &p_support) const { return (m_support == p_support.m_support); } /// Test for the inequality of two supports bool operator!=(const StrategySupport &p_support) const { return (m_support != p_support.m_support); } //@} /// @name General information //@{ /// Returns the game on which the support is defined. Game GetGame(void) const { return m_nfg; } /// Returns the number of strategies in the support for player pl. int NumStrategies(int pl) const { return m_support[pl].Length(); } /// Returns the number of strategies in the support for all players. Array NumStrategies(void) const; /// Returns the total number of strategies in the support. int MixedProfileLength(void) const; /// Returns the strategy in the st'th position for player pl. GameStrategy GetStrategy(int pl, int st) const { return m_support[pl][st]; } /// Returns an iterator over the players in the game GamePlayerIterator Players(void) const { return m_nfg->Players(); } /// Returns an iterator over the strategies for the player SupportStrategyIterator Strategies(const GamePlayer &p_player) const { return m_support[p_player->GetNumber()]; } /// Returns the index of the strategy in the support. int GetIndex(const GameStrategy &s) const { return m_support[s->GetPlayer()->GetNumber()].Find(s); } /// Returns true exactly when the strategy is in the support. bool Contains(const GameStrategy &s) const { return m_profileIndex[s->GetId()] >= 0; } /// Returns true iff this support is a (weak) subset of the specified support bool IsSubsetOf(const StrategySupport &) const; //@} /// @name Modifying the support //@{ /// Add a strategy to the support. void AddStrategy(const GameStrategy &); /// \brief Removes a strategy from the support /// /// Removes a strategy from the support. If the strategy is /// not present, or if the strategy is the only strategy for that /// player, it is not removed. Returns true if the removal was /// executed, and false if not. bool RemoveStrategy(const GameStrategy &); //@} /// @name Identification of dominated strategies //@{ bool Dominates(const GameStrategy &s, const GameStrategy &t, bool p_strict) const; bool IsDominated(const GameStrategy &s, bool p_strict, bool p_external = false) const; /// Returns a copy of the support with dominated strategies eliminated StrategySupport Undominated(bool p_strict, bool p_external = false) const; StrategySupport Undominated(bool strong, const Array &players) const; //@} /// @name Identification of overwhelmed strategies //@( bool Overwhelms(const GameStrategy &s, const GameStrategy &t, bool p_strict) const; //@} }; } // end namespace Gambit #endif // LIBGAMBIT_STRATSPT_H gambit-0.2010.09.01/src/libgambit/subgame.cc0000644000076500007650000002145111435216101015110 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/subgame.cc // Utilities for computing and verifying subgame-perfection // // 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 "libgambit.h" #include "subgame.h" #include namespace Gambit { // A nested anonymous namespace to privatize these functions namespace { /// /// Returns a copy of the game 'p_efg', including only the subtree rooted /// at 'p_node'. /// Game CopyGame(const Game &p_efg, const GameNode &p_node) { std::ostringstream os; p_efg->WriteEfgFile(os, p_node); std::istringstream is(os.str()); return ReadGame(is); } /// /// Returns a list of the root nodes of all the immediate proper subgames /// in the subtree rooted at 'p_node'. /// void ChildSubgames(const GameNode &p_node, List &p_list) { if (p_node->IsSubgameRoot()) { p_list.Append(p_node); } else { for (int i = 1; i <= p_node->NumChildren(); ChildSubgames(p_node->GetChild(i++), p_list)); } } } // end nested anonymous namespace // // Some general notes on the strategy for solving by subgames: // // * We work with a *copy* of the original game, which is destroyed // as we go. // * Before solving, information set labels on the copy game are // set to unique IDs. These are used to match up information // sets in the subgames (which are themselves copies) to the // original game. // * We only carry around DVectors instead of full MixedBehavProfiles, // because MixedBehavProfiles allocate space several times the // size of the tree to carry around useful quantities. These // quantities are irrelevant for this calculation, so we only // store the probabilities, and convert to MixedBehavProfiles // at the end of the computation // template void SolveSubgames(const BehavSupport &p_support, const DVector &p_templateSolution, SolverType p_solver, GameNode n, List > &solns, List &values) { Game efg = p_support.GetGame(); List > thissolns; thissolns.Append(p_templateSolution); ((Vector &) thissolns[1]).operator=(T(0)); List subroots; for (int i = 1; i <= n->NumChildren(); i++) { ChildSubgames(n->GetChild(i), subroots); } List > subrootvalues; subrootvalues.Append(Array(subroots.Length())); for (int i = 1; i <= subroots.Length(); i++) { //printf("Looking at subgame %d of %d\n", i, subroots.Length()); List > subsolns; List subvalues; SolveSubgames(p_support, p_templateSolution, p_solver, subroots[i], subsolns, subvalues); if (subsolns.Length() == 0) { solns = List >(); return; } //printf("Found %d subsolutions for subgame %d of %d\n", //subsolns.Length(), i, subroots.Length()); List > newsolns; List > newsubrootvalues; //printf("Merging with %d existing solutions\n", thissolns.Length()); for (int soln = 1; soln <= thissolns.Length(); soln++) { for (int subsoln = 1; subsoln <= subsolns.Length(); subsoln++) { //printf("Merging existing %d with new %d\n", soln, subsoln); DVector bp(thissolns[soln]); DVector tmp(subsolns[subsoln]); for (int j = 1; j <= bp.Length(); j++) { bp[j] += tmp[j]; } newsolns.Append(bp); newsubrootvalues.Append(subrootvalues[soln]); newsubrootvalues[newsubrootvalues.Length()][i] = subvalues[subsoln]; } } thissolns = newsolns; subrootvalues = newsubrootvalues; //printf("Finished solving subgame %d\n", i); } for (int soln = 1; soln <= thissolns.Length(); soln++) { //printf("Analyzing scenario %d of %d\n", soln, thissolns.Length()); for (int i = 1; i <= subroots.Length(); i++) { subroots[i]->SetOutcome(subrootvalues[soln][i]); } Game subgame = CopyGame(efg, n); // this prevents double-counting of outcomes at roots of subgames // by convention, we will just put the payoffs in the parent subgame subgame->GetRoot()->SetOutcome(0); BehavSupport subsupport(subgame); // Here, we build the support for the subgame /* for (int pl = 1; pl <= subgame->NumPlayers(); pl++) { GamePlayer subplayer = subgame->GetPlayer(pl); GamePlayer player = p_support.GetGame()->GetPlayer(pl); for (int iset = 1; iset <= subplayer->NumInfosets(); iset++) { GameInfoset subinfoset = subplayer->GetInfoset(iset); for (int j = 1; j <= player->NumInfosets(); j++) { GameInfoset infoset = player->GetInfoset(j); if (subinfoset->GetLabel() == infoset->GetLabel()) { for (int act = 1; act <= infoset->NumActions(); act++) { if (!p_support.Contains(infoset->GetAction(act))) { subsupport.RemoveAction(subinfoset->GetAction(act)); } } break; } } } } */ List > sol = (*p_solver)(subsupport); if (sol.Length() == 0) { solns = List >(); //printf("No solutions found\n"); return; } // Put behavior profile in "total" solution here... for (int solno = 1; solno <= sol.Length(); solno++) { solns.Append(thissolns[soln]); for (int pl = 1; pl <= subgame->NumPlayers(); pl++) { GamePlayer subplayer = subgame->GetPlayer(pl); GamePlayer player = p_support.GetGame()->GetPlayer(pl); for (int iset = 1; iset <= subplayer->NumInfosets(); iset++) { GameInfoset subinfoset = subplayer->GetInfoset(iset); for (int j = 1; j <= player->NumInfosets(); j++) { if (subinfoset->GetLabel() == player->GetInfoset(j)->GetLabel()) { int id = atoi(subinfoset->GetLabel().c_str()); for (int act = 1; act <= subsupport.NumActions(pl, iset); act++) { int actno = subsupport.GetAction(pl, iset, act)->GetNumber(); solns[solns.Length()](pl, id, actno) = sol[solno](pl, iset, act); } break; } } } } Vector subval(subgame->NumPlayers()); GameOutcome outcome = n->GetOutcome(); for (int pl = 1; pl <= subgame->NumPlayers(); pl++) { subval[pl] = sol[solno].GetPayoff(pl); if (outcome) { subval[pl] += outcome->GetPayoff(pl); } } GameOutcome ov = efg->NewOutcome(); for (int pl = 1; pl <= efg->NumPlayers(); pl++) { ov->SetPayoff(pl, ToText(subval[pl])); } values.Append(ov); } //printf("Finished with scenario %d of %d; total solutions so far = %d\n", //soln, thissolns.Length(), solns.Length()); } n->DeleteTree(); } template List > SolveBySubgames(const BehavSupport &p_support, SolverType p_solver) { Game efg = CopyGame(p_support.GetGame(), p_support.GetGame()->GetRoot()); for (int pl = 1; pl <= efg->NumPlayers(); pl++) { for (int iset = 1; iset <= efg->GetPlayer(pl)->NumInfosets(); iset++) { efg->GetPlayer(pl)->GetInfoset(iset)->SetLabel(ToText(iset)); } } BehavSupport support(efg); for (int pl = 1; pl <= efg->NumPlayers(); pl++) { GamePlayer player = p_support.GetGame()->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); for (int act = 1; act <= infoset->NumActions(); act++) { if (!p_support.Contains(infoset->GetAction(act))) { support.RemoveAction(efg->GetPlayer(pl)->GetInfoset(iset)->GetAction(act)); } } } } List > vectors; List values; SolveSubgames(support, DVector(support.NumActions()), p_solver, efg->GetRoot(), vectors, values); List > solutions; for (int i = 1; i <= vectors.Length(); i++) { solutions.Append(MixedBehavProfile(p_support)); for (int j = 1; j <= vectors[i].Length(); j++) { solutions[i][j] = vectors[i][j]; } } return solutions; } // // Explicit instantiations follow // template List > SolveBySubgames(const BehavSupport &p_support, DoubleSolver p_solver); template List > SolveBySubgames(const BehavSupport &p_support, RationalSolver p_solver); } // end namespace Gambit gambit-0.2010.09.01/src/libgambit/subgame.h0000644000076500007650000000254111435216101014751 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/subgame.h // Utilities for computing and verifying subgame-perfection // // 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 LIBGAMBIT_SUBGAME_H #define LIBGAMBIT_SUBGAME_H namespace Gambit { typedef List > (*DoubleSolver)(const BehavSupport &p_support); typedef List > (*RationalSolver)(const BehavSupport &p_support); template List > SolveBySubgames(const BehavSupport &p_support, SolverType p_solver); } #endif // LIBGAMBIT_SUBGAME_H gambit-0.2010.09.01/src/libgambit/vector.cc0000644000076500007650000000220711435216101014765 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/vector.cc // Instantiation of vector types // // 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 "libgambit.h" #include "vector.imp" template class Gambit::Vector; template class Gambit::Vector; template class Gambit::Vector; template class Gambit::Vector; template class Gambit::Vector; gambit-0.2010.09.01/src/libgambit/vector.h0000644000076500007650000000457411435216101014640 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/vector.h // A vector class // // 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 LIBGAMBIT_VECTOR_H #define LIBGAMBIT_VECTOR_H namespace Gambit { template class Matrix; /// A mathematical vector: a list of numbers with the standard math operators template class Vector : public Array { friend class Matrix; public: /** Create a vector of length len, starting at 1 */ Vector(unsigned int len = 0); /** Create a vector indexed from low to high */ Vector(int low, int high); /** Copy constructor */ Vector(const Vector& V); /** Destructor */ virtual ~Vector(); /** Assignment operator: requires vectors to be of same length */ Vector& operator=(const Vector& V); /** Assigns the value c to all components of the vector */ Vector& operator=(T c); Vector operator+(const Vector& V) const; Vector& operator+=(const Vector& V); Vector operator-(void); Vector operator-(const Vector& V) const; Vector& operator-=(const Vector& V); Vector operator*(T c) const; Vector& operator*=(T c); T operator*(const Vector& V) const; Vector operator/(T c) const; bool operator==(const Vector& V) const; bool operator!=(const Vector& V) const; /** Tests if all components of the vector are equal to a constant c */ bool operator==(T c) const; bool operator!=(T c) const; // square of length T NormSquared() const; // check vector for identical boundaries bool Check(const Vector &v) const; }; } // end namespace Gambit #endif // LIBGAMBIT_VECTOR_H gambit-0.2010.09.01/src/libgambit/vector.imp0000644000076500007650000001211711435216101015166 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/libgambit/vector.imp // Implementation of vector class // // 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 "vector.h" namespace Gambit { //------------------------------------------------------------------------ // Vector: Constructors, destructor, constructive operators //------------------------------------------------------------------------ template Vector::Vector(unsigned int len) : Array(len) { } template Vector::Vector(int low, int high) : Array(low, high) { } template Vector::Vector(const Vector &V) : Array(V) { } template Vector::~Vector() { } template Vector& Vector::operator=(const Vector& V) { if (!Check(V)) throw DimensionException(); Array::operator=(V); return *this; } //------------------------------------------------------------------------ // inline arithmetic operators //------------------------------------------------------------------------ template bool Vector::operator!=(const Vector &V) const { return !(*this == V); } template bool Vector::operator!=(T c) const { return !(*this == c); } //------------------------------------------------------------------------ // inline internal functions //------------------------------------------------------------------------ template bool Vector::Check(const Vector &v) const { return (v.mindex == this->mindex && v.maxdex == this->maxdex ); } //------------------------------------------------------------------------ // Vector: arithmetic operators //------------------------------------------------------------------------ template Vector& Vector::operator=(T c) { for(int i=this->mindex; i<=this->maxdex; i++) (*this)[i]= c; return (*this); } // arithmetic operators template Vector Vector::operator+(const Vector& V) const { if (!Check(V)) throw DimensionException(); Vector tmp(this->mindex,this->maxdex); for(int i=this->mindex; i<=this->maxdex; i++) tmp[i]= (*this)[i] + V[i]; return tmp; } template Vector Vector::operator-(const Vector& V) const { if (!Check(V)) throw DimensionException(); Vector tmp(this->mindex,this->maxdex); for(int i=this->mindex; i<=this->maxdex; i++) tmp[i]= (*this)[i] - V[i]; return tmp; } template Vector& Vector::operator+=(const Vector& V) { if (!Check(V)) throw DimensionException(); for(int i=this->mindex; i<=this->maxdex; i++) (*this)[i] += V[i]; return (*this); } template Vector& Vector::operator-=(const Vector& V) { if (!Check(V)) throw DimensionException(); for(int i=this->mindex; i<=this->maxdex; i++) (*this)[i] -= V[i]; return (*this); } template Vector Vector::operator-(void) { Vector tmp(this->mindex,this->maxdex); for(int i=this->mindex; i<=this->maxdex; i++) tmp[i]= -(*this)[i]; return tmp; } template Vector Vector::operator*(T c) const { Vector tmp(this->mindex,this->maxdex); for(int i=this->mindex; i<=this->maxdex; i++) tmp[i]= (*this)[i]*c; return tmp; } template Vector &Vector::operator*=(T c) { for(int i=this->mindex; i<=this->maxdex; i++) (*this)[i] *= c; return (*this); } template T Vector::operator*(const Vector& V) const { if (!Check(V)) throw DimensionException(); T sum= (T)0; for(int i=this->mindex; i<=this->maxdex; i++) sum += (*this)[i] * V[i]; return sum; } template Vector Vector::operator/(T c) const { Vector tmp(this->mindex,this->maxdex); for(int i=this->mindex; i<=this->maxdex; i++) tmp[i]= (*this)[i]/c; return tmp; } template bool Vector::operator==(const Vector& V) const { if (!Check(V)) throw DimensionException(); for(int i=this->mindex; i<=this->maxdex; i++) if( (*this)[i] != V[i] ) return false; return true; } template bool Vector::operator==(T c) const { for(int i=this->mindex; i<=this->maxdex; i++) if( (*this)[i] != c ) return false; return true; } template T Vector::NormSquared(void) const { T answer = (T)0; for (int i = 1; i <= this->Length(); i++) answer += (*this)[i] * (*this)[i]; return answer; } } // end namespace Gambit gambit-0.2010.09.01/src/tools/0000777000076500007650000000000011441457126012460 500000000000000gambit-0.2010.09.01/src/tools/convert/0000777000076500007650000000000011441457126014140 500000000000000gambit-0.2010.09.01/src/tools/convert/nfg2html.cc0000644000076500007650000001220311435216101016067 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/convert/nfg2html.cc // Convert a normal form game to HTML // // 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 #include #include #include #include "libgambit/libgambit.h" void WriteHtmlFile(std::ostream &p_file, const Gambit::Game &p_nfg, int p_rowPlayer, int p_colPlayer) { std::string theHtml; theHtml += "

" + p_nfg->GetTitle() + "

\n"; for (Gambit::StrategyIterator iter(p_nfg, p_rowPlayer, 1, p_colPlayer, 1); !iter.AtEnd(); iter++) { if (p_nfg->NumPlayers() > 2) { theHtml += "
Subtable with strategies:
"; for (int pl = 1; pl <= p_nfg->NumPlayers(); pl++) { if (pl == p_rowPlayer || pl == p_colPlayer) { continue; } theHtml += "
Player "; theHtml += Gambit::ToText(pl); theHtml += " Strategy "; theHtml += Gambit::ToText(iter->GetStrategy(pl)->GetNumber()); theHtml += "
"; } } theHtml += ""; theHtml += ""; theHtml += ""; for (int st = 1; st <= p_nfg->GetPlayer(p_colPlayer)->NumStrategies(); st++) { theHtml += ""; } theHtml += ""; for (int st1 = 1; st1 <= p_nfg->GetPlayer(p_rowPlayer)->NumStrategies(); st1++) { Gambit::PureStrategyProfile profile(*iter); profile.SetStrategy(p_nfg->GetPlayer(p_rowPlayer)->GetStrategy(st1)); theHtml += ""; theHtml += ""; for (int st2 = 1; st2 <= p_nfg->GetPlayer(p_colPlayer)->NumStrategies(); st2++) { profile.SetStrategy(p_nfg->GetPlayer(p_colPlayer)->GetStrategy(st2)); theHtml += ""; } theHtml += ""; } theHtml += "
"; theHtml += p_nfg->GetPlayer(p_colPlayer)->GetStrategy(st)->GetLabel(); theHtml += "
"; theHtml += p_nfg->GetPlayer(p_rowPlayer)->GetStrategy(st1)->GetLabel(); theHtml += ""; for (int pl = 1; pl <= p_nfg->NumPlayers(); pl++) { if (profile.GetOutcome()) { theHtml += profile.GetOutcome()->GetPayoff(pl); } else { theHtml += "0"; } if (pl < p_nfg->NumPlayers()) { theHtml += ","; } } theHtml += "
"; } theHtml += "\n"; p_file << theHtml; } void PrintBanner(std::ostream &p_stream) { p_stream << "Convert a Gambit .nfg file to HTML tables\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts strategic game on standard input.\n"; std::cerr << "Converts a Gambit .nfg file to HTML tables\n"; std::cerr << "Options:\n"; std::cerr << " -c PLAYER the player to show on columns (default is 2)\n"; std::cerr << " -r PLAYER the player to show on rows (default is 1)\n"; std::cerr << " -h print this help message\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; exit(1); } int main(int argc, char *argv[]) { int c; int rowPlayer = 1, colPlayer = 2; bool quiet = false; while ((c = getopt(argc, argv, "r:c:hq")) != -1) { switch (c) { case 'r': rowPlayer = atoi(optarg); break; case 'c': colPlayer = atoi(optarg); break; case 'q': quiet = true; break; case 'h': PrintHelp(argv[0]); break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } if (rowPlayer == colPlayer) { std::cerr << argv[0] << ": Row and column players must be different.\n"; return 1; } Gambit::Game nfg; try { nfg = Gambit::ReadGame(std::cin); } catch (...) { return 1; } if (rowPlayer < 1 || rowPlayer > nfg->NumPlayers()) { std::cerr << argv[0] << ": Player " << rowPlayer << " does not exist.\n"; } if (colPlayer < 1 || colPlayer > nfg->NumPlayers()) { std::cerr << argv[0] << ": Player " << colPlayer << " does not exist.\n"; } WriteHtmlFile(std::cout, nfg, rowPlayer, colPlayer); return 0; } gambit-0.2010.09.01/src/tools/convert/nfg2tex.cc0000644000076500007650000001273711435216101015737 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/convert/nfg2tex.cc // Convert a normal form game to LaTeX (using Osborne's sgame style) // // 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 #include #include #include #include "libgambit/libgambit.h" void WriteOsborneFile(std::ostream &p_file, const Gambit::Game &p_nfg, int p_rowPlayer, int p_colPlayer) { std::string theHtml; for (Gambit::StrategyIterator iter(p_nfg, p_rowPlayer, 1, p_colPlayer, 1); !iter.AtEnd(); iter++) { theHtml += "\\begin{game}{"; theHtml += Gambit::ToText(p_nfg->GetPlayer(p_rowPlayer)->NumStrategies()); theHtml += "}{"; theHtml += Gambit::ToText(p_nfg->GetPlayer(p_colPlayer)->NumStrategies()); theHtml += "}["; theHtml += p_nfg->GetPlayer(p_rowPlayer)->GetLabel(); theHtml += "]["; theHtml += p_nfg->GetPlayer(p_colPlayer)->GetLabel(); theHtml += "]"; if (p_nfg->NumPlayers() > 2) { theHtml += "["; for (int pl = 1; pl <= p_nfg->NumPlayers(); pl++) { if (pl == p_rowPlayer || pl == p_colPlayer) { continue; } theHtml += "Player "; theHtml += Gambit::ToText(pl); theHtml += " Strategy "; theHtml += Gambit::ToText(iter->GetStrategy(pl)->GetNumber()); theHtml += " "; } theHtml += "]"; } theHtml += "\n&"; for (int st = 1; st <= p_nfg->GetPlayer(p_colPlayer)->NumStrategies(); st++) { theHtml += p_nfg->GetPlayer(p_colPlayer)->GetStrategy(st)->GetLabel(); if (st < p_nfg->GetPlayer(p_colPlayer)->NumStrategies()) { theHtml += " & "; } } theHtml += "\\\\\n"; for (int st1 = 1; st1 <= p_nfg->GetPlayer(p_rowPlayer)->NumStrategies(); st1++) { Gambit::PureStrategyProfile profile(*iter); profile.SetStrategy(p_nfg->GetPlayer(p_rowPlayer)->GetStrategy(st1)); theHtml += p_nfg->GetPlayer(p_rowPlayer)->GetStrategy(st1)->GetLabel(); theHtml += " & "; for (int st2 = 1; st2 <= p_nfg->GetPlayer(p_colPlayer)->NumStrategies(); st2++) { profile.SetStrategy(p_nfg->GetPlayer(p_colPlayer)->GetStrategy(st2)); theHtml += " $"; for (int pl = 1; pl <= p_nfg->NumPlayers(); pl++) { if (profile.GetOutcome()) { theHtml += profile.GetOutcome()->GetPayoff(pl); } else { theHtml += "0"; } if (pl < p_nfg->NumPlayers()) { theHtml += ","; } } theHtml += "$ "; if (st2 < p_nfg->GetPlayer(p_colPlayer)->NumStrategies()) { theHtml += " & "; } } if (st1 < p_nfg->GetPlayer(p_rowPlayer)->NumStrategies()) { theHtml += "\\\\\n"; } } theHtml += "\n\\end{game}"; } theHtml += "\n"; p_file << theHtml; } void PrintBanner(std::ostream &p_stream) { p_stream << "Convert a Gambit .nfg file to LaTeX tables\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts strategic game on standard input.\n"; std::cerr << "Converts a Gambit .nfg file to LaTeX tables\n"; std::cerr << "Options:\n"; std::cerr << " -c PLAYER the player to show on columns (default is 2)\n"; std::cerr << " -r PLAYER the player to show on rows (default is 1)\n"; std::cerr << " -h print this help message\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; exit(1); } int main(int argc, char *argv[]) { int c; int rowPlayer = 1, colPlayer = 2; bool quiet = false; while ((c = getopt(argc, argv, "r:c:hq")) != -1) { switch (c) { case 'r': rowPlayer = atoi(optarg); break; case 'c': colPlayer = atoi(optarg); break; case 'q': quiet = true; break; case 'h': PrintHelp(argv[0]); break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (rowPlayer == colPlayer) { std::cerr << argv[0] << ": Row and column players must be different.\n"; return 1; } if (!quiet) { PrintBanner(std::cerr); } Gambit::Game nfg; try { nfg = Gambit::ReadGame(std::cin); } catch (...) { return 1; } if (rowPlayer < 1 || rowPlayer > nfg->NumPlayers()) { std::cerr << argv[0] << ": Player " << rowPlayer << " does not exist.\n"; } if (colPlayer < 1 || colPlayer > nfg->NumPlayers()) { std::cerr << argv[0] << ": Player " << colPlayer << " does not exist.\n"; } WriteOsborneFile(std::cout, nfg, rowPlayer, colPlayer); return 0; } gambit-0.2010.09.01/src/tools/enummixed/0000777000076500007650000000000011441457116014452 500000000000000gambit-0.2010.09.01/src/tools/enummixed/basis.cc0000644000076500007650000001030011435216101015756 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/basis.cc // Implementation of Basis class // // 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 "basis.h" // --------------------------------------------------------------------------- // Class Basis // --------------------------------------------------------------------------- // ----------------------- // C-tor, D-tor, Operators // ----------------------- Basis::Basis(int first, int last, int firstlabel, int lastlabel) : basis(first, last), cols(firstlabel, lastlabel), slacks(first, last), colBlocked(firstlabel,lastlabel), rowBlocked(first,last) { int i; for(i = cols.First(); i <= cols.Last(); i++) { cols[i] = 0; colBlocked[i] = false; } for(i = basis.First(); i <= basis.Last(); i++) { basis[i]= - i; slacks[i] = i; rowBlocked[i] = false; } IsBasisIdent = true; } Basis::Basis(const Basis &bas) : basis(bas.basis), cols( bas.cols ), slacks( bas.slacks ), colBlocked(bas.colBlocked), rowBlocked(bas.rowBlocked), IsBasisIdent(bas.IsBasisIdent) { } Basis::~Basis() { } Basis& Basis::operator=(const Basis &orig) { if(this != &orig) { basis = orig.basis; cols = orig.cols; slacks = orig.slacks; rowBlocked = orig.rowBlocked; colBlocked = orig.colBlocked; IsBasisIdent = orig.IsBasisIdent; } return *this; } // ------------------------- // Public Members // ------------------------- int Basis::First() const { return basis.First();} int Basis::Last() const { return basis.Last();} int Basis::MinCol() const { return cols.First();} int Basis::MaxCol() const { return cols.Last();} bool Basis::IsRegColumn( int col ) const {return col >= cols.First() && col <= cols.Last();} bool Basis::IsSlackColumn( int col ) const {return -col >= basis.First() && -col <= basis.Last();} int Basis::Pivot(int outindex, int col) { int outlabel = basis[outindex]; if (IsSlackColumn(col)) slacks[-col] = outindex; else if (IsRegColumn(col)) cols[col] = outindex; else throw Gambit::IndexException(); // not a valid column to pivot in. if (IsSlackColumn(outlabel)) slacks[-outlabel] = 0; else if (IsRegColumn(outlabel)) cols[outlabel] = 0; else { // Note: here, should back out outindex. throw Gambit::IndexException(); // not a valid column to pivot out. } basis[outindex] = col; CheckBasis(); return outlabel; } bool Basis::Member( int col ) const { int ret; if (IsSlackColumn(col)) ret = slacks[-col]; else if (IsRegColumn(col)) ret = cols[col]; else ret = 0; return (ret != 0); } int Basis::Find( int col ) const { int ret; if ( IsSlackColumn(col)) ret = slacks[-col]; else if (IsRegColumn(col)) ret = cols[col]; else throw Gambit::IndexException(); return ret; } int Basis::Label(int index) const { return basis[index]; } void Basis::Mark(int col ) { if (IsSlackColumn(col)) rowBlocked[-col] = true; else if (IsRegColumn(col)) colBlocked[col] = true; } void Basis::UnMark(int col ) { if (IsSlackColumn(col)) rowBlocked[-col] = false; else if (IsRegColumn(col)) colBlocked[col] = false; } bool Basis::IsBlocked(int col) const { if (IsSlackColumn(col)) return rowBlocked[-col]; else if (IsRegColumn(col)) return colBlocked[col]; return false; } void Basis::CheckBasis() { bool check = true; for (int i =basis.First(); i <= basis.Last() && check; i++) if(basis[i] != -i) check = false; IsBasisIdent = check; } bool Basis::IsIdent() { return IsBasisIdent; } gambit-0.2010.09.01/src/tools/enummixed/basis.h0000644000076500007650000000544511435216101015636 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/basis.h // Declaration of basis class for tableaus // // 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 BASIS_H #define BASIS_H #include "libgambit/libgambit.h" //--------------------------------------------------------------------------- // Class Basis //--------------------------------------------------------------------------- class Basis { private: Gambit::Array basis; // current members of basis (neg for slacks) Gambit::Array cols; // location of col in basis (0 if not in basis) Gambit::Array slacks; // location of slacks in basis Gambit::Array colBlocked; Gambit::Array rowBlocked; bool IsBasisIdent; public: //------------------------------------------- // Constructors, Destructor, Operators //------------------------------------------- Basis(int first, int last, int firstlabel, int lastlabel); Basis(const Basis &); virtual ~Basis(); Basis& operator=(const Basis&); //------------------------------ // Public Members //------------------------------ int First() const; // First basis index int Last() const; // Last basis index int MinCol() const; // First Column label int MaxCol() const; // Last Column label bool IsRegColumn( int col ) const; bool IsSlackColumn( int col ) const; //remove outindex, insert label, return outlabel int Pivot(int outindex, int col); // return true iff label is a Basis member bool Member(int label) const; // finds Basis index corresponding to label number, int Find(int label) const; // finds label of variable corresponding to Basis index int Label(int index) const; // marks/unmarks label to block it from entering basis void Mark(int label); void UnMark(int label); // returns true if label is blocked from entering basis bool IsBlocked(int label) const; // Check if Basis is Ident virtual void CheckBasis(); // returns whether the basis is the identity matrix bool IsIdent(); }; #endif // BASIS_H gambit-0.2010.09.01/src/tools/enummixed/bfs.cc0000644000076500007650000000333511435216101015441 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/bfs.cc // Implementation of basic feasible solution class // // 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 "bfs.h" //-------------------------------------------------------------------------- // class BFS: member functions //-------------------------------------------------------------------------- template BFS::BFS(void) : Gambit::Map((T) 0) { } template BFS::BFS(const T &d) : Gambit::Map((T) d) { } template BFS::BFS(const BFS &m) : Gambit::Map(m) { } template int BFS::operator==(const BFS &M) const { if (this->length != M.length) return 0; for (int i = 0; i < this->length; i++) if (this->keys[i] != M.keys[i]) return 0; return 1; } template int BFS::operator!=(const BFS &M) const { return !(*this == M); } template class BFS; template class BFS; gambit-0.2010.09.01/src/tools/enummixed/bfs.h0000644000076500007650000000240711435216101015302 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/bfs.h // Interface to basic feasible solution class // // 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 BFS_H #define BFS_H #include "libgambit/libgambit.h" template class BFS : public Gambit::Map { public: BFS(void); BFS(const T &d); BFS(const BFS &m); // define two BFS's to be equal if their bases are equal int operator==(const BFS &M) const; int operator!=(const BFS &M) const; }; #endif // BFS_H gambit-0.2010.09.01/src/tools/enummixed/btableau.cc0000644000076500007650000000224211435216101016442 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/btableau.cc // Instantiation of base tableau classes // // 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 "libgambit/libgambit.h" #include #include "btableau.imp" template class BaseTableau; template class BaseTableau; template class TableauInterface; template class TableauInterface; gambit-0.2010.09.01/src/tools/enummixed/btableau.h0000644000076500007650000001145111435216101016306 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/btableau.h // Interface to base tableau classes // // 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 BTABLEAU_H #define BTABLEAU_H #include "bfs.h" #include "basis.h" // --------------------------------------------------------------------------- // BaseTableau Stuff // --------------------------------------------------------------------------- template class BaseTableau { public: class BadPivot : public Gambit::Exception { public: virtual ~BadPivot() { } std::string GetDescription(void) const { return "Bad Pivot in BaseTableau"; } }; virtual ~BaseTableau() { } bool ColIndex(int) const; bool RowIndex(int) const; bool ValidIndex(int) const; virtual int MinRow() const = 0; virtual int MaxRow() const = 0; virtual int MinCol() const = 0; virtual int MaxCol() const = 0; virtual bool Member(int i) const = 0; // is variable i is a member of basis virtual int Label(int i) const = 0; // return variable in i'th position of Tableau virtual int Find(int i) const = 0; // return position of variable i // pivoting virtual int CanPivot(int outgoing,int incoming) = 0; virtual void Pivot(int outrow,int col) = 0; // perform pivot operation -- outgoing is row, incoming is column void CompPivot(int outlabel,int col); virtual long NumPivots() const = 0; // raw Tableau functions virtual void Refactor() = 0; }; // --------------------------------------------------------------------------- // TableauInterface Stuff // --------------------------------------------------------------------------- template class TableauInterface : public BaseTableau{ protected: const Gambit::Matrix *A; // should this be private? const Gambit::Vector *b; // should this be private? Basis basis; Gambit::Vector solution; // current solution vector. should this be private? long npivots; T eps1,eps2; Gambit::Array artificial; // artificial variables public: TableauInterface(const Gambit::Matrix &A, const Gambit::Vector &b); TableauInterface(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); TableauInterface(const TableauInterface&); virtual ~TableauInterface(); TableauInterface& operator=(const TableauInterface&); // information int MinRow() const; int MaxRow() const; int MinCol() const; int MaxCol() const; Basis & GetBasis(void); const Gambit::Matrix & Get_A(void) const; const Gambit::Vector & Get_b(void) const; bool Member(int i) const; int Label(int i) const; // return variable in i'th position of Tableau int Find(int i) const; // return Tableau position of variable i long NumPivots() const; long &NumPivots(); void Mark(int label); // marks label to block it from entering basis void UnMark(int label); // unmarks label bool IsBlocked(int label) const; // returns true if label is blocked virtual void BasisVector(Gambit::Vector &x) const = 0; // solve M x = (*b) void GetColumn( int , Gambit::Vector &) const; // raw column void GetBasis( Basis & ) const; // return Basis for current Tableau BFS GetBFS1(void) const; BFS GetBFS(void); // used in lpsolve for some reason virtual int CanPivot(int outgoing,int incoming) = 0; virtual void Pivot(int outrow,int col) = 0; // pivot -- outgoing is row, incoming is column virtual void SolveColumn(int, Gambit::Vector &) = 0; // column in new basis virtual void Solve(const Gambit::Vector &b, Gambit::Vector &x) = 0; // solve M x = b virtual void SolveT(const Gambit::Vector &c, Gambit::Vector &y) = 0; // solve y M = c virtual void Refactor() = 0; virtual void SetRefactor(int) = 0; // miscellaneous functions bool EqZero(T x) const; bool LtZero(T x) const; bool GtZero(T x) const; bool LeZero(T x) const; bool GeZero(T x) const; T Epsilon(int i = 2) const; bool IsArtifColumn(int col) const; }; #endif // BTABLEAU_H gambit-0.2010.09.01/src/tools/enummixed/btableau.imp0000644000076500007650000001506411435216101016650 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/btableau.imp // Implementation of base tableau classes // // 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. // // --------------------------------------------------------------------------- // BaseTableau method definitions // --------------------------------------------------------------------------- #include "btableau.h" template bool BaseTableau::ColIndex(int x) const { return MinCol()<=x && x<=MaxCol(); } template bool BaseTableau::RowIndex(int x) const { return MinRow()<=x && x<=MaxRow(); } template bool BaseTableau::ValidIndex(int x) const { return (ColIndex(x) || RowIndex(-x)); } template void BaseTableau::CompPivot(int outlabel, int col) { Pivot(Find(outlabel),col); Pivot(Find(-col),-outlabel); } // --------------------------------------------------------------------------- // TableauInterface method definitions // --------------------------------------------------------------------------- // Constructors and Destructor template TableauInterface::TableauInterface(const Gambit::Matrix &A, const Gambit::Vector &b) : A(&A), b(&b), basis(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()), solution(A.MinRow(),A.MaxRow()), npivots(0), artificial(A.MaxCol()+1,A.MaxCol()) { // These are the values recommended by Murtagh (1981) for 15 digit // accuracy in LP problems // Note: for gRational, eps1 and eps2 resolve to 0 Gambit::Epsilon(eps1,5); Gambit::Epsilon(eps2); } template TableauInterface::TableauInterface(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : A(&A), b(&b), basis(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()+art.Length()), solution(A.MinRow(),A.MaxRow()), npivots(0), artificial(A.MaxCol()+1,A.MaxCol()+art.Length()) { Gambit::Epsilon(eps1,5); Gambit::Epsilon(eps2); for(int i = 0;i TableauInterface::TableauInterface(const TableauInterface &orig) : A(orig.A), b(orig.b), basis(orig.basis), solution(orig.solution), npivots(orig.npivots), eps1(orig.eps1), eps2(orig.eps2), artificial(orig.artificial) { } template TableauInterface::~TableauInterface() { } template TableauInterface& TableauInterface::operator=(const TableauInterface &orig) { if(this!= &orig) { A = orig.A; b = orig.b; basis= orig.basis; solution= orig.solution; npivots = orig.npivots; artificial = orig.artificial; } return *this; } // getting information template int TableauInterface::MinRow() const { return A->MinRow(); } template int TableauInterface::MaxRow() const { return A->MaxRow(); } template int TableauInterface::MinCol() const { return basis.MinCol(); } template int TableauInterface::MaxCol() const { return basis.MaxCol(); } template Basis & TableauInterface::GetBasis(void) {return basis; } template const Gambit::Matrix & TableauInterface::Get_A(void) const {return *A; } template const Gambit::Vector & TableauInterface::Get_b(void) const {return *b;} template bool TableauInterface::Member(int i) const { return basis.Member(i);} template int TableauInterface::Label(int i) const { return basis.Label(i);} template int TableauInterface::Find(int i) const { return basis.Find(i);} template long TableauInterface::NumPivots() const { return npivots; } template long &TableauInterface::NumPivots() { return npivots; } template void TableauInterface::Mark(int label) {basis.Mark(label);} template void TableauInterface::UnMark(int label) {basis.UnMark(label);} template bool TableauInterface::IsBlocked(int label) const { return basis.IsBlocked(label); } template void TableauInterface::GetColumn(int col, Gambit::Vector &ret) const { if(IsArtifColumn(col)) { ret = (T) 0; ret[artificial[col]] = (T)1; } else if(basis.IsRegColumn(col)) A->GetColumn(col, ret); else if (basis.IsSlackColumn(col)) { ret = (T) 0; ret[-col] = (T) 1; } } template void TableauInterface::GetBasis(Basis &out) const { out= basis; } template BFS TableauInterface::GetBFS() { Gambit::Vector sol(basis.First(),basis.Last()); BasisVector(sol); BFS cbfs((T) 0); for(int i=MinCol();i<=MaxCol();i++) if(Member(i)) cbfs.Define(i,sol[basis.Find(i)]); return cbfs; } template BFS TableauInterface::GetBFS1() const { Gambit::Vector sol(basis.First(),basis.Last()); BasisVector(sol); BFS cbfs((T) 0); int i; for(i=-MaxRow();i<=-MinRow();i++) if(Member(i)) cbfs.Define(i,sol[basis.Find(i)]); for(i=MinCol();i<=MaxCol();i++) if(Member(i)) cbfs.Define(i,sol[basis.Find(i)]); return cbfs; } // miscellaneous functions template bool TableauInterface::EqZero(T x) const { return (LeZero(x) && GeZero(x)); } template bool TableauInterface::LtZero(T x) const { return !GeZero(x); } template bool TableauInterface::GtZero(T x) const { return !LeZero(x); } template bool TableauInterface::LeZero(T x) const { if(x <=eps2) return 1; return 0; } template bool TableauInterface::GeZero(T x) const { if(x >= -eps2) return 1; return 0; } template T TableauInterface::Epsilon(int i) const { if(i!=1 && i!=2) { throw Gambit::DimensionException(); } if(i==1) return eps1; return eps2; } template bool TableauInterface::IsArtifColumn(int col) const { return col>=artificial.First() && col<=artificial.Last(); } gambit-0.2010.09.01/src/tools/enummixed/clique.cc0000644000076500007650000005223711435216101016156 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/clique.cc // Maximal cliques and solution components via von Stengel's algorithm // // 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 "clique.h" #include "libgambit/libgambit.h" // to compile as standalone,compile with -DSTANDALONE #ifdef STANDALONE // =============== main =============== int main() { gArray edgelist1(MAXEDGES); int i,j, count = 0; while (scanf("%d %d", &i, &j) != EOF) { count ++; edgelist1[count].node1=i; edgelist1[count].node2=j; } gArray edgelist(count); for(int i=1;i<=count;i++) { edgelist[i].node1 = edgelist1[i].node1; edgelist[i].node2 = edgelist1[i].node2; } EnumCliques clique(edgelist,MAXINP1,MAXINP2); return 1 ; } // =============== end main =============== #endif // -------------------------------------------------- EnumCliques::EnumCliques(Gambit::Array &edgelist,int maxinp1,int maxinp2 ) : firstedge(MIN(maxinp1,maxinp2)+1), maxinp1(maxinp1), maxinp2(maxinp2) { int numco = getconnco(firstedge, edgelist); workonco(numco, firstedge, edgelist) ; }; EnumCliques::~EnumCliques() { }; void EnumCliques:: candtry1 (int stk[], // stack bool connected[MAXM][MAXN], int cand, // the candidate from NODES1 to be added to CLIQUE int clique1[], int cliqsize1, // CLIQUE so far in NODES1 int clique2[], int cliqsize2, // CLIQUE so far in NODES2 int sn1, int *sc1, int ec1, // start NOT1, start CAND1, end CAND1 int sn2, int sc2, int ec2, // start NOT2, start CAND2, end CAND2 int tos, // top of stack int orignode1[MAXM], int orignode2[MAXN] ) /* recurses down by moving cand from CAND1 to clique1 and then to NOT1 after extension. clique1 is extended by cand where all points in NOT2 and CAND2 relate to cand. pre: cand is in CAND1 post: cand is moved from CAND1 to NOT1 CAND1 may be shuffled, o/w stack unchanged */ { int i, j, snnew, scnew, ecnew; clique1[cliqsize1++] = cand ; // remove cand from CAND1 by replacing it with the last element of CAND1 for (i=*sc1; i= ec1, ec2 int orignode1[MAXM], // original node numbers as input int orignode2[MAXN] ) /* extends the current set CLIQUE or outputs it if NOT and CAND are empty. pre: CLIQUE = clique1[0, cliqsize1], clique2[0, cliqsize2] NOT1 = stk[sn1, sc1], CAND1= stk[sc1, ec1] NOT2 = stk[sn2, sc2], CAND2= stk[sc2, ec2] sn1 <= sc1 <= ec1, sn2 <= sc2 <= ec2 all cliques extending CLIQUE containing a node in NOT1 or NOT2 have already been generated post: output of all maximal cliques extending CLIQUE with candidates from CAND1 or CAND2 but not from NOT1, NOT2. */ { /* if no further extension is possible then output the current CLIQUE if applicable, and return */ if (sc1 == ec1 && sc2 == ec2) { // CAND is empty if (sn1 == sc1 && sn2 == sc2) // NOT is empty, otherwise do nothing outCLIQUE(clique1, cliqsize1, clique2, cliqsize2, orignode1, orignode2) ; } else { // CAND not empty int cmax; // maximal number of candidates on either side int firstlist, savelist, tmplist, posfix ; // stack positions int fixp; // the fixpoint int minnod ; bool bfound, bfixin1, bcandfix; cmax = MAX(ec1-sc1, ec2-sc2); // the larger of |CAND1|, |CAND2| // reserve two arrays of size cmax on the stack firstlist = tmplist = tos; tos += cmax; savelist = tos; // tos is not used again.. // tos += cmax; /* find fixpoint fixp (a node of the graph) in NOT or CAND which has the smallest possible number of disconnections minnod to CAND */ minnod = cmax + 1 ; // look for fixp in NODES1 findfixpoint(stk, connected, &savelist, &tmplist, &minnod, sn1, ec1, sc2, ec2, 1, &bfixin1, &fixp, &posfix) ; bcandfix = (posfix >= sc1); // look for fixp in nodes2 findfixpoint(stk, connected, &savelist, &tmplist, &minnod, sn2, ec2, sc1, ec1, 0, &bfound, &fixp, &posfix) ; if (bfound) { bfixin1 = false ; bcandfix = (posfix >= sc2); } /* now: fixp = the node that is the fixpoint, posfix = its position on the stack, bfixin1 = fixp is in NODES1 bcandfix = fixp is a candidate stk[savelist, +minnod] = nodes disconnected to fixp which are all either in CAND1 or in CAND2; */ /* top of stack can be reset to savelist+minnod where if savelist is the second of the two lists, recopy it to avoid that stk[firstlist, +cmax] is wasted */ if (savelist != firstlist) {int i; for (i=0; i < minnod; i++) stk[firstlist + i] = stk[savelist + i]; savelist = firstlist ; } tos = savelist + minnod; if (bfixin1) {int j; // fixpoint in NODES1 if (bcandfix) // fixpoint is a candidate candtry1(stk, connected, fixp, clique1, cliqsize1, clique2, cliqsize2, sn1, &sc1, ec1, sn2, sc2, ec2, tos, orignode1, orignode2); // fixpoint is now in NOT1, try all the nodes disconnected to it for (j=0; j &edgelist, int orignode1[MAXM], int orignode2[MAXN], bool connected[MAXM][MAXN], int *m, int *n ) /* generates the incidence matrix connected from the edgelist starting with edgelist[e] pre: all nodes in edgelist < maxinp1,2 post: orignode1[0..*m) contains the original node1 numbers orignode2[0..*n) contains the original node2 numbers connected[][] == true if edge, o/w false *m == number of rows *n == number of columns */ { Gambit::Array newnode1(0,maxinp1-1) ; Gambit::Array newnode2(0,maxinp2-1) ; int i,j, newi, newj ; // init newnode for (i=0; i= MAXM) { // out of bounds for connected, reject printf("Left bound %d for incidence matrix ", MAXM ) ; printf("reached, edge (%d, %d) rejected\n", i, j); goto KEEPGOING ; } else { int k; newi = (*m) ++ ; // init connected on the fly for (k=0; k= MAXN) { // out of bounds for connected, reject printf("Right bound %d for incidence matrix ", MAXN ) ; printf("reached, edge (%d, %d) rejected\n", i, j); goto KEEPGOING ; } else { newj = (*n) ++ ; newnode2[j] = newj ; orignode2[newj] = j ; } } connected[newi][newj] = true ; KEEPGOING: e = edgelist[e].nextedge ; } } // -------------------------------------------------- int EnumCliques::getconnco(Gambit::Array &firstedge, Gambit::Array &edgelist ) /* reads edges of bipartite graph from input, puts them in disjoint lists of edges representing its connected components pre: nodes are nonzero integers < maxinp1,2 other edges are rejected, and so are edges starting from the MAXEDGEth edge on and larger, each with a warning msg. post: return value == numco (largest index of a connected component) where numco < MAXCO, and for 1 <= co <= numco: edgelist[co].firstedge == 0 if co is not a component == edgeindex e otherwise where e > 0 and edgelist[e].node1, .node2[e] are endpoints of edge, edgelist[e].nextedge == next edgeindex of component, zero if e is index to the last edge */ { int numco, newedge ; Gambit::Array co1(0,maxinp1-1), co2(0,maxinp2-1); // components of node1,2 int i, j; // indices to left and right nodes // initialize component indices of left and right nodes for (i=0; i= maxinp1 || j<0 || j>=maxinp2) printf("Edge (%d, %d) not in admitted range (0..%d, 0..%d), rejected\n", i,j, maxinp1-1, maxinp2-1) ; else { // add edge (i,j) to current componentlist int ico, jco ; // current components of i,j ico = co1[i] ; jco = co2[j] ; if (ico == 0) { // i has not yet been in a component before if (jco == 0) { // j has not yet been in a component before // add a new component numco ++; co1[i] = co2[j] = numco ; firstedge[numco] = newedge ; edgelist[newedge].nextedge = 0; } else { /* j is already in a component: add i to j's component, adding list elements in front */ co1[i] = jco ; edgelist[newedge].nextedge = firstedge[jco]; firstedge[jco] = newedge; } } else { // i is already in a component if (jco == 0) { // j has not yet been in a component before // add j to i's component co2[j] = ico ; edgelist[newedge].nextedge = firstedge[ico]; firstedge[ico] = newedge; } else { // i and j are already in components if (ico == jco) { // i, j in same component: just add the current edge edgelist[newedge].nextedge = firstedge[ico]; firstedge[ico] = newedge; } else { /* i and j in different components: merge these by traversing the edgelists and updating components of all incident nodes (this is wasteful since only nodes need be updated, not edges) */ int e, newco, oldco ; if (ico < jco) { newco = ico; oldco = jco; } else { newco = jco; oldco = ico; } // insert the current edge edgelist[newedge].nextedge= firstedge[oldco] ; e = newedge ; while (1) { co1[edgelist[e].node1] = co2[edgelist[e].node2] = newco ; if (edgelist[e].nextedge == 0) break; e = edgelist[e].nextedge; } // e is now the last edge in the updated list edgelist[e].nextedge = firstedge[newco] ; firstedge[newco] = newedge ; /* oldco is unused now: reuse it if it was the last component, otherwise just leave empty */ if (oldco == numco) numco-- ; firstedge[oldco] = 0; } } } } } // end scanning input return numco; } // -------------------------------------------------- void EnumCliques::outCLIQUE(int clique1[], int cliqsize1, int clique2[], int cliqsize2, int orignode1[MAXM], int orignode2[MAXN] ) // outputs CLIQUE using the original node numbers in orignode { if (cliqsize1>0 && cliqsize2>0) { int i; //printf("{") ; Array cliq1; for (i=0; i cliq2; for (i=0; i &firstedge, Gambit::Array &edgelist ) /* works on the edgelists as generated by getconnco it processes each component by computing its maximal cliques pre : firstedge[1..numco], if nonzero, points to a connected component in edgelist post: all components are processed */ { int orignode1[MAXM]; int orignode2[MAXN]; bool connected[MAXM][MAXN]; int m; int n; // graph dimensions int stk[STKSIZE]; // stack int tos; // top of stack int clique1[MAXM], clique2[MAXN]; // CLIQUE for first and second node class int co; int countco = 0; for (co=1; co <= numco; co++) if (firstedge[co]) { // found a nonzero component list countco ++ ; //printf("\nConnected component %d:\n", countco) ; genincidence(firstedge[co], edgelist, orignode1, orignode2, connected, &m, &n); /* compute the cliques of the component via extend; initialize stack with the full sets of nodes and empty sets CAND and NOT */ tos = 0; { int i ; for (i=0; i=MAXM/2 will be rejected with a warning message post: connected[i][j] = true for the edges (i,j) of the bipartite graph, nodes numbered 0..*m-1 and 0..*n-1 m <= MAXM, n <= MAXN */ { int i, j; for (i=0; i= MAXM || j<0 || j>=MAXN) printf("Edge (%d, %d) not in admitted range (0..%d, 0..%d), rejected\n", i,j, MAXM-1, MAXN-1) ; else { connected[i][j] = true ; *m = MAX(*m, i+1) ; *n = MAX(*n, j+1) ; } } } // -------------------------------------------------- void EnumCliques::outgraph( int orignode1[MAXM], int orignode2[MAXN], bool connected[MAXM][MAXN], int m, int n ) /* prints the graph incidence matrix on standard output including information about original node numbers */ { int i, j; printf("\nConnected component: ") ; printf("%d columns of right hand side nodes are\n ", n) ; for (j=0; j #include "libgambit/libgambit.h" using namespace Gambit; #define MAX(A,B) ((A) > (B) ? (A) : (B)) #define MIN(A,B) ((A) < (B) ? (A) : (B)) #define MAXM 700 // max. no of left nodes for incidence matrix #define MAXN MAXM // max. no of right nodes for incidence matrix #define MAXINP1 5000 // max. no of left nodes in input #define MAXINP2 MAXINP1 // max. no of right nodes in input #define MAXEDGES 50000 // max. no of edges in input #define MAXCO MIN(MAXINP1, MAXINP2) + 1 // max. no of connected components; on the smaller side, // each node could be in different component #define STKSIZE (MAXM + 1) * (MAXN + 1) // largest stack usage for full graph class edge { public: int node1; int node2; int nextedge; edge() { }; ~edge() { } ; // gArray requires the following operators to exist bool operator ==( const edge &y) const { return (node1 == y.node1 && node2 == y.node2);} bool operator !=(const edge &y) const {return !(*this == y);} }; class EnumCliques { private: Array firstedge; int maxinp1,maxinp2; List > m_cliques1, m_cliques2; void candtry1 (int stk[], // stack bool connected[MAXM][MAXN], int cand, // the candidate from NODES1 to be added to CLIQUE int clique1[], int cliqsize1, // CLIQUE so far in NODES1 int clique2[], int cliqsize2, // CLIQUE so far in NODES2 int sn1, int *sc1, int ec1, // start NOT1, start CAND1, end CAND1 int sn2, int sc2, int ec2, // start NOT2, start CAND2, end CAND2 int tos, // top of stack int orignode1[MAXM], int orignode2[MAXN] ); void candtry2 (int stk[], // stack bool connected[MAXM][MAXN], int cand, // the candidate from NODES2 to be added to CLIQUE int clique1[], int cliqsize1, // CLIQUE so far in NODES1 int clique2[], int cliqsize2, // CLIQUE so far in NODES2 int sn1, int sc1, int ec1, // start NOT1, start CAND1, end CAND1 int sn2, int *sc2, int ec2, // start NOT2, start CAND2, end CAND2 int tos, // top of stack int orignode1[MAXM], int orignode2[MAXN]); void extend (int stk[], // stack bool connected[MAXM][MAXN], int clique1[], int cliqsize1, // CLIQUE so far in NODES1 int clique2[], int cliqsize2, // CLIQUE so far in NODES2 int sn1, int sc1, int ec1, // start NOT1, start CAND1, end CAND1 int sn2, int sc2, int ec2, // start NOT2, start CAND2, end CAND2 int tos, // top of stack, tos >= ec1, ec2 int orignode1[MAXM], // original node numbers as input int orignode2[MAXN]); void findfixpoint(int stk[], // stack bool connected[MAXM][MAXN], int *savelist, // position of savelist on the stack int *tmplist, // position of tmplist on the stack int *minnod, // currently lowest no. of disconnections int sninspect, int ecinspect, int scother, int ecother, bool binspect1, // inspected nodes are in class1, o/w class2 bool *bfound, // a new lower no. of disconnections was found int *fixp, // the new fixpoint, if *bfound = true int *posfix); // position of fixpoint on the stack, if *bfound public: EnumCliques(Array &, int, int); ~EnumCliques(); const List > &GetCliques1(void) const { return m_cliques1; } const List > &GetCliques2(void) const { return m_cliques2; } void genincidence(int e, Array &edgelist, int orignode1[MAXM], int orignode2[MAXN], bool connected[MAXM][MAXN], int *m, int *n); int getconnco(Array &firstedge, Array &edgelist); void outCLIQUE(int clique1[], int cliqsize1, int clique2[], int cliqsize2, int orignode1[MAXM], int orignode2[MAXN]); void workonco(int numco, Array &firstedge, Array &edgelist); /* --- the following are unused TEST ROUTINES --- */ void getgraph(bool connected[MAXM][MAXN], int *m, int *n); void outgraph(int orignode1[MAXM], int orignode2[MAXN], bool connected[MAXM][MAXN], int m, int n); }; #endif // CLIQUE_H gambit-0.2010.09.01/src/tools/enummixed/enummixed.cc0000644000076500007650000002603011435216101016657 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/enummixed.cc // Compute Nash equilibria via Mangasarian's algorithm // // 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 #include #include #include #include "vertenum.imp" #include "tableau.imp" #include "libgambit/libgambit.h" #include "clique.h" using namespace Gambit; bool g_showConnect = false; int g_numDecimals = 6; template bool EqZero(const T &x) { T eps; Epsilon(eps, 12); return (x <= eps && x >= -eps); } int m_stopAfter = 0; void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedStrategyProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << ',' << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedStrategyProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream << ',' << p_profile[i]; } p_stream << std::endl; } template void GetCliques(std::ostream &p_stream, const StrategySupport &p_support, const List &p_node1, const List > &p_key1, int p_v1, const List &p_node2, const List > &p_key2, int p_v2) { int n = p_node1.Length(); if (p_node2.Length() != n) throw DimensionException(); Array edgelist(n); //p_stream << "\nKey:\nPlayer 1:"; //for (int i = 1; i <= p_key1.Length(); i++) { //p_stream << "\n" << i << ":"; //for (int j = 1; j <= p_key1[i].Length(); j++) { // p_stream << " " << p_key1[i][j]; //} //p_stream << "\n"; //} //p_stream << "\nPlayer 2:"; //for (int i = 1; i <= p_key2.Length(); i++) { // p_stream << "\n" << i << ": "; // for (int j = 1; j <= p_key2[i].Length(); j++) { // p_stream << " " << p_key2[i][j]; // } //} //p_stream << "\nExtreme equilibria:"; for (int i = 1; i <= n; i++) { edgelist[i].node1 = p_node1[i]; edgelist[i].node2 = p_node2[i]; // p_stream << "\n" << p_node1[i] << " " << p_node2[i]; } EnumCliques clique(edgelist, p_v2+1, p_v1+1); const List > &cliques1 = clique.GetCliques1(); const List > &cliques2 = clique.GetCliques2(); for (int cl = 1; cl <= cliques1.Length(); cl++) { for (int i = 1; i <= cliques1[cl].Length(); i++) { for (int j = 1; j <= cliques2[cl].Length(); j++) { MixedStrategyProfile profile(p_support); for (int k = 1; k <= p_key1[cliques1[cl][i]].Length(); k++) { profile[k] = p_key1[cliques1[cl][i]][k]; } for (int k = 1; k <= p_key2[cliques2[cl][j]].Length(); k++) { profile[k + p_key1[cliques1[cl][i]].Length()] = p_key2[cliques2[cl][j]][k]; } PrintProfile(p_stream, "convex-" + ToText(cl), profile.ToFullSupport()); } } } } template void Solve(const StrategySupport &p_support) { List > key1, key2; List node1, node2; // IDs of each component of the extreme equilibria PureStrategyProfile profile(p_support.GetGame()); Rational min = p_support.GetGame()->GetMinPayoff(); if (min > Rational(0)) { min = Rational(0); } min -= Rational(1); Rational max = p_support.GetGame()->GetMaxPayoff(); if (max < Rational(0)) { max = Rational(0); } Rational fac(1, max - min); // Construct matrices A1, A2 Matrix A1(1, p_support.NumStrategies(1), 1, p_support.NumStrategies(2)); Matrix A2(1, p_support.NumStrategies(2), 1, p_support.NumStrategies(1)); for (int i = 1; i <= p_support.NumStrategies(1); i++) { profile.SetStrategy(p_support.GetStrategy(1, i)); for (int j = 1; j <= p_support.NumStrategies(2); j++) { profile.SetStrategy(p_support.GetStrategy(2, j)); A1(i, j) = fac * (profile.GetPayoff(1) - min); A2(j, i) = fac * (profile.GetPayoff(2) - min); } } // Construct vectors b1, b2 Vector b1(1, p_support.NumStrategies(1)); Vector b2(1, p_support.NumStrategies(2)); b1 = (T) -1; b2 = (T) -1; // enumerate vertices of A1 x + b1 <= 0 and A2 x + b2 <= 0 VertEnum poly1(A1, b1); VertEnum poly2(A2, b2); const List > &verts1(poly1.VertexList()); const List > &verts2(poly2.VertexList()); int v1 = verts1.Length(); int v2 = verts2.Length(); Array vert1id(v1); Array vert2id(v2); for (int i = 1; i <= vert1id.Length(); vert1id[i++] = 0); for (int i = 1; i <= vert2id.Length(); vert2id[i++] = 0); int i = 0; int id1 = 0, id2 = 0; try { for (int i2 = 2; i2 <= v2; i2++) { BFS bfs1 = verts2[i2]; i++; for (int i1 = 2; i1 <= v1; i1++) { BFS bfs2 = verts1[i1]; // check if solution is nash // need only check complementarity, since it is feasible bool nash = true; for (int k = 1; nash && k <= p_support.NumStrategies(1); k++) { if (bfs1.IsDefined(k) && bfs2.IsDefined(-k)) { nash = nash && EqZero(bfs1(k) * bfs2(-k)); } } for (int k = 1; nash && k <= p_support.NumStrategies(2); k++) { if (bfs2.IsDefined(k) && bfs1.IsDefined(-k)) { nash = nash && EqZero(bfs2(k) * bfs1(-k)); } } if (nash) { MixedStrategyProfile profile(p_support); T sum = (T) 0; for (int k = 1; k <= p_support.NumStrategies(1); k++) { profile[p_support.GetStrategy(1, k)] = (T) 0; if (bfs1.IsDefined(k)) { profile[p_support.GetStrategy(1, k)] = -bfs1(k); sum += profile[p_support.GetStrategy(1, k)]; } } for (int k = 1; k <= p_support.NumStrategies(1); k++) { if (bfs1.IsDefined(k)) { profile[p_support.GetStrategy(1, k)] /= sum; } } sum = (T) 0; for (int k = 1; k <= p_support.NumStrategies(2); k++) { profile[p_support.GetStrategy(2, k)] = (T) 0; if (bfs2.IsDefined(k)) { profile[p_support.GetStrategy(2, k)] =-bfs2(k); sum += profile[p_support.GetStrategy(2, k)]; } } for (int k = 1; k <= p_support.NumStrategies(2); k++) { if (bfs2.IsDefined(k)) { profile[p_support.GetStrategy(2, k)] /= sum; } } PrintProfile(std::cout, "NE", profile.ToFullSupport()); // note: The keys give the mixed strategy associated with each node. // The keys should also keep track of the basis // As things stand now, two different bases could lead to // the same key... BAD! if (vert1id[i1] == 0) { id1++; vert1id[i1] = id1; Vector probs(profile.GetSupport().NumStrategies(2)); for (SupportStrategyIterator strategy = profile.GetSupport().Strategies(profile.GetGame()->GetPlayer(2)); !strategy.AtEnd(); strategy++) { probs[strategy.GetIndex()] = profile[strategy]; } key2.Append(probs); } if (vert2id[i2] == 0) { id2++; vert2id[i2] = id2; Vector probs(profile.GetSupport().NumStrategies(1)); for (SupportStrategyIterator strategy = profile.GetSupport().Strategies(profile.GetGame()->GetPlayer(1)); !strategy.AtEnd(); strategy++) { probs[strategy.GetIndex()] = profile[strategy]; } key1.Append(probs); } node1.Append(vert2id[i2]); node2.Append(vert1id[i1]); } } } if (g_showConnect) { GetCliques(std::cout, p_support, node1, key1, v1, node2, key2, v2); } } catch (...) { // stop processing, just return equilibria found (if any) } } extern void LrsSolve(const StrategySupport &); void PrintBanner(std::ostream &p_stream) { p_stream << "Compute Nash equilibria by enumerating extreme points\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "Enumeration code based on lrslib 4.2b,\n"; p_stream << "Copyright (C) 1995-2005 by David Avis (avis@cs.mcgill.ca)\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "With no options, reports all Nash equilibria found.\n\n"; std::cerr << "Options:\n"; std::cerr << " -d DECIMALS compute using floating-point arithmetic;\n"; std::cerr << " display results with DECIMALS digits\n"; std::cerr << " -D don't eliminate dominated strategies first\n"; std::cerr << " -L use lrslib for enumeration (experimental!)\n"; std::cerr << " -c output connectedness information\n"; std::cerr << " -h print this help message\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; exit(1); } int main(int argc, char *argv[]) { int c; bool useFloat = false, uselrs = false, quiet = false, eliminate = true; while ((c = getopt(argc, argv, "d:DhqcS")) != -1) { switch (c) { case 'd': useFloat = true; g_numDecimals = atoi(optarg); break; case 'D': eliminate = false; break; case 'L': uselrs = true; break; case 'h': PrintHelp(argv[0]); break; case 'c': g_showConnect = true; break; case 'S': break; case 'q': quiet = true; break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Game game = ReadGame(std::cin); if (game->NumPlayers() != 2) { std::cerr << "Error: Game does not have two players.\n"; return 1; } game->BuildComputedValues(); StrategySupport support(game); if (eliminate) { while (true) { StrategySupport newSupport = support.Undominated(true); if (newSupport == support) break; support = newSupport; } } if (uselrs) { LrsSolve(support); } else if (useFloat) { Solve(support); } else { Solve(support); } return 0; } catch (InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } } gambit-0.2010.09.01/src/tools/enummixed/lptab.cc0000644000076500007650000000175611435216101015776 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/lptab.cc // Instantiation of LP tableau // // 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 "lptab.imp" template class LPTableau; template class LPTableau; gambit-0.2010.09.01/src/tools/enummixed/lptab.h0000644000076500007650000000602211435216101015627 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/lptab.h // Interface to LP tableaus // // 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. // // --------------------------------------------------------------------------- // LPTableau Stuff (For Linear Programming code) // --------------------------------------------------------------------------- #ifndef LPTAB_H #define LPTAB_H #include "tableau.h" template class LPTableau : public Tableau { private: Gambit::Vector dual; Gambit::Array unitcost; Gambit::Array cost; Gambit::Array UB,LB; // does col have upper/lower bound? Gambit::Array ub,lb; // upper/lower bound void SolveDual(); public: class BadPivot : public Gambit::Exception { public: virtual ~BadPivot(); std::string GetDescription(void) const; }; LPTableau(const Gambit::Matrix &A, const Gambit::Vector &b); LPTableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); LPTableau(const LPTableau&); virtual ~LPTableau(); LPTableau& operator=(const LPTableau&); // cost information void SetCost(const Gambit::Vector& ); // unit column cost := 0 void SetCost(const Gambit::Vector&, const Gambit::Vector& ); Gambit::Vector GetCost() const; Gambit::Vector GetUnitCost() const; T TotalCost(); // cost of current solution T RelativeCost(int) const; // negative index convention void RelativeCostVector(Gambit::Vector &, Gambit::Vector &); void DualVector(Gambit::Vector &) const; // column vector // Redefined functions void Refactor(); void Pivot(int outrow,int col); void ReversePivots(Gambit::List > &); bool IsReversePivot(int i, int j); void DualReversePivots(Gambit::List > &); bool IsDualReversePivot(int i, int j); BFS DualBFS(void) const; // returns the label of the index of the last artificial variable int LastLabel( void ); // select Basis elements according to Tableau rows and cols void BasisSelect(const Gambit::Array&rowv, Gambit::Vector &colv) const; // as above, but unit column elements nonzero void BasisSelect(const Gambit::Array&unitv, const Gambit::Array&rowv, Gambit::Vector&colv) const; }; #endif // LPTAB_H gambit-0.2010.09.01/src/tools/enummixed/lptab.imp0000644000076500007650000004642211435216101016175 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/lptab.imp // Implementation of LP tableaus // // 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 "lptab.h" // --------------------------------------------------------------------------- // LPTableau member definitions // --------------------------------------------------------------------------- template LPTableau::LPTableau(const Gambit::Matrix &A, const Gambit::Vector &b) : Tableau(A,b), dual(A.MinRow(),A.MaxRow()), unitcost(A.MinRow(),A.MaxRow()), cost(A.MinCol(),A.MaxCol()) { }; template LPTableau::LPTableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : Tableau(A,art,b), dual(A.MinRow(),A.MaxRow()), unitcost(A.MinRow(),A.MaxRow()), cost(A.MinCol(),A.MaxCol()+art.Length()) { }; template LPTableau::LPTableau(const LPTableau &orig) : Tableau(orig), dual(orig.dual), unitcost(orig.unitcost), cost(orig.cost) { } template LPTableau::~LPTableau() { } template LPTableau& LPTableau::operator=(const LPTableau &orig) { Tableau::operator=(orig); if(this!= &orig) { dual=orig.dual; unitcost= orig.unitcost; cost= orig.cost; } return *this; } // cost-based functions template<> void LPTableau::SetCost(const Gambit::Vector& c) { int i; if(cost.First()==c.First() && cost.Last()==c.Last()) { for(i=cost.First();i<=cost.Last();i++) cost[i] = c[i]*(Gambit::Rational)Tableau::TotDenom(); for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i] = (Gambit::Rational)0; Refactor(); SolveDual(); return; } if(c.First()!=cost.First()) throw Gambit::DimensionException(); if(c.Last()!=(cost.Last()+unitcost.Length())) throw Gambit::DimensionException(); for(i=c.First();i<=cost.Last();i++) cost[i]=c[i]*(Gambit::Rational)Tableau::TotDenom(); for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i]=c[cost.Length()+i-unitcost.First()+1]; // gout << "\nc: " << c.First() << " " << c.Last() << " " << c; // gout << "\ncost: " << cost.First() << " " << cost.Last() << " " << cost; // gout << "\nunit: " << unitcost.First() << " " << unitcost.Last() << " " << unitcost; //** added for Gambit::Rational Refactor(); SolveDual(); } template<> void LPTableau::SetCost(const Gambit::Vector& c) { int i; if(cost.First()==c.First() && cost.Last()==c.Last()) { for(i=cost.First();i<=cost.Last();i++) cost[i] = c[i]; for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i] = (double)0; Refactor(); SolveDual(); return; } if(c.First()!=cost.First()) throw Gambit::DimensionException(); if(c.Last()!=(cost.Last()+unitcost.Length())) throw Gambit::DimensionException(); for(i=c.First();i<=cost.Last();i++) cost[i]=c[i]; for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i]=c[cost.Length()+i-unitcost.First()+1]; // gout << "\nc: " << c.First() << " " << c.Last() << " " << c; // gout << "\ncost: " << cost.First() << " " << cost.Last() << " " << cost; // gout << "\nunit: " << unitcost.First() << " " << unitcost.Last() << " " << unitcost; //** added for Gambit::Rational Refactor(); SolveDual(); } template void LPTableau::SetCost(const Gambit::Vector &uc, const Gambit::Vector &c) { if(cost.First()!=c.First() || cost.Last()!=c.Last()) throw Gambit::DimensionException(); if(unitcost.First()!=uc.First() || unitcost.Last()!=uc.Last()) throw Gambit::DimensionException(); int i; for(i=cost.First();i<=cost.Last();i++) cost[i]=c[i]; for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i]=uc[i]; SolveDual(); } template Gambit::Vector LPTableau::GetCost(void) const { Gambit::Vector x(cost.First(),cost.Last()); for(int i=x.First();i<=x.Last();i++)x[i]=cost[i]; return x; // return cost; } template Gambit::Vector LPTableau::GetUnitCost(void) const { Gambit::Vector x(unitcost.First(),unitcost.Last()); for(int i=x.First();i<=x.Last();i++)x[i]=unitcost[i]; return x; } template<> double LPTableau::TotalCost(void) { Gambit::Vector tmpcol(MinRow(),MaxRow()); BasisSelect(unitcost,cost,tmpcol); return tmpcol*solution; } template<> Gambit::Rational LPTableau::TotalCost(void) { Gambit::Vector tmpcol(MinRow(),MaxRow()); Gambit::Vector sol(MinRow(),MaxRow()); BasisSelect(unitcost,cost,tmpcol); BasisVector(sol); for(int i=tmpcol.First();i<=tmpcol.Last();i++) if(Label(i)>0)tmpcol[i]/=(Gambit::Rational)Tableau::TotDenom(); return tmpcol*sol; } template<> void LPTableau::DualVector(Gambit::Vector &L) const { L= dual; } template<> void LPTableau::DualVector(Gambit::Vector &out) const { out= dual; // for(int i=out.First();i<=out.Last();i++) // if(Label(i)>=0) out[i]*=TotDenom(); } template T LPTableau::RelativeCost(int col) const { Gambit::Vector tmpcol(this->MinRow(),this->MaxRow()); if( col<0 ) { return unitcost[-col] - dual[-col]; } else { GetColumn(col, (Gambit::Vector &)tmpcol); return cost[col] - dual*tmpcol; } } /* template void LPTableau::RelativeCostVector(Gambit::Vector &relunitcost, Gambit::Vector &relcost) const { if(!A->CheckColumn(relunitcost)) throw Gambit::DimensionException(); if(!A->CheckRow(relcost)) throw Gambit::DimensionException(); relunitcost= unitcost - dual; relcost= cost - dual*A; // pre multiplication not defined? } */ template void LPTableau::SolveDual() { Gambit::Vector tmpcol1(this->MinRow(),this->MaxRow()); BasisSelect(unitcost,cost,tmpcol1); SolveT(tmpcol1,dual); } // Redefined functions template void LPTableau::Refactor() { // gout << "\nIn LPTableau::Refactor()"; Tableau::Refactor(); SolveDual(); } template void LPTableau::Pivot(int outrow,int col) { // gout << "\nIn LPTableau::Pivot() "; // gout << "outrow: " << outrow << " col: " << col; // BigDump(gout); Tableau::Pivot(outrow,col); SolveDual(); } template void LPTableau::ReversePivots(Gambit::List > &PivotList) { Gambit::Vector tmpcol(this->MinRow(),this->MaxRow()); // gout << "\nIn LPTableau::ReversePivots"; bool flag; int i,j,k,enter; T ratio,a_ij,a_ik,b_i,b_k,c_j,c_k,c_jo,x; Gambit::List BestSet; Gambit::Array pivot(2); Gambit::Vector tmpdual(this->MinRow(),this->MaxRow()); Gambit::Vector solution(tmpcol); //$$ BasisVector(solution); //$$ // BigDump(gout); // gout << "\ncost: " << GetCost(); // gout << "\nunitcost: " << GetUnitCost() << "\n"; // for(i=MinCol();i<=MaxCol();i++) gout << " " << RelativeCost(i); // for(i=MinRow();i<=MaxRow();i++) gout << " " << RelativeCost(-i); for(j=-this->MaxRow();j<=this->MaxCol();j++) if(j && !this->Member(j) && !this->IsBlocked(j)) { SolveColumn(j,tmpcol); // gout << "\nColumn " << j; // gout << "\nPivCol = " << tmpcol; // gout << "\ncurrentSolCol = " << solution; // find all i where prior tableau is primal feasible BestSet = Gambit::List(); for(i=this->MinRow();i<=this->MaxRow();i++) if(GtZero(tmpcol[i])) BestSet.Append(i); if(BestSet.Length()>0) { ratio = solution[BestSet[1]]/tmpcol[BestSet[1]]; // find max ratio for(i=2;i<=BestSet.Length();i++) { x = solution[BestSet[i]]/tmpcol[BestSet[i]]; if(GtZero(x-ratio)) ratio = x; } // eliminate nonmaximizers for(i=BestSet.Length();i>=1;i--) { x = solution[BestSet[i]]/tmpcol[BestSet[i]]; if(LtZero(x-ratio)) BestSet.Remove(i); } // check that j would be the row to exit in prior tableau // first check that prior pivot entry > 0 for(i=BestSet.Length();i>=1;i--) { a_ij = (T)1/tmpcol[BestSet[i]]; if(LeZero(a_ij)) { // gout << "\nj not row to exit in prior tableau: a_ij <= 0"; BestSet.Remove(i); } else { // next check that prior pivot entry attains max ratio b_i = solution[BestSet[i]]/tmpcol[BestSet[i]]; ratio = b_i/a_ij; flag = 0; for(k=tmpcol.First();k<=tmpcol.Last() && !flag;k++) if(k!=BestSet[i]) { a_ik = - a_ij * tmpcol[k]; b_k = solution[k] - b_i*tmpcol[k]; if(GtZero(a_ik) && GtZero(b_k/a_ik -ratio)) { // gout << "\nj not row to exit in prior tableau: "; // gout << "higher ratio at row= " << k; BestSet.Remove(i); flag = 1; } else if(GtZero(a_ik) && EqZero(b_k/a_ik-ratio) && this->Label(k)GetColumn(j,tmpcol); */ GetColumn(j,tmpcol); // gout << "\ncol " << j << ": " << tmpcol; a_ij = tmpdual*tmpcol; c_j = RelativeCost(j); if(EqZero(a_ij)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "a_ij=0"; BestSet.Remove(i); } else { ratio = c_j/a_ij; // gout << " ratio: " << ratio; if(enter<0) a_ik = tmpdual[-enter]; else { GetColumn(enter,tmpcol); // A->GetColumn(enter,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(enter); c_jo = c_k - a_ik * ratio; // gout << "\ntmpdual = " << tmpdual << "\n"; // gout << " c_j:" << c_j; // gout << " c_k:" << c_k; // gout << " c_jo:" << c_jo; // gout << " a_ij:" << a_ij; // gout << " a_ik:" << a_ik; if(GeZero(c_jo)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "c_jo<0"; BestSet.Remove(i); } else { flag=0; for(k=-this->b->Last();kGetColumn(k,tmpcol); GetColumn(k,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(k); c_jo = c_k - a_ik * ratio; if(LtZero(c_jo)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "c_jo < 0 for k = " << k; BestSet.Remove(i); flag=1; } } } } } // gout << "\nafter checking cols, BestSet = "; // BestSet.Dump(gout); if(BestSet.Length()>0) for(i=1;i<=BestSet.Length();i++) { pivot[1] = BestSet[i]; pivot[2] = j; PivotList.Append(pivot); } } } template bool LPTableau::IsReversePivot(int i, int j) { Gambit::Vector tmpcol(this->MinRow(),this->MaxRow()); // first check that pivot preserves primal feasibility // gout << "\nin IsReversePivot, i= " << i << " j = "<< j; SolveColumn(j,tmpcol); Gambit::Vector solution(tmpcol); //$$ BasisVector(solution); //$$ // gout << "\ncurrentPivCol = " << tmpcol; // gout << "\ncurrentSolCol = " << solution; if(LeZero(tmpcol[i])) { // gout << "\nPrior tableau not primal feasible: currentPivCol[i] <= 0"; return 0; } int k; T ratio = solution[i]/tmpcol[i]; // gout << "\nratio = " << ratio; for(k=tmpcol.First();k<=tmpcol.Last();k++) if(GtZero(tmpcol[k]) && GtZero(solution[k]/tmpcol[k]-ratio)) { // gout << "\nPrior tableau not primal feasible: i not min ratio"; return 0; } // check that j would be the row to exit in prior tableau T a_ij,a_ik,b_i,b_k,c_j,c_k,c_jo; a_ij = (T)1/tmpcol[i]; if(LeZero(a_ij)) { // gout << "\nj not row to exit in prior tableau: a_ij <= 0"; return 0; } b_i = solution[i]/tmpcol[i]; ratio = b_i/a_ij; for(k=tmpcol.First();k<=tmpcol.Last();k++) if(k!=i) { a_ik = - a_ij * tmpcol[k]; b_k = solution[k] - b_i*tmpcol[k]; if(GtZero(a_ik) && GtZero(b_k/a_ik -ratio)) { // gout << "\nj not row to exit in prior tableau: "; // gout << "higher ratio at row= " << k; return 0; } if(GtZero(a_ik) && EqZero(b_k/a_ik-ratio) && this->Label(k)GetColumn(enter,tmpcol); GetColumn(enter,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(enter); c_jo = c_k - a_ik * ratio; if(GeZero(c_jo)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "c_jo<0"; return 0; } for(k=-this->b->Last();kGetColumn(k,tmpcol); GetColumn(k,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(k); c_jo = c_k - a_ik * ratio; if(LtZero(c_jo)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "c_jo < 0 for k = " << k; return 0; } } // gout << "\nValid Reverse pivot at i = " << i << " j = " << j; return 1; } template void LPTableau::DualReversePivots(Gambit::List > &/*list*/) { } template bool LPTableau::IsDualReversePivot(int i, int j) { // first check that pivot preserves dual feasibility // gout << "\nin IsDualReversePivot, i= " << i << " j = "<< j; int k; Gambit::Vector tmpcol(this->MinRow(),this->MaxRow()); Gambit::Vector tmpdual(this->MinRow(),this->MaxRow()); tmpcol = (T)0; tmpcol[i]=(T)1; SolveT(tmpcol,tmpdual); Gambit::Vector solution(tmpcol); //$$ BasisVector(solution); //$$ // gout << "\ncurrentPivCol = " << tmpcol; // gout << "\ncurrentSolCol = " << solution; T a_ij,a_ik,c_j,c_k,ratio; /* if( j<0 ) { tmpcol=(T)0; tmpcol[-j]=(T)1; } else A->GetColumn(j,tmpcol); */ GetColumn(j,tmpcol); a_ij = tmpdual*tmpcol; c_j = RelativeCost(j); if(GeZero(a_ij)) { // gout << "\nPrior tableau not dual feasible: "; // gout << "a_ij>=0"; return 0; } ratio = c_j/a_ij; for(k=-this->b->Last();k<=cost.Last();k++) if(k!=0) { if(k<0) a_ik=tmpdual[-k]; else { // A->GetColumn(k,tmpcol); GetColumn(k,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(k); if(LtZero(a_ik) && GtZero(c_k/a_ik-ratio)) { // gout << "\nPrior tableau not dual feasible: "; // gout << "\nhigher ratio for k = " << k; return 0; } } // check that i would be the column to enter in prior tableau int enter = this->Label(i); // gout << "\nenter = " << enter; if(enter<0) a_ik = tmpdual[-enter]; else { // A->GetColumn(enter,tmpcol); GetColumn(enter,tmpcol); a_ik = tmpdual*tmpcol; } a_ik = a_ik/a_ij; c_k = RelativeCost(enter); c_k -= a_ik * c_j; if(GeZero(a_ik)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "a_ik>=0"; return 0; } ratio = c_k/a_ik; for(k=-this->b->Last();k<=cost.Last();k++) if(k!=0) { if(k<0) a_ik=tmpdual[-k]; else { // A->GetColumn(k,tmpcol); GetColumn(k,tmpcol); a_ik = tmpdual*tmpcol; } a_ik = a_ik/a_ij; c_k = RelativeCost(k); c_k -= a_ik * c_j; if(LtZero(a_ik) && GtZero(c_k/a_ik- ratio)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "\nhigher ratio for k = " << k; return 0; } if(kb->First();k<=this->b->Last();k++) if(k!=i) { b_k = solution[k] - b_i * tmpcol[k]; if(GtZero(b_k) && this->Label(k) int LPTableau::LastLabel( void ) { return this->artificial.Last(); } template void LPTableau::BasisSelect(const Gambit::Array &rowv, Gambit::Vector &colv) const { for(int i=this->basis.First(); i<=this->basis.Last(); i++) { if(this->basis.Label(i)<0) colv[i]= 0; else colv[i]= rowv[this->basis.Label(i)]; } } template void LPTableau::BasisSelect(const Gambit::Array &unitv, const Gambit::Array &rowv, Gambit::Vector &colv ) const { for(int i=this->basis.First(); i<=this->basis.Last(); i++) { if(this->basis.Label(i)<0) colv[i]= unitv[-this->basis.Label(i)]; else colv[i]= rowv[this->basis.Label(i)]; } } template LPTableau::BadPivot::~BadPivot() { } template std::string LPTableau::BadPivot::GetDescription(void) const { return "Bad Pivot in LPTableau"; } gambit-0.2010.09.01/src/tools/enummixed/lrslib.c0000644000076500007650000034502411350032206016015 00000000000000/* lrslib.c library code for lrs */ /* last modified: March 31, 2006 */ /* Copyright: David Avis 2003,2006 avis@cs.mcgill.ca */ /* 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "lrslib.h" /* Globals; these need to be here, rather than lrslib.h, so they are not multiply defined. */ FILE *lrs_cfp; /* output file for checkpoint information */ FILE *lrs_ifp; /* input file pointer */ FILE *lrs_ofp; /* output file pointer */ unsigned long dict_count, dict_limit, cache_tries, cache_misses; /* Variables and functions global to this file only */ static long lrs_checkpoint_seconds = 0; static long lrs_global_count = 0; /* Track how many lrs_dat records are allocated */ static lrs_dat_p *lrs_global_list[MAX_LRS_GLOBALS + 1]; static void lrs_dump_state (); /*******************************/ /* functions for external use */ /*******************************/ /*******************************************************/ /* lrs_main is driver for lrs.c does H/V enumeration */ /* showing function calls intended for public use */ /*******************************************************/ long lrs_main (int argc, char *argv[]) { lrs_dic *P; /* structure for holding current dictionary and indices */ lrs_dat *Q; /* structure for holding static problem data */ lrs_mp_vector output; /* holds one line of output; ray,vertex,facet,linearity */ lrs_mp_matrix Lin; /* holds input linearities if any are found */ long col; /* output column index for dictionary */ long startcol = 0; long prune = FALSE; /* if TRUE, getnextbasis will prune tree and backtrack */ /* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ /* they default to stdin and stdout, but may be overidden by command line parms. */ /*************************************************** Step 0: Do some global initialization that should only be done once, no matter how many lrs_dat records are allocated. db ***************************************************/ if ( !lrs_init ("\n*lrs:")) return 1; printf(AUTHOR); /*********************************************************************************/ /* Step 1: Allocate lrs_dat, lrs_dic and set up the problem */ /*********************************************************************************/ Q = lrs_alloc_dat ("LRS globals"); /* allocate and init structure for static problem data */ if (Q == NULL) return 1; if (!lrs_read_dat (Q, argc, argv)) /* read first part of problem data to get dimensions */ return 1; /* and problem type: H- or V- input representation */ P = lrs_alloc_dic (Q); /* allocate and initialize lrs_dic */ if (P == NULL) return 1; if (!lrs_read_dic (P, Q)) /* read remainder of input to setup P and Q */ return 1; output = lrs_alloc_mp_vector (Q->n); /* output holds one line of output from dictionary */ /*********************************************************************************/ /* Step 2: Find a starting cobasis from default of specified order */ /* P is created to hold active dictionary data and may be cached */ /* Lin is created if necessary to hold linearity space */ /* Print linearity space if any, and retrieve output from first dict. */ /*********************************************************************************/ if (!lrs_getfirstbasis (&P, Q, &Lin, FALSE)) return 1; /* Pivot to a starting dictionary */ /* There may have been column redundancy */ /* If so the linearity space is obtained and redundant */ /* columns are removed. User can access linearity space */ /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ if (Q->homogeneous && Q->hull) startcol++; /* col zero not treated as redundant */ for (col = startcol; col < Q->nredundcol; col++) /* print linearity space */ lrs_printoutput (Q, Lin[col]); /* Array Lin[][] holds the coeffs. */ /*********************************************************************************/ /* Step 3: Terminate if lponly option set, otherwise initiate a reverse */ /* search from the starting dictionary. Get output for each new dict. */ /*********************************************************************************/ /* We initiate reverse search from this dictionary */ /* getting new dictionaries until the search is complete */ /* User can access each output line from output which is */ /* vertex/ray/facet from the lrs_mp_vector output */ /* prune is TRUE if tree should be pruned at current node */ do { prune=lrs_checkbound(P,Q); if (!prune) for (col = 0; col <= P->d; col++) if (lrs_getsolution (P, Q, output, col)) lrs_printoutput (Q, output); } while (!Q->lponly && lrs_getnextbasis (&P, Q, prune)); if (Q->lponly) lrs_lpoutput(P,Q,output); else lrs_printtotals (P, Q); /* print final totals, including estimates */ lrs_clear_mp_vector(output, Q->n); lrs_free_dic (P,Q); /* deallocate lrs_dic */ lrs_free_dat (Q); /* deallocate lrs_dat */ lrs_close ("lrs:"); return 0; } /*********************************************/ /* end of model test program for lrs library */ /*********************************************/ /*******************************************************/ /* redund_main is driver for redund.c, removes all */ /* redundant rows from an H or V-representation */ /* showing function calls intended for public use */ /*******************************************************/ long redund_main (int argc, char *argv[]) { lrs_mp_matrix Ain; /* holds a copy of the input matrix to output at the end */ long *redineq; /* redineq[i]=0 if ineq i non-red,1 if red,2 linearity */ long ineq; /* input inequality number of current index */ lrs_dic *P; /* structure for holding current dictionary and indices */ lrs_dat *Q; /* structure for holding static problem data */ lrs_mp_matrix Lin; /* holds input linearities if any are found */ long i, j, d, m; long nlinearity; /* number of linearities in input file */ long nredund; /* number of redundant rows in input file */ long lastdv; long debug; long index; /* basic index for redundancy test */ /* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ /* they default to stdin and stdout, but may be overidden by command line parms. */ /* Lin is global 2-d array for linearity space if it is found (redund columns) */ lrs_ifp = stdin; lrs_ofp = stdout; /*************************************************** Step 0: Do some global initialization that should only be done once, no matter how many lrs_dat records are allocated. db ***************************************************/ if ( !lrs_init ("\n*redund:")) return 1; printf (AUTHOR); /*********************************************************************************/ /* Step 1: Allocate lrs_dat, lrs_dic and set up the problem */ /*********************************************************************************/ Q = lrs_alloc_dat ("LRS globals"); /* allocate and init structure for static problem data */ if (Q == NULL) return 1; if (!lrs_read_dat (Q, argc, argv)) /* read first part of problem data to get dimensions */ return 1; /* and problem type: H- or V- input representation */ P = lrs_alloc_dic (Q); /* allocate and initialize lrs_dic */ if (P == NULL) return 1; if (!lrs_read_dic (P, Q)) /* read remainder of input to setup P and Q */ return 1; /* if non-negative flag is set, non-negative constraints are not input */ /* explicitly, and are not checked for redundancy */ m = P->m_A; /* number of rows of A matrix */ d = P->d; debug = Q->debug; redineq = calloc ((m + 1), sizeof (long)); Ain = lrs_alloc_mp_matrix (m, d); /* make a copy of A matrix for output later */ for (i = 1; i <= m; i++) { for (j = 0; j <= d; j++) copy (Ain[i][j], P->A[i][j]); if (debug) lrs_printrow ("*", Q, Ain[i], d); } /*********************************************************************************/ /* Step 2: Find a starting cobasis from default of specified order */ /* Lin is created if necessary to hold linearity space */ /*********************************************************************************/ if (!lrs_getfirstbasis (&P, Q, &Lin, TRUE)) return 1; /* Pivot to a starting dictionary */ /* There may have been column redundancy */ /* If so the linearity space is obtained and redundant */ /* columns are removed. User can access linearity space */ /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ /*********************************************************************************/ /* Step 3: Test each row of the dictionary to see if it is redundant */ /*********************************************************************************/ /* note some of these may have been changed in getting initial dictionary */ m = P->m_A; d = P->d; nlinearity = Q->nlinearity; lastdv = Q->lastdv; /* linearities are not considered for redundancy */ for (i = 0; i < nlinearity; i++) redineq[Q->linearity[i]] = 2L; /* rows 0..lastdv are cost, decsion variables, or linearities */ /* other rows need to be tested */ for (index = lastdv + 1; index <= m + d; index++) { ineq = Q->inequality[index - lastdv]; /* the input inequality number corr. to this index */ redineq[ineq] = checkindex (P, Q, index); if (debug) fprintf (lrs_ofp, "\ncheck index=%ld, inequality=%ld, redineq=%ld", index, ineq, redineq[ineq]); if (redineq[ineq] == ONE) { fprintf (lrs_ofp, "\n*row %ld was redundant and removed", ineq); fflush (lrs_ofp); } } /* end for index ..... */ if (debug) { fprintf (lrs_ofp, "\n*redineq:"); for (i = 1; i <= m; i++) fprintf (lrs_ofp, " %ld", redineq[i]); } if (!Q->hull) fprintf (lrs_ofp, "\nH-representation"); else fprintf (lrs_ofp, "\nV-representation"); /* linearities will be printed first in output */ if (nlinearity > 0) { fprintf (lrs_ofp, "\nlinearity %ld", nlinearity); for (i = 1; i <= nlinearity; i++) fprintf (lrs_ofp, " %ld", i); } nredund = nlinearity; /* count number of non-redundant inequalities */ for (i = 1; i <= m; i++) if (redineq[i] == 0) nredund++; fprintf (lrs_ofp, "\nbegin"); fprintf (lrs_ofp, "\n%ld %ld rational", nredund, Q->n); /* print the linearities first */ for (i = 0; i < nlinearity; i++) lrs_printrow ("", Q, Ain[Q->linearity[i]], Q->inputd); for (i = 1; i <= m; i++) if (redineq[i] == 0) lrs_printrow ("", Q, Ain[i], Q->inputd); fprintf (lrs_ofp, "\nend"); fprintf (lrs_ofp, "\n*Input had %ld rows and %ld columns", m, Q->n); fprintf (lrs_ofp, ": %ld row(s) redundant", m - nredund); lrs_free_dic (P,Q); /* deallocate lrs_dic */ lrs_free_dat (Q); /* deallocate lrs_dat */ lrs_close ("redund:"); return 0; } /*********************************************/ /* end of redund.c */ /*********************************************/ /*******************/ /* lrs_printoutput */ /*******************/ void lrs_printoutput (lrs_dat * Q, lrs_mp_vector output) { long i; fprintf (lrs_ofp, "\n"); if (Q->hull || zero (output[0])) /*non vertex */ { for (i = 0; i < Q->n; i++) pmp ("", output[i]); } else { /* vertex */ fprintf (lrs_ofp, " 1 "); for (i = 1; i < Q->n; i++) prat ("", output[i], output[0]); } fflush(lrs_ofp); } /**************************/ /* end of lrs_printoutput */ /**************************/ /****************/ /* lrs_lpoutput */ /****************/ void lrs_lpoutput(lrs_dic * P,lrs_dat * Q, lrs_mp_vector output) { #ifndef LRS_QUIET lrs_mp Temp1, Temp2; long i; lrs_alloc_mp (Temp1); lrs_alloc_mp (Temp2); fprintf (lrs_ofp, "\n*LP solution only requested"); prat ("\n\n*Objective function has value ", P->objnum, P->objden); fprintf (lrs_ofp, "\n\n*Primal: "); for (i = 1; i < Q->n; i++) { fprintf(lrs_ofp,"x_%ld=",i); prat ("", output[i], output[0]); } if(Q->nlinearity > 0) fprintf (lrs_ofp, "\n\n*Linearities in input file - partial dual solution only"); fprintf (lrs_ofp, "\n\n*Dual: "); for (i = 0; i < P->d; i++) { fprintf(lrs_ofp,"y_%ld=",Q->inequality[P->C[i]-Q->lastdv]); changesign(P->A[0][P->Col[i]]); mulint(Q->Lcm[P->Col[i]],P->A[0][P->Col[i]],Temp1); mulint(Q->Gcd[P->Col[i]],P->det,Temp2); prat("",Temp1,Temp2); changesign(P->A[0][P->Col[i]]); } fprintf (lrs_ofp, "\n"); lrs_clear_mp (Temp1); lrs_clear_mp (Temp2); #endif } /***********************/ /* end of lrs_lpoutput */ /***********************/ void lrs_printrow (char name[], lrs_dat * Q, lrs_mp_vector output, long rowd) /* print a row of A matrix in output in "original" form */ /* rowd+1 is the dimension of output vector */ /* if input is H-rep. output[0] contains the RHS */ /* if input is V-rep. vertices are scaled by 1/output[1] */ { long i; fprintf (lrs_ofp, "\n%s", name); if (!Q->hull) /* input was inequalities, print directly */ { for (i = 0; i <= rowd; i++) pmp ("", output[i]); return; } /* input was vertex/ray */ if (zero (output[1])) /*non-vertex */ { for (i = 1; i <= rowd; i++) pmp ("", output[i]); } else { /* vertex */ fprintf (lrs_ofp, " 1 "); for (i = 2; i <= rowd; i++) prat ("", output[i], output[1]); } return; } /* end of lrs_printrow */ long lrs_getsolution (lrs_dic * P, lrs_dat * Q, lrs_mp_vector output, long col) /* check if column indexed by col in this dictionary */ /* contains output */ /* col=0 for vertex 1....d for ray/facet */ { long j; /* cobasic index */ lrs_mp_matrix A = P->A; long *Row = P->Row; if (col == ZERO) /* check for lexmin vertex */ return lrs_getvertex (P, Q, output); /* check for rays: negative in row 0 , positive if lponly */ if (Q->lponly) { if (!positive (A[0][col])) return FALSE; } else if (!negative (A[0][col])) return FALSE; /* and non-negative for all basic non decision variables */ j = Q->lastdv + 1; while (j <= P->m && !negative (A[Row[j]][col])) j++; if (j <= P->m) return FALSE; if (Q->geometric || Q->allbases || lexmin (P, Q, col) || Q->lponly) return lrs_getray (P, Q, col, Q->n, output); return FALSE; /* no more output in this dictionary */ } /* end of lrs_getsolution */ /* added (back?) by db, March 29, 2006 */ int lrs_init_quiet(FILE *ifp, FILE *ofp){ if (!lrs_mp_init (ZERO, ifp, ofp)) /* initialize arithmetic */ return FALSE; lrs_global_count = 0; lrs_checkpoint_seconds = 0; return TRUE; } long lrs_init (char *name) /* returns TRUE if successful, else FALSE */ { #ifdef UNUSED_BY_GAMBIT printf ("%s", name); printf (TITLE); printf (LRS_VERSION); printf ("("); printf (BIT); printf (","); printf (ARITH); #endif // UNUSED_BY_GAMBIT if (!lrs_mp_init (ZERO, stdin, stdout)) /* initialize arithmetic */ return FALSE; //printf (")"); lrs_global_count = 0; lrs_checkpoint_seconds = 0; #ifdef SIGNALS setup_signals (); #endif return TRUE; } void lrs_close (char *name) { #ifdef UNUSED_BY_GAMBIT fprintf (lrs_ofp, "\n*%s", name); fprintf (lrs_ofp, TITLE); fprintf (lrs_ofp, LRS_VERSION); fprintf (lrs_ofp, "("); fprintf (lrs_ofp, BIT); fprintf (lrs_ofp, ","); fprintf (lrs_ofp, ARITH); fprintf (lrs_ofp, ")"); #endif // UNUSED_BY_GAMBIT #ifdef MP //fprintf (lrs_ofp, " max digits=%ld/%ld", DIG2DEC (lrs_record_digits), DIG2DEC (lrs_digits)); #endif #ifdef TIMES //ptimes (); #endif //fprintf (lrs_ofp, "\n"); fclose (lrs_ifp); if (lrs_ofp != stdout) fclose (lrs_ofp); } /***********************************/ /* allocate and initialize lrs_dat */ /***********************************/ lrs_dat * lrs_alloc_dat (char *name) { lrs_dat *Q; long i; if (lrs_global_count >= MAX_LRS_GLOBALS) { fprintf (stderr, "Fatal: Attempt to allocate more than %ld global data blocks\n", MAX_LRS_GLOBALS); exit (1); } Q = (lrs_dat *) malloc (sizeof (lrs_dat)); if (Q == NULL) return Q; /* failure to allocate */ lrs_global_list[lrs_global_count] = Q; Q->id = lrs_global_count; lrs_global_count++; Q->name=(char *) CALLOC ((unsigned) strlen(name)+1, sizeof (char)); strcpy(Q->name,name); /* initialize variables */ Q->m = 0L; Q->n = 0L; Q->inputd = 0L; Q->deepest = 0L; Q->nlinearity = 0L; Q->nredundcol = 0L; Q->runs = 0L; Q->seed = 1234L; Q->totalnodes = 0L; for (i = 0; i < 10; i++) { Q->count[i] = 0L; Q->cest[i] = 0.0; } Q->count[2] = 1L; /* basis counter */ /* initialize flags */ Q->allbases = FALSE; Q->bound = FALSE; /* upper/lower bound on objective function given */ Q->debug = FALSE; Q->frequency = 0L; Q->dualdeg = FALSE; /* TRUE if dual degenerate starting dictionary */ Q->geometric = FALSE; Q->getvolume = FALSE; Q->homogeneous = TRUE; Q->polytope = FALSE; Q->hull = FALSE; Q->incidence = FALSE; Q->lponly = FALSE; Q->maxdepth = MAXD; Q->mindepth = -MAXD; Q->maxoutput = 0L; Q->nash = FALSE; Q->nonnegative = FALSE; Q->printcobasis = FALSE; Q->printslack = FALSE; Q->truncate = FALSE; /* truncate tree when moving from opt vertex */ Q->verbose=FALSE; Q->voronoi = FALSE; Q->maximize = FALSE; /*flag for LP maximization */ Q->minimize = FALSE; /*flag for LP minimization */ Q->restart = FALSE; /* TRUE if restarting from some cobasis */ Q->givenstart = FALSE; /* TRUE if a starting cobasis is given */ Q->strace = -1L; /* turn on debug at basis # strace */ Q->etrace = -1L; /* turn off debug at basis # etrace */ Q->saved_flag = 0; /* no cobasis saved initially, db */ lrs_alloc_mp (Q->Nvolume); lrs_alloc_mp (Q->Dvolume); lrs_alloc_mp (Q->sumdet); lrs_alloc_mp (Q->saved_det); lrs_alloc_mp (Q->boundn); lrs_alloc_mp (Q->boundd); itomp (ZERO, Q->Nvolume); itomp (ONE, Q->Dvolume); itomp (ZERO, Q->sumdet); return Q; } /* end of allocate and initialize lrs_dat */ /*******************************/ /* lrs_read_dat */ /*******************************/ long lrs_read_dat (lrs_dat * Q, int argc, char *argv[]) { char name[100]; long dec_digits = 0; long infile=0; /*input file number to open if any */ long firstline = TRUE; /*flag for picking off name at line 1 */ int c; /* for fgetc */ if(argc > 1 ) infile=1; if(Q->nash && argc == 2) /* open second nash input file */ infile=2; if (infile > 0) /* command line argument overides stdin */ { if ((lrs_ifp = fopen (argv[infile], "r")) == NULL) { printf ("\nBad input file name\n"); return (FALSE); } else { if (infile==1) printf ("\n*Input taken from file %s", argv[infile]); } } /* command line argument overides stdout */ if ((!Q->nash && argc == 3) || (Q->nash && argc == 4)) { if ((lrs_ofp = fopen (argv[argc-1], "w")) == NULL) { printf ("\nBad output file name\n"); return (FALSE); } else printf ("\n*Output sent to file %s\n", argv[argc-1]); } /* process input file */ fscanf (lrs_ifp, "%s", name); while (strcmp (name, "begin") != 0) /*skip until "begin" found processing options */ { if (strncmp (name, "*", 1) == 0) /* skip any line beginning with * */ { c = name[0]; while (c != EOF && c != '\n') c = fgetc (lrs_ifp); } else if (strcmp (name, "H-representation") == 0) Q->hull = FALSE; else if ((strcmp (name, "hull") == 0) || (strcmp (name, "V-representation") == 0)) { Q->hull = TRUE; Q->polytope = TRUE; /* will be updated as input read */ } else if (strcmp (name, "digits") == 0) { if (fscanf (lrs_ifp, "%ld", &dec_digits) == EOF) { fprintf (lrs_ofp, "\nNo begin line"); return (FALSE); } if (!lrs_set_digits(dec_digits)) return (FALSE); } else if (strcmp (name, "linearity") == 0) { if (!readlinearity (Q)) return FALSE; } else if (strcmp (name, "nonnegative") == 0) { if(Q->nash) fprintf (lrs_ofp, "\nNash incompatibile with nonnegative option - skipped"); else Q->nonnegative = TRUE; } else if (firstline) { stringcpy (Q->fname, name); fprintf (lrs_ofp, "\n%s", Q->fname); firstline = FALSE; } if (fscanf (lrs_ifp, "%s", name) == EOF) { fprintf (lrs_ofp, "\nNo begin line"); return (FALSE); } } /* end of while */ if (fscanf (lrs_ifp, "%ld %ld %s", &Q->m, &Q->n, name) == EOF) { fprintf (lrs_ofp, "\nNo data in file"); return (FALSE); } if (strcmp (name, "integer") != 0 && strcmp (name, "rational") != 0) { fprintf (lrs_ofp, "\nData type must be integer of rational"); return (FALSE); } if (Q->m == 0) { fprintf (lrs_ofp, "\nNo input given"); /* program dies ungracefully */ return (FALSE); } /* inputd may be reduced in preprocessing of linearities and redund cols */ return TRUE; } /* end of lrs_read_dat */ /****************************/ /* set up lrs_dic structure */ /****************************/ long lrs_read_dic (lrs_dic * P, lrs_dat * Q) /* read constraint matrix and set up problem and dictionary */ { lrs_mp Temp,Tempn,Tempd, mpone, mpten; lrs_mp_vector oD; /* Denom for objective function */ long i, j; char name[100]; int c; /* fgetc actually returns an int. db */ /* assign local variables to structures */ lrs_mp_matrix A; lrs_mp_vector Gcd, Lcm; long hull = Q->hull; long m, d; long dualperturb=FALSE; /* dualperturb=TRUE: objective function perturbed */ lrs_alloc_mp(Temp); lrs_alloc_mp(mpone); lrs_alloc_mp(Tempn); lrs_alloc_mp(Tempd); lrs_alloc_mp(mpten); A = P->A; m = Q->m; d = Q->inputd; Gcd = Q->Gcd; Lcm = Q->Lcm; oD = lrs_alloc_mp_vector (d); itomp (ONE, mpone); itomp (ONE, A[0][0]); itomp (ONE, Lcm[0]); itomp (ONE, Gcd[0]); for (i = 1; i <= m; i++) /* read in input matrix row by row */ { itomp (ONE, Lcm[i]); /* Lcm of denominators */ itomp (ZERO, Gcd[i]); /* Gcd of numerators */ for (j = hull; j <= d; j++) /* hull data copied to cols 1..d */ { if (readrat (A[i][j], A[0][j])) lcm (Lcm[i], A[0][j]); /* update lcm of denominators */ copy (Temp, A[i][j]); gcd (Gcd[i], Temp); /* update gcd of numerators */ } if (hull) { itomp (ZERO, A[i][0]); /*for hull, we have to append an extra column of zeroes */ if (!one (A[i][1]) || !one (A[0][1])) /* all rows must have a one in column one */ Q->polytope = FALSE; } if (!zero (A[i][hull])) /* for H-rep, are zero in column 0 */ Q->homogeneous = FALSE; /* for V-rep, all zero in column 1 */ storesign (Gcd[i], POS); storesign (Lcm[i], POS); if (greater (Gcd[i], mpone) || greater (Lcm[i], mpone)) for (j = 0; j <= d; j++) { exactdivint (A[i][j], Gcd[i], Temp); /*reduce numerators by Gcd */ mulint (Lcm[i], Temp, Temp); /*remove denominators */ exactdivint (Temp, A[0][j], A[i][j]); /*reduce by former denominator */ } } /* end of for i= */ if (Q->homogeneous && Q->verbose) { fprintf (lrs_ofp, "\n*Input is homogeneous, column 1 not treated as redundant"); } /* read in flags */ while (fscanf (lrs_ifp, "%s", name) != EOF) { if (strncmp (name, "*", 1) == 0) /* skip any line beginning with * */ { c = name[0]; while (c != EOF && c != '\n') c = fgetc (lrs_ifp); } if (strcmp (name, "checkpoint") == 0) { long seconds; fscanf (lrs_ifp, "%ld", &seconds); #ifdef SIGNALS if (seconds > 0) { lrs_checkpoint_seconds = seconds; errcheck ("signal", signal (SIGALRM, timecheck)); alarm (lrs_checkpoint_seconds); } #endif } if (strcmp (name, "debug") == 0) { fscanf (lrs_ifp, "%ld %ld", &Q->strace, &Q->etrace); fprintf (lrs_ofp, "\n*%s from B#%ld to B#%ld", name, Q->strace, Q->etrace); Q->verbose=TRUE; if (Q->strace <= 1) Q->debug = TRUE; } if (strcmp (name, "startingcobasis") == 0) { if(Q->nonnegative) fprintf (lrs_ofp, "\n*startingcobasis incompatible with nonnegative option:skipped"); else { fprintf (lrs_ofp, "\n*startingcobasis"); Q->givenstart = TRUE; if (!readfacets (Q, Q->inequality)) return FALSE; } } if (strcmp (name, "restart") == 0) { Q->restart = TRUE; if(Q->voronoi) { fscanf (lrs_ifp, "%ld %ld %ld %ld", &Q->count[1], &Q->count[0], &Q->count[2], &P->depth); fprintf (lrs_ofp, "\n*%s V#%ld R#%ld B#%ld h=%ld data points", name, Q->count[1], Q->count[0], Q->count[2], P->depth); } else if(hull) { fscanf (lrs_ifp, "%ld %ld %ld", &Q->count[0], &Q->count[2], &P->depth); fprintf (lrs_ofp, "\n*%s F#%ld B#%ld h=%ld vertices/rays", name, Q->count[0], Q->count[2], P->depth); } else { fscanf (lrs_ifp, "%ld %ld %ld %ld", &Q->count[1], &Q->count[0], &Q->count[2], &P->depth); fprintf (lrs_ofp, "\n*%s V#%ld R#%ld B#%ld h=%ld facets", name, Q->count[1], Q->count[0], Q->count[2], P->depth); } if (!readfacets (Q, Q->facet)) return FALSE; } /* end of restart */ /* The next flag request a LP solution only */ if (strcmp (name, "lponly") == 0) { if (Q->hull) fprintf (lrs_ofp, "\n*lponly option not valid for V-representation-skipped"); else Q->lponly = TRUE; } /* The LP will be solved after initialization to get starting vertex */ /* Used also with lponly flag */ if (strcmp (name, "maximize") == 0 || strcmp (name, "minimize") == 0) { if (Q->hull) fprintf (lrs_ofp, "\n*%s option not valid for V-representation-skipped", name); else { { if (strcmp (name, "maximize") == 0) Q->maximize = TRUE; else Q->minimize = TRUE; } fprintf (lrs_ofp,"\n*%s", name); if(dualperturb) /* apply a perturbation to objective function */ { fprintf (lrs_ofp, " - Objective function perturbed"); itomp(10L,mpten); copy(Temp,mpten); for (j = 0; j <= 10; j++) mulint(mpten,Temp,Temp); } fprintf (lrs_ofp, ": "); for (j = 0; j <= d; j++) { if (readrat (A[0][j], oD[j]) || dualperturb ) { if(dualperturb && j > 0 && j < d ) { if (Q->maximize) linrat(A[0][j], oD[j],ONE,mpone,Temp,ONE,Tempn,Tempd); else linrat(A[0][j], oD[j],ONE,mpone,Temp,-1L,Tempn,Tempd); copy(A[0][j],Tempn); copy(oD[j],Tempd); mulint(mpten,Temp,Temp); } reduce (A[0][j], oD[j]); lcm (Q->Lcm[0], oD[j]); /* update lcm of denominators */ } prat ("", A[0][j], oD[j]); if (!Q->maximize) changesign (A[0][j]); } storesign (Q->Lcm[0], POS); if (greater (Q->Lcm[0], mpone)) for (j = 0; j <= d; j++) { mulint (Q->Lcm[0], A[0][j], A[0][j]); /*remove denominators */ copy (Temp, A[0][j]); exactdivint (Temp, oD[j], A[0][j]); } if (Q->debug) printA (P, Q); } } /* end of LP setup */ if (strcmp (name, "volume") == 0) { fprintf (lrs_ofp, "\n*%s", name); Q->getvolume = TRUE; } if (strcmp (name, "geometric") == 0) { fprintf (lrs_ofp, "\n*%s", name); if (hull & !Q->voronoi) fprintf (lrs_ofp, " - option for H-representation or voronoi only, skipped"); else Q->geometric = TRUE; } if (strcmp (name, "allbases") == 0) { fprintf (lrs_ofp, "\n*%s", name); Q->allbases = TRUE; } if (strcmp (name, "dualperturb") == 0) { dualperturb = TRUE; } if (strcmp (name, "incidence") == 0) { fprintf (lrs_ofp, "\n*%s", name); Q->incidence = TRUE; } if (strcmp (name, "#incidence") == 0) /* number of incident inequalities only */ { Q->printcobasis = TRUE; } if (strcmp (name, "printcobasis") == 0) { fscanf (lrs_ifp, "%ld", &Q->frequency); fprintf (lrs_ofp, "\n*%s", name); fprintf(lrs_ofp," %ld", Q->frequency); Q->printcobasis = TRUE; } if (strcmp (name, "printslack") == 0) { Q->printslack = TRUE; } if (strcmp (name, "cache") == 0) { fscanf (lrs_ifp, "%ld", &dict_limit); fprintf (lrs_ofp, "\n*cache %ld", dict_limit); if (dict_limit < 1) dict_limit = 1; } if (strcmp (name, "linearity") == 0) { if (!readlinearity (Q)) return FALSE; } if (strcmp (name, "maxdepth") == 0) { fscanf (lrs_ifp, "%ld", &Q->maxdepth); fprintf (lrs_ofp, "\n*%s %ld", name, Q->maxdepth); } if (strcmp (name, "maxoutput") == 0) { fscanf (lrs_ifp, "%ld", &Q->maxoutput); fprintf (lrs_ofp, "\n*%s %ld", name, Q->maxoutput); } if (strcmp (name, "mindepth") == 0) { fscanf (lrs_ifp, "%ld", &Q->mindepth); fprintf (lrs_ofp, "\n*%s %ld", name, Q->mindepth); } if (strcmp (name, "truncate") == 0) { fprintf (lrs_ofp, "\n*%s", name); if (!hull) Q->truncate = TRUE; else fprintf (lrs_ofp, " - option for H-representation only, skipped"); } if (strcmp (name, "verbose") == 0) Q->verbose = TRUE; if (strcmp (name, "bound") == 0) { readrat(Q->boundn,Q->boundd); Q->bound = TRUE; } if (strcmp (name, "nonnegative") == 0) { fprintf (lrs_ofp, "\n*%s", name); fprintf (lrs_ofp, " - option must come before begin line - skipped"); } if (strcmp (name, "seed") == 0) { fscanf (lrs_ifp, "%ld", &Q->seed); fprintf (lrs_ofp, "\n*seed= %ld ", Q->seed); } if (strcmp (name, "estimates") == 0) { fscanf (lrs_ifp, "%ld", &Q->runs); fprintf (lrs_ofp, "\n*%ld %s", Q->runs, name); } if ((strcmp (name, "voronoi") == 0) || (strcmp (name, "Voronoi") == 0)) { if (!hull) fprintf (lrs_ofp, "\n*voronoi requires V-representation - option skipped"); else { Q->voronoi = TRUE; Q->polytope = FALSE; } } } /* end of while for reading flags */ if (Q->polytope) Q->getvolume = TRUE; /* might as well get volume, it doesn't cost much */ if (Q->bound && Q->maximize) prat("\n*Lower bound on objective function:",Q->boundn,Q->boundd); if (Q->bound && Q->minimize) prat("\n*Upper bound on objective function:",Q->boundn,Q->boundd); /* Certain options are incompatible, this is fixed here */ if (Q->restart) Q->getvolume = FALSE; /* otherwise incorrect volume reported */ if (Q->incidence) { Q->printcobasis = TRUE; } if (Q->debug) { printA (P, Q); fprintf (lrs_ofp, "\nexiting lrs_read_dic"); } lrs_clear_mp(Temp); lrs_clear_mp(mpone); lrs_clear_mp(Tempn); lrs_clear_mp(Tempd); lrs_clear_mp(mpten); lrs_clear_mp_vector (oD,d); return TRUE; } /********* end of lrs_read_dic ***************/ /* In lrs_getfirstbasis and lrs_getnextbasis we use D instead of P */ /* since the dictionary P may change, ie. &P in calling routine */ #define D (*D_p) long lrs_getfirstbasis (lrs_dic ** D_p, lrs_dat * Q, lrs_mp_matrix * Lin, long no_output) /* gets first basis, FALSE if none */ /* P may get changed if lin. space Lin found */ /* no_output is TRUE supresses output headers */ { lrs_mp scale, Temp; long i, j, k; /* assign local variables to structures */ lrs_mp_matrix A; long *B, *C, *Row, *Col; long *inequality; long *linearity; long hull = Q->hull; long m, d, lastdv, nlinearity, nredundcol; static long ocount=0; lrs_alloc_mp(Temp); lrs_alloc_mp(scale); if (Q->lponly) no_output = TRUE; m = D->m; d = D->d; lastdv = Q->lastdv; nredundcol = 0L; /* will be set after getabasis */ nlinearity = Q->nlinearity; /* may be reset if new linearity read */ linearity = Q->linearity; A = D->A; B = D->B; C = D->C; Row = D->Row; Col = D->Col; inequality = Q->inequality; if (Q->nlinearity > 0 && Q->nonnegative) { fprintf (lrs_ofp, "\n*linearity and nonnegative options incompatible"); fprintf (lrs_ofp, " - all linearities are skipped"); fprintf (lrs_ofp, "\n*add nonnegative constraints explicitly and "); fprintf (lrs_ofp, " remove nonnegative option"); } if (Q->nlinearity && Q->voronoi) fprintf (lrs_ofp, "\n*linearity and Voronoi options set - results unpredictable"); if (Q->lponly && !Q->maximize && !Q->minimize) fprintf (lrs_ofp, "\n*LP has no objective function given - assuming all zero"); if (Q->runs > 0) /* arrays for estimator */ { Q->isave = (long *) CALLOC ((unsigned) (m * d), sizeof (long)); Q->jsave = (long *) CALLOC ((unsigned) (m * d), sizeof (long)); } /* default is to look for starting cobasis using linearies first, then */ /* filling in from last rows of input as necessary */ /* linearity array is assumed sorted here */ /* note if restart/given start inequality indices already in place */ /* from nlinearity..d-1 */ for (i = 0; i < nlinearity; i++) /* put linearities first in the order */ inequality[i] = linearity[i]; k = 0; /* index for linearity array */ if (Q->givenstart) k = d; else k = nlinearity; for (i = m; i >= 1; i--) { j = 0; while (j < k && inequality[j] != i) j++; /* see if i is in inequality */ if (j == k) inequality[k++] = i; } if (Q->debug) { fprintf (lrs_ofp, "\n*Starting cobasis uses input row order"); for (i = 0; i < m; i++) fprintf (lrs_ofp, " %ld", inequality[i]); } /* for voronoi convert to h-description using the transform */ /* a_0 .. a_d-1 -> (a_0^2 + ... a_d-1 ^2)-2a_0x_0-...-2a_d-1x_d-1 + x_d >= 0 */ /* note constant term is stored in column d, and column d-1 is all ones */ /* the other coefficients are multiplied by -2 and shifted one to the right */ if (Q->debug) printA (D, Q); if (Q->voronoi) { Q->hull = FALSE; hull = FALSE; for (i = 1; i <= m; i++) { if (zero (A[i][1])) { fprintf (lrs_ofp, "\nWith voronoi option column one must be all one"); return (FALSE); } copy (scale, A[i][1]); /*adjust for scaling to integers of rationals */ itomp (ZERO, A[i][0]); for (j = 2; j <= d; j++) /* transform each input row */ { copy (Temp, A[i][j]); mulint (A[i][j], Temp, Temp); linint (A[i][0], ONE, Temp, ONE); linint (A[i][j - 1], ZERO, A[i][j], -TWO); mulint (scale, A[i][j - 1], A[i][j - 1]); } /* end of for (j=1;..) */ copy (A[i][d], scale); mulint (scale, A[i][d], A[i][d]); } /* end of for (i=1;..) */ if (Q->debug) printA (D, Q); } /* end of if(voronoi) */ if (!Q->maximize && !Q->minimize) for (j = 0; j <= d; j++) itomp (ZERO, A[0][j]); /* Now we pivot to standard form, and then find a primal feasible basis */ /* Note these steps MUST be done, even if restarting, in order to get */ /* the same index/inequality correspondance we had for the original prob. */ /* The inequality array is used to give the insertion order */ /* and is defaulted to the last d rows when givenstart=FALSE */ if(Q->nonnegative) { /* no need for initial pivots here, labelling already done */ Q->lastdv = d; Q->nredundcol = 0; } else { if (!getabasis (D, Q, inequality)) return FALSE; } if(Q->debug) { fprintf(lrs_ofp,"\nafter getabasis"); printA(D, Q); } nredundcol = Q->nredundcol; lastdv = Q->lastdv; d = D->d; /********************************************************************/ /* now we start printing the output file unless no output requested */ /********************************************************************/ if (!no_output || Q->debug) { if (Q->voronoi) fprintf (lrs_ofp, "\n*Voronoi Diagram: Voronoi vertices and rays are output"); if (hull) fprintf (lrs_ofp, "\nH-representation"); else fprintf (lrs_ofp, "\nV-representation"); /* Print linearity space */ /* Don't print linearity if first column zero in hull computation */ if (hull && Q->homogeneous) k = 1; /* 0 normally, 1 for homogeneous case */ else k = 0; if (nredundcol > k) { fprintf (lrs_ofp, "\nlinearity %ld ", nredundcol - k); /*adjust nredundcol for homog. */ for (i = 1; i <= nredundcol - k; i++) fprintf (lrs_ofp, " %ld", i); } /* end print of linearity space */ fprintf (lrs_ofp, "\nbegin"); fprintf (lrs_ofp, "\n***** %ld rational", Q->n); } /* end of if !no_output ....... */ /* Reset up the inequality array to remember which index is which input inequality */ /* inequality[B[i]-lastdv] is row number of the inequality with index B[i] */ /* inequality[C[i]-lastdv] is row number of the inequality with index C[i] */ for (i = 1; i <= m; i++) inequality[i] = i; if (nlinearity > 0) /* some cobasic indices will be removed */ { for (i = 0; i < nlinearity; i++) /* remove input linearity indices */ inequality[linearity[i]] = 0; k = 1; /* counter for linearities */ for (i = 1; i <= m - nlinearity; i++) { while (k <= m && inequality[k] == 0) k++; /* skip zeroes in corr. to linearity */ inequality[i] = inequality[k++]; } } /* end if linearity */ if (Q->debug) { fprintf (lrs_ofp, "\ninequality array initialization:"); for (i = 1; i <= m - nlinearity; i++) fprintf (lrs_ofp, " %ld", inequality[i]); } if (nredundcol > 0) { *Lin = lrs_alloc_mp_matrix (nredundcol, Q->n); for (i = 0; i < nredundcol; i++) { if (!(Q->homogeneous && Q->hull && i == 0)) /* skip redund col 1 for homog. hull */ { lrs_getray (D, Q, Col[0], D->C[0] + i - hull, (*Lin)[i]); /* adjust index for deletions */ } if (!removecobasicindex (D, Q, 0L)) return FALSE; } } /* end if nredundcol > 0 */ if (Q->lponly || Q->nash ) if (Q->verbose) { fprintf (lrs_ofp, "\nNumber of pivots for starting dictionary: %ld",Q->count[3]); ocount=Q->count[3]; if(Q->lponly) printA (D, Q); } /* Do dual pivots to get primal feasibility */ if (!primalfeasible (D, Q)) { #ifndef LRS_QUIET fprintf (lrs_ofp, "\nNo feasible solution"); #endif if (Q->nash && Q->verbose ) { fprintf (lrs_ofp, "\nNumber of pivots for feasible solution: %ld",Q->count[3]); fprintf (lrs_ofp, " - No feasible solution"); ocount=Q->count[3]; } return FALSE; } if (Q->lponly || Q->nash ) if (Q->verbose) { fprintf (lrs_ofp, "\nNumber of pivots for feasible solution: %ld",Q->count[3]); ocount=Q->count[3]; if(Q->lponly) printA (D, Q); } /* Now solve LP if objective function was given */ if (Q->maximize || Q->minimize) { Q->unbounded = !lrs_solvelp (D, Q, Q->maximize); if (Q->lponly) { if (Q->verbose) { fprintf (lrs_ofp, "\nNumber of pivots for optimum solution: %ld",Q->count[3]); printA (D, Q); ocount=Q->count[3]; } lrs_clear_mp(Temp); lrs_clear_mp(scale); return TRUE; } else /* check to see if objective is dual degenerate */ { j = 1; while (j <= d && !zero (A[0][j])) j++; if (j <= d) Q->dualdeg = TRUE; } } else /* re-initialize cost row to -det */ { for (j = 1; j <= d; j++) { copy (A[0][j], D->det); storesign (A[0][j], NEG); } itomp (ZERO, A[0][0]); /* zero optimum objective value */ } /* reindex basis to 0..m if necessary */ /* we use the fact that cobases are sorted by index value */ if (Q->debug) printA (D, Q); while (C[0] <= m) { i = C[0]; j = inequality[B[i] - lastdv]; inequality[B[i] - lastdv] = inequality[C[0] - lastdv]; inequality[C[0] - lastdv] = j; C[0] = B[i]; B[i] = i; reorder1 (C, Col, ZERO, d); } if (Q->debug) { fprintf (lrs_ofp, "\n*Inequality numbers for indices %ld .. %ld : ", lastdv + 1, m + d); for (i = 1; i <= m - nlinearity; i++) fprintf (lrs_ofp, " %ld ", inequality[i]); printA (D, Q); } if (Q->restart) { if (Q->debug) fprintf (lrs_ofp, "\nPivoting to restart co-basis"); if (!restartpivots (D, Q)) return FALSE; D->lexflag = lexmin (D, Q, ZERO); /* see if lexmin basis */ if (Q->debug) printA (D, Q); } /* Check to see if necessary to resize */ if (Q->inputd > D->d) *D_p = resize (D, Q); lrs_clear_mp(Temp); lrs_clear_mp(scale); return TRUE; } /********* end of lrs_getfirstbasis ***************/ /*****************************************/ /* getnextbasis in reverse search order */ /*****************************************/ long lrs_getnextbasis (lrs_dic ** D_p, lrs_dat * Q, long backtrack) /* gets next reverse search tree basis, FALSE if none */ /* switches to estimator if maxdepth set */ /* backtrack TRUE means backtrack from here */ { /* assign local variables to structures */ long i = 0L, j = 0L; long m = D->m; long d = D->d; if (backtrack && D->depth == 0) return FALSE; /* cannot backtrack from root */ if (Q->maxoutput > 0 && Q->count[0]+Q->count[1]-Q->hull >= Q->maxoutput) return FALSE; /* output limit reached */ while ((j < d) || (D->B[m] != m)) /*main while loop for getnextbasis */ { if (D->depth >= Q->maxdepth) { backtrack = TRUE; if (Q->runs > 0) /*get an estimate of remaining tree */ lrs_estimate (D, Q); if (Q->maxdepth == 0) /* estimate only */ return FALSE; /* no nextbasis */ } if ( Q->truncate && negative(D->A[0][0])) /* truncate when moving from opt. vertex */ backtrack = TRUE; if (backtrack) /* go back to prev. dictionary, restore i,j */ { backtrack = FALSE; if (check_cache (D_p, Q, &i, &j)) { if (Q->debug) fprintf (lrs_ofp, "\n Cached Dict. restored to depth %ld\n", D->depth); } else { D->depth--; selectpivot (D, Q, &i, &j); pivot (D, Q, i, j); update (D, Q, &i, &j); /*Update B,C,i,j */ } if (Q->debug) { fprintf (lrs_ofp, "\n Backtrack Pivot: indices i=%ld j=%ld depth=%ld", i, j, D->depth); printA (D, Q); }; j++; /* go to next column */ } /* end of if backtrack */ if (D->depth < Q->mindepth) break; /* try to go down tree */ while ((j < d) && !reverse (D, Q, &i, j)) j++; if (j == d) backtrack = TRUE; else /*reverse pivot found */ { cache_dict (D_p, Q, i, j); /* Note that the next two lines must come _after_ the call to cache_dict */ D->depth++; if (D->depth > Q->deepest) Q->deepest++; pivot (D, Q, i, j); update (D, Q, &i, &j); /*Update B,C,i,j */ D->lexflag = lexmin (D, Q, ZERO); /* see if lexmin basis */ Q->count[2]++; Q->totalnodes++; save_basis (*D_p, Q); if (Q->strace == Q->count[2]) Q->debug = TRUE; if (Q->etrace == Q->count[2]) Q->debug = FALSE; return TRUE; /*return new dictionary */ } } /* end of main while loop for getnextbasis */ return FALSE; /* done, no more bases */ } /*end of lrs_getnextbasis */ /*************************************/ /* print out one line of output file */ /*************************************/ long lrs_getvertex (lrs_dic * P, lrs_dat * Q, lrs_mp_vector output) /*Print out current vertex if it is lexmin and return it in output */ /* return FALSE if no output generated */ { lrs_mp_matrix A = P->A; long i; long ind; /* output index */ long ired; /* counts number of redundant columns */ /* assign local variables to structures */ long *redundcol = Q->redundcol; long *count = Q->count; long *B = P->B; long *Row = P->Row; long lastdv = Q->lastdv; long hull; long m, d; long lexflag; hull = Q->hull; m = P->m; d = P->d; lexflag = P->lexflag; if (lexflag || Q->allbases) ++(Q->count[1]); if (Q->debug) printA (P, Q); linint (Q->sumdet, 1, P->det, 1); if (Q->getvolume) updatevolume (P, Q); /*print cobasis if printcobasis=TRUE and count[2] a multiple of frequency */ /* or for lexmin basis, except origin for hull computation - ugly! */ if (Q->printcobasis) if ((lexflag && !hull) || ((Q->frequency > 0) && (count[2] == (count[2] / Q->frequency) * Q->frequency))) lrs_printcobasis (P, Q, ZERO); if (hull) return FALSE; /* skip printing the origin */ if (!lexflag && !Q->allbases && !Q->lponly) /* not lexmin, and not printing forced */ return FALSE; /* copy column 0 to output */ i = 1; ired = 0; copy (output[0], P->det); for (ind = 1; ind < Q->n; ind++) /* extract solution */ if ((ired < Q->nredundcol) && (redundcol[ired] == ind)) /* column was deleted as redundant */ { itomp (ZERO, output[ind]); ired++; } else /* column not deleted as redundant */ { getnextoutput (P, Q, i, ZERO, output[ind]); i++; } reducearray (output, Q->n); if (lexflag && one(output[0])) ++Q->count[4]; /* integer vertex */ /* uncomment to print nonzero basic variables printf("\n nonzero basis: vars"); for(i=1;i<=lastdv; i++) { if ( !zero(A[Row[i]][0]) ) printf(" %ld ",B[i]); } */ /* printslack inequality indices */ if (Q->printslack) { fprintf(lrs_ofp,"\nslack ineq:"); for(i=lastdv+1;i<=P->m; i++) { if (!zero(A[Row[i]][0])) fprintf(lrs_ofp," %ld ", Q->inequality[B[i]-lastdv]); } } return TRUE; } /* end of lrs_getvertex */ long lrs_getray (lrs_dic * P, lrs_dat * Q, long col, long redcol, lrs_mp_vector output) /*Print out solution in col and return it in output */ /*redcol =n for ray/facet 0..n-1 for linearity column */ /*hull=1 implies facets will be recovered */ /* return FALSE if no output generated in column col */ { long i; long ind; /* output index */ long ired; /* counts number of redundant columns */ /* assign local variables to structures */ long *redundcol = Q->redundcol; long *count = Q->count; long hull = Q->hull; long n = Q->n; if (Q->debug) { printA (P, Q); for (i = 0; i < Q->nredundcol; i++) fprintf (lrs_ofp, " %ld", redundcol[i]); fflush(lrs_ofp); } if (redcol == n) { ++count[0]; if (Q->printcobasis) lrs_printcobasis (P, Q, col); } i = 1; ired = 0; for (ind = 0; ind < n; ind++) /* print solution */ { if (ind == 0 && !hull) /* must have a ray, set first column to zero */ itomp (ZERO, output[0]); else if ((ired < Q->nredundcol) && (redundcol[ired] == ind)) /* column was deleted as redundant */ { if (redcol == ind) /* true for linearity on this cobasic index */ /* we print reduced determinant instead of zero */ copy (output[ind], P->det); else itomp (ZERO, output[ind]); ired++; } else /* column not deleted as redundant */ { getnextoutput (P, Q, i, col, output[ind]); i++; } } reducearray (output, n); return TRUE; } /* end of lrs_getray */ void getnextoutput (lrs_dic * P, lrs_dat * Q, long i, long col, lrs_mp out) /* get A[B[i][col] and copy to out */ { long row; long m = P->m; long d = P->d; long lastdv = Q->lastdv; lrs_mp_matrix A = P->A; long *B = P->B; long *Row = P->Row; long j; if (i == d && Q->voronoi) return; /* skip last column if voronoi set */ row = Row[i]; if (Q->nonnegative) /* if m+i basic get correct value from dictionary */ /* the slack for the inequality m-d+i contains decision */ /* variable x_i. We first see if this is in the basis */ /* otherwise the value of x_i is zero, except for a ray */ /* when it is one (det/det) for the actual column it is in */ { for (j = lastdv+ 1; j <= m; j++) { if ( Q->inequality[B[j]-lastdv] == m-d+i ) { copy (out, A[Row[j]][col]); return; } } /* did not find inequality m-d+i in basis */ if ( i == col ) copy(out,P->det); else itomp(ZERO,out); } else copy (out, A[row][col]); } /* end of getnextoutput */ void lrs_printcobasis (lrs_dic * P, lrs_dat * Q, long col) /* col is output column being printed */ { long i; long rflag; /* used to find inequality number for ray column */ /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Col = P->Col; long *Row = P->Row; long *inequality = Q->inequality; long *temparray = Q->temparray; long *count = Q->count; long hull = Q->hull; long d = P->d; long lastdv = Q->lastdv; long m=P->m; long firstime=TRUE; long nincidence; /* count number of tight inequalities */ if (hull) fprintf (lrs_ofp, "\nF#%ld B#%ld h=%ld vertices/rays ", count[0], count[2], P->depth); else if (Q->voronoi) fprintf (lrs_ofp, "\nV#%ld R#%ld B#%ld h=%ld data points ", count[1], count[0], count[2], P->depth); else fprintf (lrs_ofp, "\nV#%ld R#%ld B#%ld h=%ld facets ", count[1], count[0], count[2], P->depth); rflag = (-1); for (i = 0; i < d; i++) { temparray[i] = inequality[C[i] - lastdv]; if (Col[i] == col) rflag = temparray[i]; /* look for ray index */ } for (i = 0; i < d; i++) reorder (temparray, d); for (i = 0; i < d; i++) { fprintf (lrs_ofp, " %ld", temparray[i]); if (!(col == ZERO) && (rflag == temparray[i])) /* missing cobasis element for ray */ fprintf (lrs_ofp, "*"); } /* get and print incidence information */ if ( col == 0 ) nincidence = d; else nincidence = d-1; for(i=lastdv+1;i<=m;i++) if ( zero (A[Row[i]][0] )) if( ( col == ZERO ) || zero (A[Row[i]] [col]) ) { nincidence++; if( Q->incidence ) { if (firstime) { fprintf (lrs_ofp," :"); firstime = FALSE; } fprintf(lrs_ofp," %ld",inequality[B[i] - lastdv ] ); } } fprintf(lrs_ofp," I#%ld",nincidence); pmp (" det=", P->det); } /* end of lrs_printcobasis */ /*********************/ /* print final totals */ /*********************/ void lrs_printtotals (lrs_dic * P, lrs_dat * Q) { long i; double x; /* local assignments */ double *cest = Q->cest; long *count = Q->count; long *inequality = Q->inequality; long *linearity = Q->linearity; long *temparray = Q->temparray; long *C = P->C; long hull = Q->hull; long homogeneous = Q->homogeneous; long nlinearity = Q->nlinearity; long nredundcol = Q->nredundcol; long m, d, lastdv; m = P->m; d = P->d; lastdv = Q->lastdv; fprintf (lrs_ofp, "\nend"); if (Q->dualdeg) { fprintf (lrs_ofp, "\n*Warning: Starting dictionary is dual degenerate"); fprintf (lrs_ofp, "\n*Complete enumeration may not have been produced"); if (Q->maximize) fprintf(lrs_ofp,"\n*Recommendation: Add dualperturb option before maximize in input file\n"); else fprintf(lrs_ofp,"\n*Recommendation: Add dualperturb option before minimize in input file\n"); } if (Q->unbounded) { fprintf (lrs_ofp, "\n*Warning: Starting dictionary contains rays"); fprintf (lrs_ofp, "\n*Complete enumeration may not have been produced"); if (Q->maximize) fprintf(lrs_ofp,"\n*Recommendation: Change or remove maximize option or add bounds\n"); else fprintf(lrs_ofp,"\n*Recommendation: Change or remove minimize option or add bounds\n"); } if (Q->truncate) fprintf(lrs_ofp,"\n*Tree truncated at each new vertex"); if (Q->maxdepth < MAXD) fprintf (lrs_ofp, "\n*Tree truncated at depth %ld", Q->maxdepth); if (Q->maxoutput > 0L) fprintf (lrs_ofp, "\n*Maximum number of output lines = %ld", Q->maxoutput); #ifdef LONG fprintf (lrs_ofp, "\n*Caution: no overflow checking with long integer arithemtic"); #else if( Q->verbose) { fprintf (lrs_ofp, "\n*Sum of det(B)="); pmp ("", Q->sumdet); } #endif /* next block with volume rescaling must come before estimates are printed */ if (Q->getvolume) { rescalevolume (P, Q, Q->Nvolume, Q->Dvolume); if (Q->polytope) prat ("\n*Volume=", Q->Nvolume, Q->Dvolume); else prat ("\n*Pseudovolume=", Q->Nvolume, Q->Dvolume); } if (hull) /* output things that are specific to hull computation */ { fprintf (lrs_ofp, "\n*Totals: facets=%ld bases=%ld", count[0], count[2]); if (nredundcol > homogeneous) /* don't count column 1 as redundant if homogeneous */ { fprintf (lrs_ofp, " linearities=%ld", nredundcol - homogeneous); fprintf (lrs_ofp, " facets+linearities=%ld",nredundcol-homogeneous+count[0]); } if ((cest[2] > 0) || (cest[0] > 0)) { fprintf (lrs_ofp, "\n*Estimates: facets=%g bases=%g", count[0] + cest[0], count[2] + cest[2]); if (Q->getvolume) { rattodouble (Q->Nvolume, Q->Dvolume, &x); for (i = 2; i < d; i++) cest[3] = cest[3] / i; /*adjust for dimension */ fprintf (lrs_ofp, " volume=%g", cest[3] + x); } fprintf (lrs_ofp, "\n*Total number of tree nodes evaluated: %ld", Q->totalnodes); } if ( Q-> restart || Q->allbases || (count[0] > 1 && !Q->homogeneous && !Q->polytope)) fprintf (lrs_ofp, "\n*Note! Duplicate facets may be present"); } else /* output things specific to vertex/ray computation */ { fprintf (lrs_ofp, "\n*Totals: vertices=%ld rays=%ld bases=%ld", count[1], count[0], count[2]); fprintf (lrs_ofp, " integer vertices=%ld ",count[4]); if (nredundcol > 0) fprintf (lrs_ofp, " linearities=%ld", nredundcol); if ( count[0] + nredundcol > 0 ) { fprintf (lrs_ofp, " vertices+rays"); if ( nredundcol > 0 ) fprintf (lrs_ofp, "+linearities"); fprintf (lrs_ofp, "=%ld",nredundcol+count[0]+count[1]); } if ((cest[2] > 0) || (cest[0] > 0)) { fprintf (lrs_ofp, "\n*Estimates: vertices=%g rays=%g", count[1]+cest[1], count[0]+cest[0]); fprintf (lrs_ofp, " bases=%g integer vertices=%g ",count[2]+cest[2], count[4]+cest[4]); if (Q->getvolume) { rattodouble (Q->Nvolume, Q->Dvolume, &x); for (i = 2; i <= d-homogeneous; i++) cest[3] = cest[3] / i; /*adjust for dimension */ fprintf (lrs_ofp, " pseudovolume=%g", cest[3] + x); } fprintf (lrs_ofp, "\n*Total number of tree nodes evaluated: %ld", Q->totalnodes); } if (Q->restart || Q->allbases) /* print warning */ fprintf (lrs_ofp, "\n*Note! Duplicate vertices/rays may be present"); else if ( (count[0] > 1 && !Q->homogeneous)) fprintf (lrs_ofp, "\n*Note! Duplicate rays may be present"); } /* end of output for vertices/rays */ if(!Q->verbose) return; fprintf (lrs_ofp, "\n*Input size m=%ld rows n=%ld columns", P->m, Q->n); if (hull) fprintf (lrs_ofp, " working dimension=%ld", d - 1 + homogeneous); else fprintf (lrs_ofp, " working dimension=%ld", d); fprintf (lrs_ofp, "\n*Starting cobasis defined by input rows"); for (i = 0; i < nlinearity; i++) temparray[i] = linearity[i]; for (i = nlinearity; i < lastdv; i++) temparray[i] = inequality[C[i - nlinearity] - lastdv]; for (i = 0; i < lastdv; i++) reorder (temparray, lastdv); for (i = 0; i < lastdv; i++) fprintf (lrs_ofp, " %ld", temparray[i]); fprintf (lrs_ofp, "\n*Dictionary Cache: max size= %ld misses= %ld/%ld Tree Depth= %ld", dict_count, cache_misses, cache_tries, Q->deepest); } /* end of lrs_printtotals */ /************************/ /* Estimation function */ /************************/ void lrs_estimate (lrs_dic * P, lrs_dat * Q) /*get estimate of tree size from current node */ /*current node is not counted. */ /*cest[0]rays [1]vertices [2]bases [3]volume */ /* [4] integer vertices */ { lrs_mp_vector output; /* holds one line of output; ray,vertex,facet,linearity */ lrs_mp Nvol, Dvol; /* hold volume of current basis */ long estdepth = 0; /* depth of basis/vertex in subtree for estimate */ long i = 0, j = 0, k, nchild, runcount, col; double prod = 0.0; double cave[] = {0.0, 0.0, 0.0, 0.0, 0.0}; double nvertices, nbases, nrays, nvol, nivertices; long rays = 0; double newvol = 0.0; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *isave = Q->isave; long *jsave = Q->jsave; double *cest = Q->cest; long d = P->d; lrs_alloc_mp(Nvol); lrs_alloc_mp(Dvol); /* Main Loop of Estimator */ output = lrs_alloc_mp_vector (Q->n); /* output holds one line of output from dictionary */ for (runcount = 1; runcount <= Q->runs; runcount++) { /* runcount counts number of random probes */ j = 0; nchild = 1; prod = 1; nvertices = 0.0; nbases = 0.0; nrays = 0.0; nvol = 0.0; nivertices =0.0; while (nchild != 0) /* while not finished yet */ { nchild = 0; while (j < d) { if (reverse (P, Q, &i, j)) { isave[nchild] = i; jsave[nchild] = j; nchild++; } j++; } if (estdepth == 0 && nchild == 0) { cest[0] = cest[0] + rays; /* may be some rays here */ lrs_clear_mp(Nvol); lrs_clear_mp(Dvol); return; /*subtree is a leaf */ } prod = prod * nchild; nbases = nbases + prod; if (Q->debug) { fprintf (lrs_ofp, " degree= %ld ", nchild); fprintf (lrs_ofp, "\nPossible reverse pivots: i,j="); for (k = 0; k < nchild; k++) fprintf (lrs_ofp, "%ld,%ld ", isave[k], jsave[k]); } if (nchild > 0) /*reverse pivot found choose random child */ { k = myrandom (Q->seed, nchild); Q->seed = myrandom (Q->seed, 977L); i = isave[k]; j = jsave[k]; if (Q->debug) fprintf (lrs_ofp, " selected pivot k=%ld seed=%ld ", k, Q->seed); estdepth++; Q->totalnodes++; /* calculate total number of nodes evaluated */ pivot (P, Q, i, j); update (P, Q, &i, &j); /*Update B,C,i,j */ if (lexmin (P, Q, ZERO)) /* see if lexmin basis for vertex */ { nvertices = nvertices + prod; /* integer vertex estimate */ if( lrs_getvertex(P,Q,output)) { --Q->count[1]; if (one(output[0] )) { --Q->count[4]; nivertices = nivertices + prod; } } } rays = 0; for (col = 1; col <= d; col++) if (negative (A[0][col]) && (ratio (P, Q, col) == 0) && lexmin (P, Q, col)) rays++; nrays = nrays + prod * rays; /* update ray info */ if (Q->getvolume) { rescaledet (P, Q, Nvol, Dvol); /* scales determinant in case input rational */ rattodouble (Nvol, Dvol, &newvol); nvol = nvol + newvol * prod; /* adjusts volume for degree */ } j = 0; } } cave[0] = cave[0] + nrays; cave[1] = cave[1] + nvertices; cave[2] = cave[2] + nbases; cave[3] = cave[3] + nvol; cave[4] = cave[4] + nivertices; /* backtrack to root and do it again */ while (estdepth > 0) { estdepth = estdepth - 1; selectpivot (P, Q, &i, &j); pivot (P, Q, i, j); update (P, Q, &i, &j); /*Update B,C,i,j */ /*fprintf(lrs_ofp,"\n0 +++"); */ if (Q->debug) { fprintf (lrs_ofp, "\n Backtrack Pivot: indices i,j %ld %ld ", i, j); printA (P, Q); } j++; } } /* end of for loop on runcount */ for (i = 0; i < 5; i++) cest[i] = cave[i] / Q->runs + cest[i]; lrs_clear_mp(Nvol); lrs_clear_mp(Dvol); lrs_clear_mp_vector(output, Q->n); } /* end of lrs_estimate */ /*********************************/ /* Internal functions */ /*********************************/ /* Basic Dictionary functions */ /******************************* */ long reverse (lrs_dic * P, lrs_dat * Q, long *r, long s) /* find reverse indices */ /* TRUE if B[*r] C[s] is a reverse lexicographic pivot */ { long i, j, enter, row, col; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Row = P->Row; long *Col = P->Col; long d = P->d; enter = C[s]; col = Col[s]; if (Q->debug) { fprintf (lrs_ofp, "\n+reverse: col index %ld C %ld Col %ld ", s, enter, col); fflush (stdout); } if (!negative (A[0][col])) { if (Q->debug) fprintf (lrs_ofp, " Pos/Zero Cost Coeff"); return (FALSE); } *r = ratio (P, Q, col); if (*r == 0) /* we have a ray */ { if (Q->debug) fprintf (lrs_ofp, " Pivot col non-negative: ray found"); return (FALSE); } row = Row[*r]; /* check cost row after "pivot" for smaller leaving index */ /* ie. j s.t. A[0][j]*A[row][col] < A[0][col]*A[row][j] */ /* note both A[row][col] and A[0][col] are negative */ for (i = 0; i < d && C[i] < B[*r]; i++) if (i != s) { j = Col[i]; if (positive (A[0][j]) || negative (A[row][j])) /*or else sign test fails trivially */ if ((!negative (A[0][j]) && !positive (A[row][j])) || comprod (A[0][j], A[row][col], A[0][col], A[row][j]) == -1) { /*+ve cost found */ if (Q->debug) { fprintf (lrs_ofp, "\nPositive cost found: index %ld C %ld Col %ld", i, C[i], j); fflush(lrs_ofp); } return (FALSE); } } if (Q->debug) { fprintf (lrs_ofp, "\n+end of reverse : indices r %ld s %ld \n", *r, s); fflush (stdout); } return (TRUE); } /* end of reverse */ long selectpivot (lrs_dic * P, lrs_dat * Q, long *r, long *s) /* select pivot indices using lexicographic rule */ /* returns TRUE if pivot found else FALSE */ /* pivot variables are B[*r] C[*s] in locations Row[*r] Col[*s] */ { long j, col; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *Col = P->Col; long d = P->d; *r = 0; *s = d; j = 0; /*find positive cost coef */ while ((j < d) && (!positive (A[0][Col[j]]))) j++; if (j < d) /* pivot column found! */ { *s = j; col = Col[j]; /*find min index ratio */ *r = ratio (P, Q, col); if (*r != 0) return (TRUE); /* unbounded */ } return (FALSE); } /* end of selectpivot */ /******************************************************* */ void pivot (lrs_dic * P, lrs_dat * Q, long bas, long cob) /* Qpivot routine for array A */ /* indices bas, cob are for Basis B and CoBasis C */ /* corresponding to row Row[bas] and column */ /* Col[cob] respectively */ { long r, s; long i, j; lrs_mp Ns, Nt, Ars; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Row = P->Row; long *Col = P->Col; long m, d, m_A; lrs_alloc_mp(Ns); lrs_alloc_mp(Nt); lrs_alloc_mp(Ars); m = P->m; d = P->d; m_A = P->m_A; Q->count[3]++; /* count the pivot */ r = Row[bas]; s = Col[cob]; /* Ars=A[r][s] */ if (Q->debug) { fprintf (lrs_ofp, "\n pivot B[%ld]=%ld C[%ld]=%ld ", bas, B[bas], cob, C[cob]); printA(P,Q); fflush (stdout); } copy (Ars, A[r][s]); storesign (P->det, sign (Ars)); /*adjust determinant to new sign */ for (i = 0; i <= m_A; i++) if (i != r) for (j = 0; j <= d; j++) if (j != s) { /* A[i][j]=(A[i][j]*Ars-A[i][s]*A[r][j])/P->det; */ mulint (A[i][j], Ars, Nt); mulint (A[i][s], A[r][j], Ns); decint (Nt, Ns); exactdivint (Nt, P->det, A[i][j]); } /* end if j .... */ if (sign (Ars) == POS) { for (j = 0; j <= d; j++) /* no need to change sign if Ars neg */ /* A[r][j]=-A[r][j]; */ if (!zero (A[r][j])) changesign (A[r][j]); } /* watch out for above "if" when removing this "}" ! */ else for (i = 0; i <= m_A; i++) if (!zero (A[i][s])) changesign (A[i][s]); /* A[r][s]=P->det; */ copy (A[r][s], P->det); /* restore old determinant */ copy (P->det, Ars); storesign (P->det, POS); /* always keep positive determinant */ if (Q->debug) { fprintf (lrs_ofp, " depth=%ld ", P->depth); pmp ("det=", P->det); fflush(stdout); } /* set the new rescaled objective function value */ mulint (P->det, Q->Lcm[0], P->objden); mulint (Q->Gcd[0], A[0][0], P->objnum); if (!Q->maximize) changesign (P->objnum); if (zero (P->objnum)) storesign (P->objnum, POS); else reduce (P->objnum,P->objden); lrs_clear_mp(Ns); lrs_clear_mp(Nt); lrs_clear_mp(Ars); } /* end of pivot */ long primalfeasible (lrs_dic * P, lrs_dat * Q) /* Do dual pivots to get primal feasibility */ /* Note that cost row is all zero, so no ratio test needed for Dual Bland's rule */ { long primalinfeasible = TRUE; long i, j; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *Row = P->Row; long *Col = P->Col; long m, d, lastdv; m = P->m; d = P->d; lastdv = Q->lastdv; /*temporary: try to get new start after linearity */ while (primalinfeasible) { i=lastdv+1; while (i <= m && !negative (A[Row[i]][0]) ) i++; if (i <= m ) { j = 0; /*find a positive entry for in row */ while (j < d && !positive (A[Row[i]][Col[j]])) j++; if (j >= d) return (FALSE); /* no positive entry */ pivot (P, Q, i, j); update (P, Q, &i, &j); } else primalinfeasible = FALSE; } /* end of while primalinfeasibile */ return (TRUE); } /* end of primalfeasible */ long lrs_solvelp (lrs_dic * P, lrs_dat * Q, long maximize) /* Solve primal feasible lp by Dantzig`s rule and lexicographic ratio test */ /* return TRUE if bounded, FALSE if unbounded */ { long i, j; /* assign local variables to structures */ long d = P->d; while (dan_selectpivot (P, Q, &i, &j)) { Q->count[3]++; pivot (P, Q, i, j); update (P, Q, &i, &j); /*Update B,C,i,j */ } if (Q->debug) printA (P, Q); if (j < d && i == 0) /* selectpivot gives information on unbounded solution */ { #ifndef LRS_QUIET if (Q->lponly) fprintf (lrs_ofp, "\n*Unbounded solution"); #endif return FALSE; } return TRUE; } /* end of lrs_solvelp */ long getabasis (lrs_dic * P, lrs_dat * Q, long order[]) /* Pivot Ax<=b to standard form */ /*Try to find a starting basis by pivoting in the variables x[1]..x[d] */ /*If there are any input linearities, these appear first in order[] */ /* Steps: (a) Try to pivot out basic variables using order */ /* Stop if some linearity cannot be made to leave basis */ /* (b) Permanently remove the cobasic indices of linearities */ /* (c) If some decision variable cobasic, it is a linearity, */ /* and will be removed. */ { long i, j, k; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Row = P->Row; long *Col = P->Col; long *linearity = Q->linearity; long *redundcol = Q->redundcol; long m, d, nlinearity; long nredundcol = 0L; /* will be calculated here */ m = P->m; d = P->d; nlinearity = Q->nlinearity; if (Q->debug) { fprintf (lrs_ofp, "\ngetabasis from inequalities given in order"); for (i = 0; i < m; i++) fprintf (lrs_ofp, " %ld", order[i]); } for (j = 0; j < m; j++) { i = 0; while (i <= m && B[i] != d + order[j]) i++; /* find leaving basis index i */ if (j < nlinearity && i > m) /* cannot pivot linearity to cobasis */ { if (Q->debug) printA (P, Q); #ifndef LRS_QUIET fprintf (lrs_ofp, "\nCannot find linearity in the basis"); #endif return FALSE; } if (i <= m) { /* try to do a pivot */ k = 0; while (C[k] <= d && zero (A[Row[i]][Col[k]])) k++; if (C[k] <= d) { pivot (P, Q, i, k); update (P, Q, &i, &k); } else if (j < nlinearity) { /* cannot pivot linearity to cobasis */ if (zero (A[Row[i]][0])) { #ifndef LRS_QUIET fprintf (lrs_ofp, "\n*Input linearity in row %ld is redundant--skipped\n", order[j]); #endif linearity[j] = 0; } else { if (Q->debug) printA (P, Q); #ifndef LRS_QUIET fprintf (lrs_ofp, "\n*Input linearity in row %ld is inconsistent with earlier linearities", order[j]); fprintf (lrs_ofp, "\n*No feasible solution\n"); #endif return FALSE; } } /* end if j < nlinearity */ } /* end of if i <= m .... */ } /* end of for */ /* update linearity array to get rid of redundancies */ i = 0; k = 0; /* counters for linearities */ while (k < nlinearity) { while (k < nlinearity && linearity[k] == 0) k++; if (k < nlinearity) linearity[i++] = linearity[k++]; } nlinearity = i; /* column dependencies now can be recorded */ /* redundcol contains input column number 0..n-1 where redundancy is */ k = 0; while (k < d && C[k] <= d) { if (C[k] <= d) /* decision variable still in cobasis */ redundcol[nredundcol++] = C[k] - Q->hull; /* adjust for hull indices */ k++; } /* now we know how many decision variables remain in problem */ Q->nredundcol = nredundcol; Q->lastdv = d - nredundcol; if (Q->debug) { fprintf (lrs_ofp, "\nend of first phase of getabasis: "); fprintf (lrs_ofp, "lastdv=%ld nredundcol=%ld", Q->lastdv, Q->nredundcol); fprintf (lrs_ofp, "\nredundant cobases:"); for (i = 0; i < nredundcol; i++) fprintf (lrs_ofp, " %ld", redundcol[i]); printA (P, Q); } /* Remove linearities from cobasis for rest of computation */ /* This is done in order so indexing is not screwed up */ for (i = 0; i < nlinearity; i++) { /* find cobasic index */ k = 0; while (k < d && C[k] != linearity[i] + d) k++; if (k >= d) { fprintf (lrs_ofp, "\nError removing linearity"); return FALSE; } if (!removecobasicindex (P, Q, k)) return FALSE; d = P->d; } if (Q->debug && nlinearity > 0) printA (P, Q); /* set index value for first slack variable */ /* Check feasability */ if (Q->givenstart) { i = Q->lastdv + 1; while (i <= m && !negative (A[Row[i]][0])) i++; if (i <= m) fprintf (lrs_ofp, "\n*Infeasible startingcobasis - will be modified"); } return TRUE; } /* end of getabasis */ long removecobasicindex (lrs_dic * P, lrs_dat * Q, long k) /* remove the variable C[k] from the problem */ /* used after detecting column dependency */ { long i, j, cindex, deloc; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Col = P->Col; long m, d; m = P->m; d = P->d; if (Q->debug) fprintf (lrs_ofp, "\nremoving cobasic index k=%ld C[k]=%ld", k, C[k]); cindex = C[k]; /* cobasic index to remove */ deloc = Col[k]; /* matrix column location to remove */ for (i = 1; i <= m; i++) /* reduce basic indices by 1 after index */ if (B[i] > cindex) B[i]--; for (j = k; j < d; j++) /* move down other cobasic variables */ { C[j] = C[j + 1] - 1; /* cobasic index reduced by 1 */ Col[j] = Col[j + 1]; } if (deloc != d) { /* copy col d to deloc */ for (i = 0; i <= m; i++) copy (A[i][deloc], A[i][d]); /* reassign location for moved column */ j = 0; while (Col[j] != d) j++; Col[j] = deloc; } P->d--; if (Q->debug) printA (P, Q); return TRUE; } /* end of removecobasicindex */ lrs_dic * resize (lrs_dic * P, lrs_dat * Q) /* resize the dictionary after some columns are deleted, ie. inputd>d */ /* a new lrs_dic record is created with reduced size, and items copied over */ { lrs_dic *P1; /* to hold new dictionary in case of resizing */ long i, j; long m, d, m_A; m = P->m; d = P->d; m_A = P->m_A; /* get new dictionary record */ P1 = new_lrs_dic (m, d, m_A); /* copy data from P to P1 */ P1->i = P->i; P1->j = P->j; P1->depth = P->depth; P1->m = P->m; P1->d = P1->d_orig = d; P1->lexflag = P->lexflag; P1->m_A = P->m_A; copy (P1->det, P->det); copy (P1->objnum, P->objnum); copy (P1->objden, P->objden); for (i = 0; i <= m; i++) { P1->B[i] = P->B[i]; P1->Row[i] = P->Row[i]; } for (i = 0; i <= m_A; i++) { for (j = 0; j <= d; j++) copy (P1->A[i][j], P->A[i][j]); } for (j = 0; j <= d; j++) { P1->Col[j] = P->Col[j]; P1->C[j] = P->C[j]; } if (Q->debug) { fprintf (lrs_ofp, "\nDictionary resized from d=%ld to d=%ld", Q->inputd, P->d); printA (P1, Q); } lrs_free_dic (P,Q); /* Reassign cache pointers */ Q->Qhead = P1; Q->Qtail = P1; P1->next = P1; P1->prev = P1; return P1; } /********* resize ***************/ long restartpivots (lrs_dic * P, lrs_dat * Q) /* facet contains a list of the inequalities in the cobasis for the restart */ /* inequality contains the relabelled inequalities after initialization */ { long i, j, k; long *Cobasic; /* when restarting, Cobasic[j]=1 if j is in cobasis */ /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Row = P->Row; long *Col = P->Col; long *inequality = Q->inequality; long *facet = Q->facet; long nlinearity = Q->nlinearity; long m, d, lastdv; m = P->m; d = P->d; lastdv = Q->lastdv; Cobasic = (long *) CALLOC ((unsigned) m + d + 2, sizeof (long)); if (Q->debug) fprintf(lrs_ofp,"\nCobasic flags in restartpivots"); /* set Cobasic flags */ for (i = 0; i < m + d + 1; i++) Cobasic[i] = 0; for (i = 0; i < d; i++) /* find index corresponding to facet[i] */ { j = 1; while (facet[i + nlinearity] != inequality[j]) j++; Cobasic[j + lastdv] = 1; if (Q->debug) fprintf(lrs_ofp," %ld %ld;",facet[i+nlinearity],j+lastdv); } /* Note that the order of doing the pivots is important, as */ /* the B and C vectors are reordered after each pivot */ for (i = m; i >= d + 1; i--) /*see if a basic variable should leave */ if (Cobasic[B[i]]) /* basic variable must leave */ { /* find a Cobasic variable that must enter basis */ k = d - 1; while ((k >= 0) && (zero (A[Row[i]][Col[k]]) || Cobasic[C[k]])) k--; if (k >= 0) { pivot (P, Q, i, k); update (P, Q, &i, &k); } else { fprintf (lrs_ofp, "\nInvalid Co-basis - does not have correct rank"); free(Cobasic); return FALSE; } } /* end of if(Cobasic.. */ if (lexmin (P, Q, ZERO)) --Q->count[1]; /* decrement vertex count if lexmin */ /* check restarting from a primal feasible dictionary */ for (i = lastdv + 1; i <= m; i++) if (negative (A[Row[i]][0])) { fprintf (lrs_ofp, "\nTrying to restart from infeasible dictionary"); free(Cobasic); return FALSE; } free(Cobasic); return TRUE; } /* end of restartpivots */ long ratio (lrs_dic * P, lrs_dat * Q, long col) /*find lex min. ratio */ /* find min index ratio -aig/ais, ais<0 */ /* if multiple, checks successive basis columns */ /* recoded Dec 1997 */ { long i, j, comp, ratiocol, basicindex, start, nstart, cindex, bindex; long firstime; /*For ratio test, true on first pass,else false */ lrs_mp Nmin, Dmin; long degencount, ndegencount; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *Row = P->Row; long *Col = P->Col; long *minratio = Q->minratio; long m, d, lastdv; m = P->m; d = P->d; lastdv = Q->lastdv; nstart=0; ndegencount=0; degencount = 0; for (j = lastdv + 1; j <= m; j++) { /* search rows with negative coefficient in dictionary */ /* minratio contains indices of min ratio cols */ if (negative (A[Row[j]][col])) minratio[degencount++] = j; } /* end of for loop */ if (Q->debug) { fprintf (lrs_ofp, " Min ratios: "); for (i = 0; i < degencount; i++) fprintf (lrs_ofp, " %ld ", B[minratio[i]]); } if (degencount == 0) return (degencount); /* non-negative pivot column */ lrs_alloc_mp(Nmin); lrs_alloc_mp(Dmin); ratiocol = 0; /* column being checked, initially rhs */ start = 0; /* starting location in minratio array */ bindex = d + 1; /* index of next basic variable to consider */ cindex = 0; /* index of next cobasic variable to consider */ basicindex = d; /* index of basis inverse for current ratio test, except d=rhs test */ while (degencount > 1) /*keep going until unique min ratio found */ { if (B[bindex] == basicindex) /* identity col in basis inverse */ { if (minratio[start] == bindex) /* remove this index, all others stay */ { start++; degencount--; } bindex++; } else /* perform ratio test on rhs or column of basis inverse */ { firstime = TRUE; /*get next ratio column and increment cindex */ if (basicindex != d) ratiocol = Col[cindex++]; for (j = start; j < start + degencount; j++) { i = Row[minratio[j]]; /* i is the row location of the next basic variable */ comp = 1; /* 1: lhs>rhs; 0:lhs=rhs; -1: lhsdebug) { fprintf (lrs_ofp, " ratiocol=%ld degencount=%ld ", ratiocol, degencount); fprintf (lrs_ofp, " Min ratios: "); for (i = start; i < start + degencount; i++) fprintf (lrs_ofp, " %ld ", B[minratio[i]]); } } /*end of while loop */ lrs_clear_mp(Nmin); lrs_clear_mp(Dmin); return (minratio[start]); } /* end of ratio */ long lexmin (lrs_dic * P, lrs_dat * Q, long col) /*test if basis is lex-min for vertex or ray, if so TRUE */ /* FALSE if a_r,g=0, a_rs !=0, r > s */ { /*do lexmin test for vertex if col=0, otherwise for ray */ long r, s, i, j; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Row = P->Row; long *Col = P->Col; long m = P->m; long d = P->d; for (i = Q->lastdv + 1; i <= m; i++) { r = Row[i]; if (zero (A[r][col])) /* necessary for lexmin to fail */ for (j = 0; j < d; j++) { s = Col[j]; if (B[i] > C[j]) /* possible pivot to reduce basis */ { if (zero (A[r][0])) /* no need for ratio test, any pivot feasible */ { if (!zero (A[r][s])) return (FALSE); } else if (negative (A[r][s]) && ismin (P, Q, r, s)) { return (FALSE); } } /* end of if B[i] ... */ } } if ((col != ZERO) && Q->debug) { fprintf (lrs_ofp, "\n lexmin ray in col=%ld ", col); printA (P, Q); } return (TRUE); } /* end of lexmin */ long ismin (lrs_dic * P, lrs_dat * Q, long r, long s) /*test if A[r][s] is a min ratio for col s */ { long i; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long m_A = P->m_A; for (i = 1; i <= m_A; i++) if ((i != r) && negative (A[i][s]) && comprod (A[i][0], A[r][s], A[i][s], A[r][0])) { return (FALSE); } return (TRUE); } void update (lrs_dic * P, lrs_dat * Q, long *i, long *j) /*update the B,C arrays after a pivot */ /* involving B[bas] and C[cob] */ { long leave, enter; /* assign local variables to structures */ long *B = P->B; long *C = P->C; long *Row = P->Row; long *Col = P->Col; long m = P->m; long d = P->d; leave = B[*i]; enter = C[*j]; B[*i] = enter; reorder1 (B, Row, *i, m + 1); C[*j] = leave; reorder1 (C, Col, *j, d); /* restore i and j to new positions in basis */ for (*i = 1; B[*i] != enter; (*i)++); /*Find basis index */ for (*j = 0; C[*j] != leave; (*j)++); /*Find co-basis index */ } /* end of update */ long lrs_degenerate (lrs_dic * P, lrs_dat * Q) /* TRUE if the current dictionary is primal degenerate */ /* not thoroughly tested 2000/02/15 */ { long i; long *B, *Row; lrs_mp_matrix A = P->A; long d = P->d; long m = P->m; B = P->B; Row = P->Row; for (i = d + 1; i <= m; i++) if (zero (A[Row[i]][0])) return TRUE; return FALSE; } /*********************************************************/ /* Miscellaneous */ /******************************************************* */ void reorder (long a[], long range) /*reorder array in increasing order with one misplaced element */ { long i, temp; for (i = 0; i < range - 1; i++) if (a[i] > a[i + 1]) { temp = a[i]; a[i] = a[i + 1]; a[i + 1] = temp; } for (i = range - 2; i >= 0; i--) if (a[i] > a[i + 1]) { temp = a[i]; a[i] = a[i + 1]; a[i + 1] = temp; } } /* end of reorder */ void reorder1 (long a[], long b[], long newone, long range) /*reorder array a in increasing order with one misplaced element at index newone */ /*elements of array b are updated to stay aligned with a */ { long temp; while (newone > 0 && a[newone] < a[newone - 1]) { temp = a[newone]; a[newone] = a[newone - 1]; a[newone - 1] = temp; temp = b[newone]; b[newone] = b[newone - 1]; b[--newone] = temp; } while (newone < range - 1 && a[newone] > a[newone + 1]) { temp = a[newone]; a[newone] = a[newone + 1]; a[newone + 1] = temp; temp = b[newone]; b[newone] = b[newone + 1]; b[++newone] = temp; } } /* end of reorder1 */ void rescaledet (lrs_dic * P, lrs_dat * Q, lrs_mp Vnum, lrs_mp Vden) /* rescale determinant to get its volume */ /* Vnum/Vden is volume of current basis */ { lrs_mp gcdprod; /* to hold scale factors */ long i; /* assign local variables to structures */ long *B = P->B; long *C = P->C; long m, d, lastdv; lrs_alloc_mp(gcdprod); m = P->m; d = P->d; lastdv = Q->lastdv; itomp (ONE, gcdprod); itomp (ONE, Vden); for (i = 0; i < d; i++) if (B[i] <= m) { mulint (Q->Gcd[Q->inequality[C[i] - lastdv]], gcdprod, gcdprod); mulint (Q->Lcm[Q->inequality[C[i] - lastdv]], Vden, Vden); } mulint (P->det, gcdprod, Vnum); reduce (Vnum, Vden); lrs_clear_mp(gcdprod); } /* end rescaledet */ void rescalevolume (lrs_dic * P, lrs_dat * Q, lrs_mp Vnum, lrs_mp Vden) /* adjust volume for dimension */ { lrs_mp temp, dfactorial; /* assign local variables to structures */ long lastdv = Q->lastdv; lrs_alloc_mp(temp); lrs_alloc_mp(dfactorial); /*reduce Vnum by d factorial */ getfactorial (dfactorial, lastdv); mulint (dfactorial, Vden, Vden); if (Q->hull && !Q->homogeneous) { /* For hull option multiply by d to correct for lifting */ itomp (lastdv, temp); mulint (temp, Vnum, Vnum); } reduce (Vnum, Vden); lrs_clear_mp(temp); lrs_clear_mp(dfactorial); } void updatevolume (lrs_dic * P, lrs_dat * Q) /* rescale determinant and update the volume */ { lrs_mp tN, tD, Vnum, Vden; lrs_alloc_mp(tN); lrs_alloc_mp(tD); lrs_alloc_mp(Vnum); lrs_alloc_mp(Vden); rescaledet (P, Q, Vnum, Vden); copy (tN, Q->Nvolume); copy (tD, Q->Dvolume); linrat (tN, tD, ONE, Vnum, Vden, ONE, Q->Nvolume, Q->Dvolume); if (Q->debug) { prat ("\n*Volume=", Q->Nvolume, Q->Dvolume); pmp (" Vnum=", Vnum); pmp (" Vden=", Vden); } lrs_clear_mp(tN); lrs_clear_mp(tD); lrs_clear_mp(Vnum); lrs_clear_mp(Vden); } /* end of updatevolume */ /***************************************************/ /* Routines for redundancy checking */ /***************************************************/ long checkredund (lrs_dic * P, lrs_dat * Q) /* Solve primal feasible lp by least subscript and lex min basis method */ /* to check redundancy of a row in objective function */ /* returns TRUE if redundant, else FALSE */ { lrs_mp Ns, Nt; long i, j; long r, s; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B, *C, *Row, *Col; long d = P->d; lrs_alloc_mp(Ns); lrs_alloc_mp(Nt); B = P->B; C = P->C; Row = P->Row; Col = P->Col; while (selectpivot (P, Q, &i, &j)) { Q->count[2]++; /* sign of new value of A[0][0] */ /* is A[0][s]*A[r][0]-A[0][0]*A[r][s] */ r = Row[i]; s = Col[j]; mulint (A[0][s], A[r][0], Ns); mulint (A[0][0], A[r][s], Nt); if (greater (Ns, Nt)) { lrs_clear_mp(Ns); lrs_clear_mp(Nt); return FALSE; /* non-redundant */ } pivot (P, Q, i, j); update (P, Q, &i, &j); /*Update B,C,i,j */ } lrs_clear_mp(Ns); lrs_clear_mp(Nt); return !(j < d && i == 0); /* unbounded is also non-redundant */ } /* end of checkredund */ long checkcobasic (lrs_dic * P, lrs_dat * Q, long index) /* TRUE if index is cobasic and nonredundant */ /* FALSE if basic, or degen. cobasic, where it will get pivoted out */ { /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B, *C, *Row, *Col; long d = P->d; long m = P->m; long debug = Q->debug; long i = 0; long j = 0; long s; B = P->B; C = P->C; Row = P->Row; Col = P->Col; while ((j < d) && C[j] != index) j++; if (j == d) return FALSE; /* not cobasic index */ /* index is cobasic */ if (debug) fprintf (lrs_ofp, "\nindex=%ld cobasic", index); /* not debugged for new LOC s=LOC[index]; */ s = Col[j]; i = Q->lastdv + 1; while ((i <= m) && (zero (A[Row[i]][s]) || !zero (A[Row[i]][0]))) i++; if (i > m) { if (debug) fprintf (lrs_ofp, " is non-redundant"); return TRUE; } if (debug) fprintf (lrs_ofp, " is degenerate B[i]=%ld", B[i]); pivot (P, Q, i, j); update (P, Q, &i, &j); /*Update B,C,i,j */ return FALSE; /*index is no longer cobasic */ } /* end of checkcobasic */ long checkindex (lrs_dic * P, lrs_dat * Q, long index) /* 0 if index is non-redundant inequality */ /* 1 if index is redundant inequality */ /* 2 if index is input linearity */ /*NOTE: row is returned all zero if redundant!! */ { long i, j; lrs_mp_matrix A = P->A; long *Row = P->Row; long *B = P->B; long d = P->d; long m = P->m; if (Q->debug) printA (P, Q); /* each slack index must be checked for redundancy */ /* if in cobasis, it is pivoted out if degenerate */ /* else it is non-redundant */ if (checkcobasic (P, Q, index)) return ZERO; /* index is basic */ /* not debugged for new LOC i=LOC[index]; */ j = 1; while ((j <= m) && (B[j] != index)) j++; i = Row[j]; /* copy row i to cost row, and set it to zero */ for (j = 0; j <= d; j++) { copy (A[0][j], A[i][j]); changesign (A[0][j]); itomp (ZERO, A[i][j]); } if (checkredund (P, Q)) return ONE; /* non-redundant, copy back and change sign */ for (j = 0; j <= d; j++) { copy (A[i][j], A[0][j]); changesign (A[i][j]); } return ZERO; } /* end of checkindex */ /***************************************************************/ /* */ /* Package of I/O routines */ /* */ /***************************************************************/ void lprat (const char *name, long Nt, long Dt) /*print the long precision rational Nt/Dt without reducing */ { if ( Nt > 0 ) fprintf (lrs_ofp, " "); fprintf (lrs_ofp, "%s%ld", name, Nt); if (Dt != 1) fprintf (lrs_ofp, "/%ld", Dt); fprintf (lrs_ofp, " "); } /* lprat */ long lreadrat (long *Num, long *Den) /* read a rational string and convert to long */ /* returns true if denominator is not one */ { char in[MAXINPUT], num[MAXINPUT], den[MAXINPUT]; fscanf (lrs_ifp, "%s", in); atoaa (in, num, den); /*convert rational to num/dem strings */ *Num = atol (num); if (den[0] == '\0') { *Den = 1L; return (FALSE); } *Den = atol (den); return (TRUE); } void lrs_getinput(lrs_dic *P,lrs_dat *Q,long *num,long *den, long m, long d) /* code for reading data matrix in lrs/cdd format */ { long j,row; printf("\nEnter each row: b_i a_ij j=1..%ld",d); for (row=1;row<=m;row++) { printf("\nEnter row %ld: ",row ); for(j=0;j<=d;j++) { lreadrat(&num[j],&den[j]); lprat(" ",num[j],den[j]); } lrs_set_row(P,Q,row,num,den,GE); } printf("\nEnter objective row c_j j=1..%ld: ",d); num[0]=0; den[0]=1; for(j=1;j<=d;j++) { lreadrat(&num[j],&den[j]); lprat(" ",num[j],den[j]); } lrs_set_obj(P,Q,num,den,MAXIMIZE); } long readlinearity (lrs_dat * Q) /* read in and check linearity list */ { long i, j; long nlinearity; fscanf (lrs_ifp, "%ld", &nlinearity); if (nlinearity < 1) { fprintf (lrs_ofp, "\nLinearity option invalid, indices must be positive"); return (FALSE); } Q->linearity = CALLOC ((nlinearity + 1), sizeof (long)); for (i = 0; i < nlinearity; i++) { fscanf (lrs_ifp, "%ld", &j); Q->linearity[i] = j; } for (i = 1; i < nlinearity; i++) /*sort in order */ reorder (Q->linearity, nlinearity); Q->nlinearity = nlinearity; Q->polytope = FALSE; return TRUE; } /* end readlinearity */ long readfacets (lrs_dat * Q, long facet[]) /* read and check facet list for obvious errors during start/restart */ /* this must be done after linearity option is processed!! */ { long i, j; /* assign local variables to structures */ long m, d; long *linearity = Q->linearity; m = Q->m; d = Q->inputd; for (j = Q->nlinearity; j < d; j++) /* note we place these after the linearity indices */ { fscanf (lrs_ifp, "%ld", &facet[j]); fprintf (lrs_ofp, " %ld", facet[j]); if (facet[j] < 1 || facet[j] > m) { fprintf (lrs_ofp, "\n Start/Restart cobasic indices must be in range 1 .. %ld ", m); return FALSE; } for (i = 0; i < Q->nlinearity; i++) if (linearity[i] == facet[j]) { fprintf (lrs_ofp, "\n Start/Restart cobasic indices should not include linearities"); return FALSE; } for (i = 0; i < j; i++) if (facet[i] == facet[j]) { fprintf (lrs_ofp, "\n Start/Restart cobasic indices must be distinct"); return FALSE; } } return TRUE; } /* end of readfacets */ void printA (lrs_dic * P, lrs_dat * Q) /* print the integer m by n array A with B,C,Row,Col vectors */ { long i, j; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Row = P->Row; long *Col = P->Col; long m, d, lastdv; m = P->m; d = P->d; lastdv = Q->lastdv; fprintf (lrs_ofp, "\n Basis "); for (i = 0; i <= m; i++) fprintf (lrs_ofp, "%ld ", B[i]); fprintf (lrs_ofp, " Row "); for (i = 0; i <= m; i++) fprintf (lrs_ofp, "%ld ", Row[i]); fprintf (lrs_ofp, "\n Co-Basis "); for (i = 0; i <= d; i++) fprintf (lrs_ofp, "%ld ", C[i]); fprintf (lrs_ofp, " Column "); for (i = 0; i <= d; i++) fprintf (lrs_ofp, "%ld ", Col[i]); pmp (" det=", P->det); fprintf (lrs_ofp, "\n"); i=0; while ( i<= m ) { for (j = 0; j <= d; j++) pimat (P, i, j, A[Row[i]][Col[j]], "A"); fprintf (lrs_ofp, "\n"); if (i==0 && Q->nonnegative) /* skip basic rows - don't exist! */ i=d; i++; fflush (stdout); } fflush (stdout); } void pimat (lrs_dic * P, long r, long s, lrs_mp Nt, char name[]) /*print the long precision integer in row r col s of matrix A */ { long *B = P->B; long *C = P->C; if (s == 0) fprintf (lrs_ofp, "%s[%ld][%ld]=", name, B[r], C[s]); else fprintf (lrs_ofp, "[%ld]=", C[s]); pmp ("", Nt); } /***************************************************************/ /* */ /* Routines for caching, allocating etc. */ /* */ /***************************************************************/ /* From here mostly Bremner's handiwork */ void cache_dict (lrs_dic ** D_p, lrs_dat * global, long i, long j) { if (dict_limit > 1) { /* save row, column indicies */ (*D_p)->i = i; (*D_p)->j = j; /* Make a new, blank spot at the end of the queue to copy into */ pushQ (global, (*D_p)->m, (*D_p)->d, (*D_p)->m_A); copy_dict (global, global->Qtail, *D_p); /* Copy current dictionary */ } *D_p = global->Qtail; } void copy_dict (lrs_dat * global, lrs_dic * dest, lrs_dic * src) { long m = src->m; long m_A = src->m_A; /* number of rows in A */ long d = src->d; long r,s; #ifdef GMP for ( r=0;r<=m_A;r++) for( s=0;s<=d;s++) copy(dest->A[r][s],src->A[r][s]); #else /* fast copy for MP and LONG arithmetic */ /* Note that the "A" pointer trees need not be copied, since they always point to the same places within the corresponding space */ /* I wish I understood the above remark. For the time being, do it the easy way for Nash */ if(global->nash) { for ( r=0;r<=m_A;r++) for( s=0;s<=d;s++) copy(dest->A[r][s],src->A[r][s]); } else memcpy (dest->A[0][0], (global->Qtail->prev)->A[0][0], (d + 1) * (lrs_digits + 1) * (m_A + 1) * sizeof (long)); #endif dest->i = src->i; dest->j = src->j; dest->m = m; dest->d = d; dest->m_A = src->m_A; dest->depth = src->depth; dest->lexflag = src->lexflag; copy (dest->det, src->det); copy (dest->objnum, src->objnum); copy (dest->objden, src->objden); if (global->debug) fprintf (lrs_ofp, "\nSaving dict at depth %ld\n", src->depth); memcpy (dest->B, src->B, (m + 1) * sizeof (long)); memcpy (dest->C, src->C, (d + 1) * sizeof (long)); memcpy (dest->Row, src->Row, (m + 1) * sizeof (long)); memcpy (dest->Col, src->Col, (d + 1) * sizeof (long)); } /* * pushQ(lrs_dat *globals,m,d): * this routine ensures that Qtail points to a record that * may be copied into. * * It may create a new record, or it may just move the head pointer * forward so that know that the old record has been overwritten. */ #if 0 #define TRACE(s) fprintf(stderr,"\n%s %p %p\n",s,global->Qhead,global->Qtail); #else #define TRACE(s) #endif void pushQ (lrs_dat * global, long m, long d ,long m_A) { if ((global->Qtail->next) == global->Qhead) { /* the Queue is full */ if (dict_count < dict_limit) { /* but we are allowed to create more */ lrs_dic *p; p = new_lrs_dic (m, d, m_A); if (p) { /* we successfully created another record */ p->next = global->Qtail->next; (global->Qtail->next)->prev = p; (global->Qtail->next) = p; p->prev = global->Qtail; dict_count++; global->Qtail = p; TRACE ("Added new record to Q"); } else { /* virtual memory exhausted. bummer */ global->Qhead = global->Qhead->next; global->Qtail = global->Qtail->next; TRACE ("VM exhausted"); } } else { /* * user defined limit reached. start overwriting the * beginning of Q */ global->Qhead = global->Qhead->next; global->Qtail = global->Qtail->next; TRACE ("User limit"); } } else { global->Qtail = global->Qtail->next; TRACE ("Reusing"); } } lrs_dic * lrs_getdic(lrs_dat *Q) /* create another dictionary for Q without copying any values */ /* derived from lrs_alloc_dic, used by nash.c */ { lrs_dic *p; long m; m = Q->m; /* nonnegative flag set means that problem is d rows "bigger" */ /* since nonnegative constraints are not kept explicitly */ if(Q->nonnegative) m = m+Q->inputd; p = new_lrs_dic (m, Q->inputd, Q->m); if (!p) return NULL; p->next = p; p->prev = p; Q->Qhead = p; Q->Qtail = p; return p; } #define NULLRETURN(e) if (!(e)) return NULL; lrs_dic * new_lrs_dic (long m, long d, long m_A) { lrs_dic *p; NULLRETURN (p = (lrs_dic *) malloc (sizeof (lrs_dic))); NULLRETURN (p->B = calloc ((m + 1), sizeof (long))); NULLRETURN (p->Row = calloc ((m + 1), sizeof (long))); NULLRETURN (p->C = calloc ((d + 1), sizeof (long))); NULLRETURN (p->Col = calloc ((d + 1), sizeof (long))); #ifdef GMP lrs_alloc_mp(p->det); lrs_alloc_mp(p->objnum); lrs_alloc_mp(p->objden); #endif p->d_orig=d; p->A=lrs_alloc_mp_matrix(m_A,d); return p; } void lrs_free_dic (lrs_dic * P, lrs_dat *Q) { /* do the same steps as for allocation, but backwards */ /* gmp variables cannot be cleared using free: use lrs_clear_mp* */ lrs_dic *P1; /* repeat until cache is empty */ do { /* I moved these here because I'm not certain the cached dictionaries need to be the same size. Well, it doesn't cost anything to be safe. db */ long d = P->d_orig; long m_A = P->m_A; lrs_clear_mp_matrix (P->A,m_A,d); /* "it is a ghastly error to free something not assigned my malloc" KR167 */ /* so don't try: free (P->det); */ lrs_clear_mp (P->det); lrs_clear_mp (P->objnum); lrs_clear_mp (P->objden); free (P->Row); free (P->Col); free (P->C); free (P->B); /* go to next record in cache if any */ P1 =P->next; free (P); P=P1; } while (Q->Qhead != P ); } void lrs_free_dat ( lrs_dat *Q ) { long m=Q->m; /* most of these items were allocated in lrs_alloc_dic */ lrs_clear_mp_vector (Q->Gcd,m); lrs_clear_mp_vector (Q->Lcm,m); lrs_clear_mp (Q->sumdet); lrs_clear_mp (Q->Nvolume); lrs_clear_mp (Q->Dvolume); lrs_clear_mp (Q->saved_det); lrs_clear_mp (Q->boundd); lrs_clear_mp (Q->boundn); free (Q->inequality); free (Q->facet); free (Q->redundcol); free (Q->linearity); free (Q->minratio); free (Q->temparray); free (Q->name); free (Q->saved_C); lrs_global_count--; free(Q); } long check_cache (lrs_dic ** D_p, lrs_dat * global, long *i_p, long *j_p) { /* assign local variables to structures */ cache_tries++; if (global->Qtail == global->Qhead) { TRACE ("cache miss"); /* Q has only one element */ cache_misses++; return 0; } else { global->Qtail = global->Qtail->prev; *D_p = global->Qtail; *i_p = global->Qtail->i; *j_p = global->Qtail->j; TRACE ("restoring dict"); return 1; } } lrs_dic * lrs_alloc_dic (lrs_dat * Q) /* allocate and initialize lrs_dic */ { lrs_dic *p; long i, j; long m, d, m_A; if (Q->hull) /* d=col dimension of A */ Q->inputd = Q->n; /* extra column for hull */ else Q->inputd = Q->n - 1; m = Q->m; d = Q->inputd; m_A = m; /* number of rows in A */ /* nonnegative flag set means that problem is d rows "bigger" */ /* since nonnegative constraints are not kept explicitly */ if(Q->nonnegative) m = m+d; p = new_lrs_dic (m, d, m_A); if (!p) return NULL; p->next = p; p->prev = p; Q->Qhead = p; Q->Qtail = p; dict_count = 1; dict_limit = 10; cache_tries = 0; cache_misses = 0; /* Initializations */ p->d = p->d_orig = d; p->m = m; p->m_A = m_A; p->depth = 0L; p->lexflag = TRUE; itomp (ONE, p->det); itomp (ZERO, p->objnum); itomp (ONE, p->objden); /*m+d+1 is the number of variables, labelled 0,1,2,...,m+d */ /* initialize array to zero */ for (i = 0; i <= m_A; i++) for (j = 0; j <= d; j++) itomp (ZERO, p->A[i][j]); Q->inequality = CALLOC ((m + 1), sizeof (long)); if (Q->nlinearity == ZERO) /* linearity may already be allocated */ Q->linearity = CALLOC ((m + 1), sizeof (long)); Q->facet = (long *) CALLOC ((unsigned) d + 1, sizeof (long)); Q->redundcol = CALLOC ((d + 1), sizeof (long)); Q->minratio = CALLOC ((m + 1), sizeof (long)); Q->temparray = CALLOC ((unsigned) d + 1, sizeof (long)); Q->inequality[0] = 2L; Q->Gcd = lrs_alloc_mp_vector(m); Q->Lcm = lrs_alloc_mp_vector(m); Q->saved_C = CALLOC (d + 1, sizeof (long)); Q->lastdv = d; /* last decision variable may be decreased */ /* if there are redundant columns */ /*initialize basis and co-basis indices, and row col locations */ /*if nonnegative, we label differently to avoid initial pivots */ /* set basic indices and rows */ if(Q->nonnegative) for (i = 0; i <= m; i++) { p->B[i] = i; if (i <= d ) p->Row[i]=0; /* no row for decision variables */ else p->Row[i]=i-d; } else for (i = 0; i <= m; i++) { if (i == 0 ) p->B[0]=0; else p->B[i] = d + i; p->Row[i] = i; } for (j = 0; j < d; j++) { if(Q->nonnegative) p->C[j] = m+j+1; else p->C[j] = j + 1; p->Col[j] = j + 1; } p->C[d] = m + d + 1; p->Col[d] = 0; return p; } /* end of lrs_alloc_dic */ /* this routine makes a copy of the information needed to restart, so that we can guarantee that if a signal is received, we can guarantee that nobody is messing with it. This as opposed to adding all kinds of critical regions in the main line code. It is also used to make sure that in case of overflow, we have a valid cobasis to restart from. */ void save_basis (lrs_dic * P, lrs_dat * Q) { int i; /* assign local variables to structures */ long *C = P->C; long d; #ifdef SIGNALS sigset_t oset, blockset; sigemptyset (&blockset); sigaddset (&blockset, SIGTERM); sigaddset (&blockset, SIGHUP); sigaddset (&blockset, SIGUSR1); errcheck ("sigprocmask", sigprocmask (SIG_BLOCK, &blockset, &oset)); #endif d = P->d; Q->saved_flag = 1; for (i = 0; i < 3; i++) Q->saved_count[i] = Q->count[i]; for (i = 0; i < d + 1; i++) Q->saved_C[i] = C[i]; copy (Q->saved_det, P->det); Q->saved_d = P->d; Q->saved_depth = P->depth; #ifdef SIGNALS errcheck ("sigprocmask", sigprocmask (SIG_SETMASK, &oset, 0)); #endif } /* digits overflow is a call from lrs_mp package */ void digits_overflow () { fprintf (lrs_ofp, "\nOverflow at digits=%ld", DIG2DEC (lrs_digits)); fprintf (lrs_ofp, "\nRerun with option: digits n, where n > %ld\n", DIG2DEC (lrs_digits)); lrs_dump_state (); notimpl(""); } static void lrs_dump_state () { long i; fprintf (stderr, "\n\nlrs_lib: checkpointing:\n"); fprintf (stderr, "lrs_lib: Current digits at %ld out of %ld\n", DIG2DEC (lrs_record_digits), DIG2DEC (lrs_digits)); for (i = 0; i < lrs_global_count; i++) { print_basis (stderr, lrs_global_list[i]); } fprintf (stderr, "lrs_lib: checkpoint finished\n"); } /* print out the saved copy of the basis */ void print_basis (FILE * fp, lrs_dat * global) { int i; /* assign local variables to structures */ fprintf (fp, "lrs_lib: State #%ld: (%s)\t", global->id, global->name); if (global->saved_flag) { fprintf (fp, "V#%ld R#%ld B#%ld h=%ld facets ", global->saved_count[1], global->saved_count[0], global->saved_count[2], global->saved_depth); for (i = 0; i < global->saved_d; i++) fprintf (fp, "%ld ", global->inequality[global->saved_C[i] - global->lastdv]); pmp (" det=", global->saved_det); fprintf (fp, "\n"); } else { fprintf (fp, "lrs_lib: Computing initial basis\n"); } fflush (fp); } #ifdef SIGNALS /* If given a signal USR1 print current cobasis and continue TERM print current cobasis and terminate INT (ctrl-C) ditto HUP ditto */ void setup_signals () { errcheck ("signal", signal (SIGTERM, die_gracefully)); errcheck ("signal", signal (SIGALRM, timecheck)); errcheck ("signal", signal (SIGHUP, die_gracefully)); errcheck ("signal", signal (SIGINT, die_gracefully)); errcheck ("signal", signal (SIGUSR1, checkpoint)); } void timecheck () { lrs_dump_state (); errcheck ("signal", signal (SIGALRM, timecheck)); alarm (lrs_checkpoint_seconds); } void checkpoint () { lrs_dump_state (); errcheck ("signal", signal (SIGUSR1, checkpoint)); } void die_gracefully () { lrs_dump_state (); exit (1); } #endif #ifdef TIMES /* * Not sure about the portability of this yet, * - db */ #include #define double_time(t) ((double)(t.tv_sec)+(double)(t.tv_usec)/1000000) void ptimes () { struct rusage rusage; getrusage (RUSAGE_SELF, &rusage); fprintf (lrs_ofp, "\n*%0.3fu %0.3fs %ldKb %ld flts %ld swaps %ld blks-in %ld blks-out \n", double_time (rusage.ru_utime), double_time (rusage.ru_stime), rusage.ru_maxrss, rusage.ru_majflt, rusage.ru_nswap, rusage.ru_inblock, rusage.ru_oublock); } #endif /* Routines based on lp_solve */ void lrs_set_row(lrs_dic *P, lrs_dat *Q, long row, long num[], long den[], long ineq) /* convert to lrs_mp then call lrs_set_row */ { lrs_mp_vector Num, Den; long m,d; long j; m = P->m; d = P->d; Num=lrs_alloc_mp_vector(d+1); Den=lrs_alloc_mp_vector(d+1); for (j=0;j<=d;j++) { itomp(num[j],Num[j]); itomp(den[j],Den[j]); } lrs_set_row_mp(P,Q,row,Num,Den,ineq); lrs_clear_mp_vector(Num,d+1); lrs_clear_mp_vector(Den,d+1); } void lrs_set_row_mp(lrs_dic *P, lrs_dat *Q, long row, lrs_mp_vector num, lrs_mp_vector den, long ineq) /* set row of dictionary using num and den arrays for rational input */ /* ineq = 1 (GE) - ordinary row */ /* = 0 (EQ) - linearity */ { lrs_mp Temp, mpone; lrs_mp_vector oD; /* denominator for row */ long i, j; /* assign local variables to structures */ lrs_mp_matrix A; lrs_mp_vector Gcd, Lcm; long hull; long m, d; lrs_alloc_mp(Temp); lrs_alloc_mp(mpone); hull = Q->hull; A = P->A; m = P->m; d = P->d; Gcd = Q->Gcd; Lcm = Q->Lcm; oD = lrs_alloc_mp_vector (d); itomp (ONE, mpone); itomp (ONE, oD[0]); i=row; itomp (ONE, Lcm[i]); /* Lcm of denominators */ itomp (ZERO, Gcd[i]); /* Gcd of numerators */ for (j = hull; j <= d; j++) /* hull data copied to cols 1..d */ { copy( A[i][j],num[j-hull]); copy(oD[j],den[j-hull]); if (!one(oD[j])) lcm (Lcm[i], oD[j]); /* update lcm of denominators */ copy (Temp, A[i][j]); gcd (Gcd[i], Temp); /* update gcd of numerators */ } if (hull) { itomp (ZERO, A[i][0]); /*for hull, we have to append an extra column of zeroes */ if (!one (A[i][1]) || !one (oD[1])) /* all rows must have a one in column one */ Q->polytope = FALSE; } if (!zero (A[i][hull])) /* for H-rep, are zero in column 0 */ Q->homogeneous = FALSE; /* for V-rep, all zero in column 1 */ storesign (Gcd[i], POS); storesign (Lcm[i], POS); if (greater (Gcd[i], mpone) || greater (Lcm[i], mpone)) for (j = 0; j <= d; j++) { exactdivint (A[i][j], Gcd[i], Temp); /*reduce numerators by Gcd */ mulint (Lcm[i], Temp, Temp); /*remove denominators */ exactdivint (Temp, oD[j], A[i][j]); /*reduce by former denominator */ } if ( ineq == EQ ) /* input is linearity */ { Q->linearity[Q->nlinearity]=row; Q->nlinearity++; } lrs_clear_mp_vector (oD,d); lrs_clear_mp(Temp); lrs_clear_mp(mpone); } /* end of lrs_set_row_mp */ void lrs_set_obj(lrs_dic *P, lrs_dat *Q, long num[], long den[], long max) { long i; if (max == MAXIMIZE) Q->maximize=TRUE; else { Q->minimize=TRUE; for(i=0;i<=P->d;i++) num[i]=-num[i]; } lrs_set_row(P,Q,0L,num,den,GE); } void lrs_set_obj_mp(lrs_dic *P, lrs_dat *Q, lrs_mp_vector num, lrs_mp_vector den, long max) { long i; if (max == MAXIMIZE) Q->maximize=TRUE; else { Q->minimize=TRUE; for(i=0;i<=P->d;i++) changesign(num[i]); } lrs_set_row_mp(P,Q,0L,num,den,GE); } long lrs_solve_lp(lrs_dic *P, lrs_dat *Q) /* user callable function to solve lp only */ { lrs_mp_matrix Lin; /* holds input linearities if any are found */ long col; Q->lponly = TRUE; if (!lrs_getfirstbasis (&P, Q, &Lin, FALSE)) return FALSE; /* There may have been column redundancy */ /* If so the linearity space is obtained and redundant */ /* columns are removed. User can access linearity space */ /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ for (col = 0; col < Q->nredundcol; col++) /* print linearity space */ lrs_printoutput (Q, Lin[col]); /* Array Lin[][] holds the coeffs. */ return TRUE; } /* end of lrs_solve_lp */ long dan_selectpivot (lrs_dic * P, lrs_dat * Q, long *r, long *s) /* select pivot indices using dantzig simplex method */ /* largest coefficient with lexicographic rule to avoid cycling */ /* Bohdan Kaluzny's handiwork */ /* returns TRUE if pivot found else FALSE */ /* pivot variables are B[*r] C[*s] in locations Row[*r] Col[*s] */ { long j,k,col; lrs_mp coeff; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *Col = P->Col; long d = P->d; lrs_alloc_mp (coeff); *r = 0; *s = d; j = 0; k = 0; itomp(0,coeff); /*find positive cost coef */ while (k < d) { if(greater(A[0][Col[k]],coeff)) { j = k; copy(coeff,A[0][Col[j]]); } k++; } if (positive(coeff)) /* pivot column found! */ { *s = j; col = Col[j]; /*find min index ratio */ *r = ratio (P, Q, col); if (*r != 0) { lrs_clear_mp(coeff); return (TRUE); /* unbounded */ } } lrs_clear_mp(coeff); return (FALSE); } /* end of dan_selectpivot */ long phaseone (lrs_dic * P, lrs_dat * Q) /* Do a dual pivot to get primal feasibility (pivot in X_0)*/ /* Bohdan Kaluzny's handiwork */ { long i, j, k; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *Row = P->Row; long *Col = P->Col; long m, d; lrs_mp b_vector; lrs_alloc_mp (b_vector); m = P->m; d = P->d; i = 0; k = d+1; itomp(0,b_vector); fprintf (lrs_ofp, "\nLP: Phase One: Dual pivot on artificial variable"); /*find most negative b vector */ while (k <= m) { if(greater(b_vector,A[Row[k]][0])) { i = k; copy(b_vector,A[Row[i]][0]); } k++; } if (negative(b_vector)) /* pivot row found! */ { j = 0; /*find a positive entry for in row */ while (j < d && !positive (A[Row[i]][Col[j]])) j++; if (j >= d) { lrs_clear_mp (b_vector); return (FALSE); /* no positive entry */ } pivot (P, Q, i, j); update (P, Q, &i, &j); } lrs_clear_mp (b_vector); return (TRUE); } long lrs_set_digits(long dec_digits) { /* convert user specified decimal digits to mp digits */ fprintf (lrs_ofp, "\n*digits %ld", dec_digits); if (dec_digits > 0) lrs_digits = DEC2DIG (dec_digits); if (lrs_digits > MAX_DIGITS) { fprintf (lrs_ofp, "\nDigits must be at most %ld\nChange MAX_DIGITS and recompile", DIG2DEC (MAX_DIGITS)); fflush(stdout); return (FALSE); } return (TRUE); } long lrs_checkbound(lrs_dic *P, lrs_dat *Q) { /* check bound on objective and return TRUE if exceeded */ if(!Q->bound) return FALSE; if( Q->maximize && comprod(Q->boundn,P->objden,P->objnum,Q->boundd) == 1 ) { if(Q->verbose) { prat(" \nObj value: ",P->objnum,P->objden); fprintf(lrs_ofp," Pruning "); } return TRUE; } if( Q->minimize && comprod(Q->boundn,P->objden,P->objnum,Q->boundd) == -1 ) { if(Q->verbose) { prat(" \nObj value: ",P->objnum,P->objden); fprintf(lrs_ofp," Pruning "); } return TRUE; } return FALSE; } gambit-0.2010.09.01/src/tools/enummixed/lrslib.h0000644000076500007650000004540211350032206016017 00000000000000/* lrslib.h (vertex enumeration using lexicographic reverse search) */ #define TITLE "lrslib " #define LRS_VERSION "v.4.2b, 2006.3.31" #define AUTHOR "\n*Copyright (C) 1995,2006, David Avis avis@cs.mcgill.ca " /* 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /*Ver 4.0* library version */ /******************************************************************************/ /* See http://cgm.cs.mcgill.ca/~avis/C/lrs.html for usage instructions */ /******************************************************************************/ /* Selection of arithmetic package */ /*************************************/ #ifdef LONG #define ARITH "lrslong.h" /* lrs long integer arithmetic package */ #else #ifdef GMP #define ARITH "lrsgmp.h" /* lrs wrapper for gmp multiple precsion arithmetic */ #else #define ARITH "lrsmp.h" /* lrs multiple precsion arithmetic */ #define MP #endif #endif #include ARITH #ifdef SIGNALS #include #include #define errcheck(s,e) if ((long)(e)==-1L){ perror(s);exit(1);} #endif #ifdef TIMES void ptimes (); #endif #define CALLOC(n,s) xcalloc(n,s,__LINE__,__FILE__) /* make this include file includable in a C++ file Note that lrsgmp.h should not be inside an extern "C" {} block */ #ifdef __cplusplus extern "C" { #endif /*************/ /* typedefs */ /*************/ /******************************************************************************/ /* Indexing after initialization */ /* Basis Cobasis */ /* --------------------------------------- ----------------------------- */ /* | i |0|1| .... |lastdv|lastdv+1|...|m| | j | 0 | 1 | ... |d-1| d | */ /* |-----|+|+|++++++|++++++|--------|---|-| |----|---|---|-----|---|+++++| */ /* |B[i] |0|1| .... |lastdv|lastdv+1|...|m| |C[j]|m+1|m+2| ... |m+d|m+d+1| */ /* -----|+|+|++++++|++++++|????????|???|?| ----|???|???|-----|???|+++++| */ /* */ /* Row[i] is row location for B[i] Col[j] is column location for C[j] */ /* ----------------------------- ----------------------------- */ /* | i |0|1| ..........|m-1|m| | j | 0 | 1 | ... |d-1| d | */ /* |-------|+|-|-----------|---|-| |------|---|---|--- |---|++++| */ /* |Row[i] |0|1|...........|m-1|m| |Col[j]| 1 | 2 | ... | d | 0 | */ /* --------|+|*|***********|***|*| ------|***|***|*****|***|++++| */ /* */ /* + = remains invariant * = indices may be permuted ? = swapped by pivot */ /* */ /* m = number of input rows n= number of input columns */ /* input dimension inputd = n-1 (H-rep) or n (V-rep) */ /* lastdv = inputd-nredundcol (each redundant column removes a dec. var) */ /* working dimension d=lastdv-nlinearity (an input linearity removes a slack) */ /* obj function in row 0, index 0=B[0] col 0 has index m+d+1=C[d] */ /* H-rep: b-vector in col 0, A matrix in columns 1..n-1 */ /* V-rep: col 0 all zero, b-vector in col 1, A matrix in columns 1..n */ /******************************************************************************/ typedef struct lrs_dic_struct /* dynamic dictionary data */ { lrs_mp_matrix A; long m; /* A has m+1 rows, row 0 is cost row */ long m_A; /* =m or m-d if nonnegative flag set */ long d; /* A has d+1 columns, col 0 is b-vector */ long d_orig; /* value of d as A was allocated (E.G.) */ long lexflag; /* true if lexmin basis for this vertex */ long depth; /* depth of basis/vertex in reverse search tree */ long i, j; /* last pivot row and column pivot indices */ lrs_mp det; /* current determinant of basis */ lrs_mp objnum; /* objective numerator value */ lrs_mp objden; /* objective denominator value */ long *B, *Row; /* basis, row location indices */ long *C, *Col; /* cobasis, column location indices */ struct lrs_dic_struct *prev, *next; } lrs_dic; typedef struct lrs_dat /* global problem data */ { lrs_mp_vector Gcd; /* Gcd of each row of numerators */ lrs_mp_vector Lcm; /* Lcm for each row of input denominators */ lrs_mp sumdet; /* sum of determinants */ lrs_mp Nvolume; /* volume numerator */ lrs_mp Dvolume; /* volume denominator */ lrs_mp boundn; /* objective bound numerator */ lrs_mp boundd; /* objective bound denominator */ long unbounded; /* lp unbounded */ char fname[100]; /* input file name from line 1 of input */ long *inequality; /* indices of inequalities corr. to cobasic ind */ /* initially holds order used to find starting */ /* basis, default: m,m-1,...,2,1 */ long *facet; /* cobasic indices for restart in needed */ long *redundcol; /* holds columns which are redundant */ long *linearity; /* holds cobasic indices of input linearities */ long *minratio; /* used for lexicographic ratio test */ long *temparray; /* for sorting indices, dimensioned to d */ long *isave, *jsave; /* arrays for estimator, malloc'ed at start */ long inputd; /* input dimension: n-1 for H-rep, n for V-rep */ long m; /* number of rows in input file */ long n; /* number of columns in input file */ long lastdv; /* index of last dec. variable after preproc */ /* given by inputd-nredundcol */ long count[10]; /* count[0]=rays [1]=verts. [2]=base [3]=pivots */ /* count[4]=integer vertices */ long deepest; /* max depth ever reached in search */ long nredundcol; /* number of redundant columns */ long nlinearity; /* number of input linearities */ long totalnodes; /* count total number of tree nodes evaluated */ long runs; /* probes for estimate function */ long seed; /* seed for random number generator */ double cest[10]; /* ests: 0=rays,1=vert,2=bases,3=vol,4=int vert */ /**** flags ********** */ long allbases; /* TRUE if all bases should be printed */ long bound; /* TRUE if upper/lower bound on objective given */ long debug; long dualdeg; /* TRUE if start dictionary is dual degenerate */ long etrace; /* turn off debug at basis # strace */ long frequency; /* frequency to print cobasis indices */ long geometric; /* TRUE if incident vertex prints after each ray */ long getvolume; /* do volume calculation */ long givenstart; /* TRUE if a starting cobasis is given */ long homogeneous; /* TRUE if all entries in column one are zero */ long hull; /* do convex hull computation if TRUE */ long incidence; /* print all tight inequalities (vertices/rays) */ long lponly; /* true if only lp solution wanted */ long maxdepth; /* max depth to search to in treee */ long maximize; /* flag for LP maximization */ long maxoutput; /* if positive, maximum number of output lines */ long minimize; /* flag for LP minimization */ long mindepth; /* do not backtrack above mindepth */ long nash; /* TRUE for computing nash equilibria */ long nonnegative; /* TRUE if last d constraints are nonnegativity */ long polytope; /* TRUE for facet computation of a polytope */ long printcobasis; /* TRUE if all cobasis should be printed */ long printslack; /* TRUE if indices of slack inequal. printed */ long truncate; /* TRUE: truncate tree when moving from opt vert*/ long verbose; /* FALSE for minimalist output */ long restart; /* TRUE if restarting from some cobasis */ long strace; /* turn on debug at basis # strace */ long voronoi; /* compute voronoi vertices by transformation */ /* Variables for saving/restoring cobasis, db */ long id; /* numbered sequentially */ char *name; /* passed by user */ long saved_count[3]; /* How often to print out current cobasis */ long *saved_C; lrs_mp saved_det; long saved_depth; long saved_d; long saved_flag; /* There is something in the saved cobasis */ /* Variables for cacheing dictionaries, db */ lrs_dic *Qhead, *Qtail; } lrs_dat, lrs_dat_p; /*********************/ /*global variables */ /*********************/ #define MAX_LRS_GLOBALS 100L #define MAXIMIZE 1L /* maximize the lp */ #define MINIMIZE 0L /* maximize the lp */ #define GE 1L /* constraint is >= */ #define EQ 0L /* constraint is linearity */ extern FILE *lrs_cfp; /* output file for checkpoint information */ extern unsigned long dict_count, dict_limit, cache_tries, cache_misses; extern lrs_dic *PBnew; /* we will save Bob's dictionary in getabasis */ /*******************************/ /* functions for external use */ /*******************************/ long lrs_main (int argc, char *argv[]); /* lrs driver, argv[1]=input file, [argc-1]=output file */ long redund_main (int argc, char *argv[]); /* redund driver, argv[1]=input file, [2]=output file */ lrs_dat *lrs_alloc_dat (char *name); /* allocate for lrs_dat structure "name" */ lrs_dic *lrs_alloc_dic (lrs_dat * Q); /* allocate for lrs_dic structure corr. to Q */ void lrs_estimate (lrs_dic * P, lrs_dat * Q); /* get estimates only */ long lrs_read_dat (lrs_dat * Q, int argc, char *argv[]); /* read header and set up lrs_dat */ long lrs_read_dic (lrs_dic * P, lrs_dat * Q); /* read input and set up problem and lrs_dic */ long lrs_checkbound (lrs_dic *P, lrs_dat * Q); /* TRUE if current objective value exceeds specified bound */ long lrs_getfirstbasis (lrs_dic ** P_p, lrs_dat * Q, lrs_mp_matrix * Lin,long no_output); /* gets first basis, FALSE if none,P may get changed if lin. space Lin found */ /* no_output is TRUE supresses output headers */ /* P may get changed if lin. space Lin found */ void lrs_getinput(lrs_dic *P,lrs_dat *Q,long *num,long *den, long m, long d); /* reads input matrix b A in lrs/cdd format */ long lrs_getnextbasis (lrs_dic ** dict_p, lrs_dat * Q, long prune); /* gets next lrs tree basis, FALSE if none */ /* backtrack if prune is TRUE */ long lrs_getsolution (lrs_dic * P, lrs_dat * Q, lrs_mp_vector output, long col); long lrs_getray (lrs_dic * P, lrs_dat * Q, long col, long comment, lrs_mp_vector output); long lrs_getvertex (lrs_dic * P, lrs_dat * Q, lrs_mp_vector output); void lrs_close (char *name); /* close lrs lib program "name" */ long lrs_init (char *name); /* initialize lrslib and arithmetic package for prog "name" */ void lrs_lpoutput(lrs_dic * P,lrs_dat * Q, lrs_mp_vector output); /* print LP primal and dual solutions */ void lrs_printcobasis (lrs_dic * P, lrs_dat * Q, long col); /* print cobasis for column col(verted or ray) */ void lrs_printoutput (lrs_dat * Q, lrs_mp_vector output); /* print output array */ void lrs_printrow (char name[], lrs_dat * Q, lrs_mp_vector output, long rowd); /*print row of A matrix in output[0..rowd] */ void lrs_printsol (lrs_dic * P, lrs_dat * Q, long col, long comment); /* print out solution from col, comment= */ /* 0=normal,-1=geometric ray,1..inputd=linearity */ void lrs_printtotals (lrs_dic * P, lrs_dat * Q); /* print final totals for lrs */ long lrs_set_digits (long dec_digits ); /* set lrsmp digits to equiv. of decimal dec_digits */ long lrs_solvelp (lrs_dic * P, lrs_dat * Q, long maximize); /* solve primal feas LP:TRUE bounded else FALSE */ /*******************************/ /* functions for internal use */ /*******************************/ /* basic dictionary functions */ /*******************************/ long getabasis (lrs_dic * P, lrs_dat * Q, long order[]); /* Try to find a starting basis */ void getnextoutput (lrs_dic * P, lrs_dat * Q, long i, long col, lrs_mp out); /* get A[B[i][col] and copy to out */ long ismin (lrs_dic * P, lrs_dat * Q, long r, long s); /* test if A[r][s] is a min ratio for col s */ long lexmin (lrs_dic * P, lrs_dat * Q, long col); /* test A to see if current basis is lexmin */ void pivot (lrs_dic * P, lrs_dat * Q, long bas, long cob); /* Qpivot routine for array A */ long primalfeasible (lrs_dic * P, lrs_dat * Q); /* Do dual pivots to get primal feasibility */ long ratio (lrs_dic * P, lrs_dat * Q, long col); /* find lex min. ratio */ long removecobasicindex (lrs_dic * P, lrs_dat * Q, long k); /* remove C[k] from problem */ long restartpivots (lrs_dic * P, lrs_dat * Q); /* restart problem from given cobasis */ long reverse (lrs_dic * P, lrs_dat * Q, long *r, long s); /* TRUE if B[*r] C[s] is a reverse lex-pos pivot */ long selectpivot (lrs_dic * P, lrs_dat * Q, long *r, long *s); /* select pivot indices using lexicographic rule */ long dan_selectpivot (lrs_dic * P, lrs_dat * Q, long *r, long *s); /* select pivot indices using dantzig-lex rule */ void update (lrs_dic * P, lrs_dat * Q, long *i, long *j); /* update the B,C, LOC arrays after a pivot */ void updatevolume (lrs_dic * P, lrs_dat * Q); /* rescale determinant and update the volume */ /*******************************/ /* other functions using P,Q */ /*******************************/ long lrs_degenerate (lrs_dic * P, lrs_dat * Q); /* TRUE if the dictionary is primal degenerate */ void print_basis (FILE * fp, lrs_dat * Q); void printA (lrs_dic * P, lrs_dat * Q); /* raw print of dictionary, bases for debugging */ void pimat (lrs_dic * P, long r, long s, lrs_mp Nt, char name[]); /* print the row r col s of A */ long readfacets (lrs_dat * Q, long facet[]); /* read and check facet list */ long readlinearity (lrs_dat * Q); /* read and check linearity list */ void rescaledet (lrs_dic * P, lrs_dat * Q, lrs_mp Vnum, lrs_mp Vden); /* rescale determinant to get its volume */ void rescalevolume (lrs_dic * P, lrs_dat * Q, lrs_mp Vnum, lrs_mp Vden); /* adjust volume for dimension */ /***************************************************/ /* Routines for redundancy checking */ /***************************************************/ long checkredund (lrs_dic * P, lrs_dat * Q); /* solve primal lp to check redund of obj fun. */ /* returns TRUE if redundant, else FALSE */ long checkcobasic (lrs_dic * P, lrs_dat * Q, long index); /* TRUE if index is cobasic and nondegenerate */ /* FALSE if basic, or degen. cobasic, where it will get pivoted out */ long checkindex (lrs_dic * P, lrs_dat * Q, long index); /* index=0 non-red.,1 red., 2 input linearity */ /* NOTE: row is returned all zero if redundant!! */ /***************************************************/ /* Routines for caching and restoring dictionaries */ /***************************************************/ void lrs_free_dic ( lrs_dic *P, lrs_dat *Q); void lrs_free_dat ( lrs_dat *Q); void cache_dict (lrs_dic ** D_p, lrs_dat * global, long i, long j); long check_cache (lrs_dic ** D_p, lrs_dat * global, long *i_p, long *j_p); void copy_dict (lrs_dat * global, lrs_dic * dest, lrs_dic * src); void pushQ (lrs_dat * global, long m, long d, long m_A); void save_basis (lrs_dic * D, lrs_dat * Q); lrs_dic *alloc_memory (lrs_dat * Q); lrs_dic * lrs_getdic(lrs_dat *Q); lrs_dic *new_lrs_dic (long m, long d, long m_A); lrs_dic *resize (lrs_dic * P, lrs_dat * Q); /*******************************/ /* signals handling */ /*******************************/ void checkpoint (); void die_gracefully (); void setup_signals (); void timecheck (); /*******************************/ /* utilities */ /*******************************/ void lprat (const char *name, long Num, long Den); /* Print Num/Den without reducing */ long lreadrat (long *Num, long *Den); /* read a rational string and convert to long integers */ void reorder (long a[], long range); /* reorder array in increasing order with one misplaced element */ void reorder1 (long a[], long b[], long newone, long range); /* reorder array a in increasing order with misplaced element newone */ /* elements of b go along for the ride */ /***************************/ /* lp_solve like functions */ /***************************/ long lrs_solve_lp(lrs_dic *P, lrs_dat *Q); /* solve lp only for given dictionary */ void lrs_set_row(lrs_dic *P, lrs_dat *Q, long row, long num[], long den[], long ineq); /* load row i of dictionary from num[]/den[] ineq=GE */ void lrs_set_row_mp(lrs_dic *P, lrs_dat *Q, long row, lrs_mp_vector num, lrs_mp_vector den, long ineq); /* same as lrs_set_row except num/den is lrs_mp type */ void lrs_set_obj(lrs_dic *P, lrs_dat *Q, long num[], long den[], long max); /* set up objective function with coeffs num[]/den[] max=MAXIMIZE or MINIMIZE */ void lrs_set_obj_mp(lrs_dic *P, lrs_dat *Q, lrs_mp_vector num, lrs_mp_vector den, long max); /* same as lrs_set_obj but num/den has lrs_mp type */ /* end of lrslib.h (vertex enumeration using lexicographic reverse search) */ #ifdef __cplusplus } #endif gambit-0.2010.09.01/src/tools/enummixed/lrsmp.c0000644000076500007650000005203411350032206015657 00000000000000/* lrsmp.c library code for lrs extended precision arithmetic */ /* Version 4.0b, Feb. 8, 2000 */ /* Copyright: David Avis 1999, avis@cs.mcgill.ca */ /* 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /******************************************************************/ /* digit overflow is caught by digits_overflow at the end of this */ /* file, make sure it is either user supplied or uncomment */ /* the define below */ /******************************************************************/ #define digits_overflow() lrs_default_digits_overflow() #include #include #include "lrsmp.h" /*********************************************************/ /* Initialization and allocation procedures - must use! */ /******************************************************* */ long lrs_mp_init (long dec_digits, FILE * fpin, FILE * fpout) /* max number of decimal digits for the computation */ { /* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ lrs_ifp = fpin; lrs_ofp = fpout; lrs_record_digits = 0; if (dec_digits <= 0) dec_digits = DEFAULT_DIGITS; lrs_digits = DEC2DIG (dec_digits); /* max permitted no. of digits */ if (lrs_digits > MAX_DIGITS) { fprintf (lrs_ofp, "\nDigits must be at most %ld\nChange MAX_DIGITS and recompile\n", DIG2DEC (MAX_DIGITS)); lrs_digits = MAX_DIGITS; return FALSE; } return TRUE; } lrs_mp_t lrs_alloc_mp_t () /* dynamic allocation of lrs_mp number */ { lrs_mp_t p; p=(long *)calloc (lrs_digits+1, sizeof (long)); return p; } lrs_mp_vector lrs_alloc_mp_vector (long n) /* allocate lrs_mp_vector for n+1 lrs_mp numbers */ { lrs_mp_vector p; long i; p = CALLOC ((n + 1), sizeof (lrs_mp *)); for (i = 0; i <= n; i++) p[i] = CALLOC (1, sizeof (lrs_mp)); return p; } void lrs_clear_mp_vector (lrs_mp_vector p, long n) /* free space allocated to p */ { long i; for (i=0; i<=n; i++) free (p[i] ); free (p); } lrs_mp_matrix lrs_alloc_mp_matrix (long m, long n) /* allocate lrs_mp_matrix for m+1 x n+1 lrs_mp numbers */ { lrs_mp_matrix a; long *araw; int mp_width, row_width; int i, j; mp_width = lrs_digits + 1; row_width = (n + 1) * mp_width; araw = calloc ((m + 1) * row_width, sizeof (long)); a = calloc ((m + 1), sizeof (lrs_mp_vector)); for (i = 0; i < m + 1; i++) { a[i] = calloc ((n + 1), sizeof (lrs_mp *)); for (j = 0; j < n + 1; j++) a[i][j] = (araw + i * row_width + j * mp_width); } return a; } void lrs_clear_mp_matrix (lrs_mp_matrix p, long m, long n) /* free space allocated to lrs_mp_matrix p */ { long i; /* p[0][0] is araw, the actual matrix storage address */ free(p[0][0]); for (i = 0; i < m + 1; i++) free (p[i]); free(p); } /*********************************************************/ /* Core library functions - depend on mp implementation */ /******************************************************* */ void copy (lrs_mp a, lrs_mp b) /* assigns a=b */ { long i; for (i = 0; i <= length (b); i++) a[i] = b[i]; } /********************************************************/ /* Divide two multiple precision integers (c=a/b). */ /* a is destroyed and contains the remainder on return. */ /* From Knuth Vol.2 SemiNumerical Algorithms */ /* coded by J. Quinn */ /********************************************************/ void divint (lrs_mp a, lrs_mp b, lrs_mp c) /* c=a/b, a contains remainder on return */ { long cy, la, lb, lc, d1, s, t, sig; long i, j, qh; /* figure out and save sign, do everything with positive numbers */ sig = sign (a) * sign (b); la = length (a); lb = length (b); lc = la - lb + 2; if (la < lb) { storelength (c, TWO); storesign (c, POS); c[1] = 0; normalize (c); return; } for (i = 1; i < lc; i++) c[i] = 0; storelength (c, lc); storesign (c, (sign (a) == sign (b)) ? POS : NEG); /******************************/ /* division by a single word: */ /* do it directly */ /******************************/ if (lb == 2) { cy = 0; t = b[1]; for (i = la - 1; i > 0; i--) { cy = cy * BASE + a[i]; a[i] = 0; cy -= (c[i] = cy / t) * t; } a[1] = cy; storesign (a, (cy == 0) ? POS : sign (a)); storelength (a, TWO); /* set sign of c to sig (**mod**) */ storesign (c, sig); normalize (c); return; } else { /* mp's are actually DIGITS+1 in length, so if length of a or b = */ /* DIGITS, there will still be room after normalization. */ /****************************************************/ /* Step D1 - normalize numbers so b > floor(BASE/2) */ d1 = BASE / (b[lb - 1] + 1); if (d1 > 1) { cy = 0; for (i = 1; i < la; i++) { cy = (a[i] = a[i] * d1 + cy) / BASE; a[i] %= BASE; } a[i] = cy; cy = 0; for (i = 1; i < lb; i++) { cy = (b[i] = b[i] * d1 + cy) / BASE; b[i] %= BASE; } b[i] = cy; } else { a[la] = 0; /* if la or lb = DIGITS this won't work */ b[lb] = 0; } /*********************************************/ /* Steps D2 & D7 - start and end of the loop */ for (j = 0; j <= la - lb; j++) { /*************************************/ /* Step D3 - determine trial divisor */ if (a[la - j] == b[lb - 1]) qh = BASE - 1; else { s = (a[la - j] * BASE + a[la - j - 1]); qh = s / b[lb - 1]; while (qh * b[lb - 2] > (s - qh * b[lb - 1]) * BASE + a[la - j - 2]) qh--; } /*******************************************************/ /* Step D4 - divide through using qh as quotient digit */ cy = 0; for (i = 1; i <= lb; i++) { s = qh * b[i] + cy; a[la - j - lb + i] -= s % BASE; cy = s / BASE; if (a[la - j - lb + i] < 0) { a[la - j - lb + i] += BASE; cy++; } } /*****************************************************/ /* Step D6 - adjust previous step if qh is 1 too big */ if (cy) { qh--; cy = 0; for (i = 1; i <= lb; i++) /* add a back in */ { a[la - j - lb + i] += b[i] + cy; cy = a[la - j - lb + i] / BASE; a[la - j - lb + i] %= BASE; } } /***********************************************************************/ /* Step D5 - write final value of qh. Saves calculating array indices */ /* to do it here instead of before D6 */ c[la - lb - j + 1] = qh; } /**********************************************************************/ /* Step D8 - unnormalize a and b to get correct remainder and divisor */ for (i = lc; c[i - 1] == 0 && i > 2; i--); /* strip excess 0's from quotient */ storelength (c, i); if (i == 2 && c[1] == 0) storesign (c, POS); cy = 0; for (i = lb - 1; i >= 1; i--) { cy = (a[i] += cy * BASE) % d1; a[i] /= d1; } for (i = la; a[i - 1] == 0 && i > 2; i--); /* strip excess 0's from quotient */ storelength (a, i); if (i == 2 && a[1] == 0) storesign (a, POS); if (cy) fprintf (lrs_ofp, "divide error"); for (i = lb - 1; i >= 1; i--) { cy = (b[i] += cy * BASE) % d1; b[i] /= d1; } } } /* end of divint */ void gcd (lrs_mp u, lrs_mp v) /*returns u=gcd(u,v) destroying v */ /*Euclid's algorithm. Knuth, II, p.320 modified to avoid copies r=u,u=v,v=r Switches to single precision when possible for greater speed */ { lrs_mp r; unsigned long ul, vl; long i; static unsigned long maxspval = MAXD; /* Max value for the last digit to guarantee */ /* fitting into a single long integer. */ static long maxsplen; /* Maximum digits for a number that will fit */ /* into a single long integer. */ static long firstime = TRUE; if (firstime) /* initialize constants */ { for (maxsplen = 2; maxspval >= BASE; maxsplen++) maxspval /= BASE; firstime = FALSE; } if (greater (v, u)) goto bigv; bigu: if (zero (v)) return; if ((i = length (u)) < maxsplen || (i == maxsplen && u[maxsplen - 1] < maxspval)) goto quickfinish; divint (u, v, r); normalize (u); bigv: if (zero (u)) { copy (u, v); return; } if ((i = length (v)) < maxsplen || (i == maxsplen && v[maxsplen - 1] < maxspval)) goto quickfinish; divint (v, u, r); normalize (v); goto bigu; /* Base 10000 only at the moment */ /* when u and v are small enough, transfer to single precision integers */ /* and finish with euclid's algorithm, then transfer back to lrs_mp */ quickfinish: ul = vl = 0; for (i = length (u) - 1; i > 0; i--) ul = BASE * ul + u[i]; for (i = length (v) - 1; i > 0; i--) vl = BASE * vl + v[i]; if (ul > vl) goto qv; qu: if (!vl) { for (i = 1; ul; i++) { u[i] = ul % BASE; ul = ul / BASE; } storelength (u, i); return; } ul %= vl; qv: if (!ul) { for (i = 1; vl; i++) { u[i] = vl % BASE; vl = vl / BASE; } storelength (u, i); return; } vl %= ul; goto qu; } long compare (lrs_mp a, lrs_mp b) /* a ? b and returns -1,0,1 for <,=,> */ { long i; if (a[0] > b[0]) return 1L; if (a[0] < b[0]) return -1L; for (i = length (a) - 1; i >= 1; i--) { if (a[i] < b[i]) { if (sign (a) == POS) return -1L; else return 1L; } if (a[i] > b[i]) { if (sign (a) == NEG) return -1L; else return 1L; } } return 0L; } long greater (lrs_mp a, lrs_mp b) /* tests if a > b and returns (TRUE=POS) */ { long i; if (a[0] > b[0]) return (TRUE); if (a[0] < b[0]) return (FALSE); for (i = length (a) - 1; i >= 1; i--) { if (a[i] < b[i]) { if (sign (a) == POS) return (0); else return (1); } if (a[i] > b[i]) { if (sign (a) == NEG) return (0); else return (1); } } return (0); } void itomp (long in, lrs_mp a) /* convert integer i to multiple precision with base BASE */ { long i; a[0] = 2; /* initialize to zero */ for (i = 1; i < lrs_digits; i++) a[i] = 0; if (in < 0) { storesign (a, NEG); in = in * (-1); } i = 0; while (in != 0) { i++; a[i] = in - BASE * (in / BASE); in = in / BASE; storelength (a, i + 1); } } /* end of itomp */ void linint (lrs_mp a, long ka, lrs_mp b, long kb) /*compute a*ka+b*kb --> a */ /***Handbook of Algorithms and Data Structures P.239 ***/ { long i, la, lb; la = length (a); lb = length (b); for (i = 1; i < la; i++) a[i] *= ka; if (sign (a) != sign (b)) kb = (-kb); if (lb > la) { storelength (a, lb); for (i = la; i < lb; i++) a[i] = 0; } for (i = 1; i < lb; i++) a[i] += kb * b[i]; normalize (a); } /***end of linint***/ void mptodouble (lrs_mp a, double *x) /* convert lrs_mp to double */ { long i, la; double y = 1.0; (*x) = 0; la = length (a); for (i = 1; i < la; i++) { (*x) = (*x) + y * a[i]; y = y * BASE; } if (negative (a)) (*x)= -(*x); } void mulint (lrs_mp a, lrs_mp b, lrs_mp c) /* multiply two integers a*b --> c */ /***Handbook of Algorithms and Data Structures, p239 ***/ { long nlength, i, j, la, lb; /*** b and c may coincide ***/ la = length (a); lb = length (b); nlength = la + lb - 2; if (nlength > lrs_digits) digits_overflow (); for (i = 0; i < la - 2; i++) c[lb + i] = 0; for (i = lb - 1; i > 0; i--) { for (j = 2; j < la; j++) if ((c[i + j - 1] += b[i] * a[j]) > MAXD - (BASE - 1) * (BASE - 1) - MAXD / BASE) { c[i + j - 1] -= (MAXD / BASE) * BASE; c[i + j] += MAXD / BASE; } c[i] = b[i] * a[1]; } storelength (c, nlength); storesign (c, sign (a) == sign (b) ? POS : NEG); normalize (c); } /***end of mulint ***/ void normalize (lrs_mp a) { long cy, i, la; la = length (a); start: cy = 0; for (i = 1; i < la; i++) { cy = (a[i] += cy) / BASE; a[i] -= cy * BASE; if (a[i] < 0) { a[i] += BASE; cy--; } } while (cy > 0) { a[i++] = cy % BASE; cy /= BASE; } if (cy < 0) { a[la - 1] += cy * BASE; for (i = 1; i < la; i++) a[i] = (-a[i]); storesign (a, sign (a) == POS ? NEG : POS); goto start; } while (a[i - 1] == 0 && i > 2) i--; if (i > lrs_record_digits) { if ((lrs_record_digits = i) > lrs_digits) digits_overflow (); }; storelength (a, i); if (i == 2 && a[1] == 0) storesign (a, POS); } /* end of normalize */ long mptoi (lrs_mp a) /* convert lrs_mp to long integer */ { long len = length (a); if (len == 2) return sign (a) * a[1]; if (len == 3) return sign (a) * (a[1] + BASE * a[2]); notimpl ("mp to large for conversion to long"); return 0; /* never executed */ } void pmp (char name[], lrs_mp a) /*print the long precision integer a */ { long i; fprintf (lrs_ofp, "%s", name); if (sign (a) == NEG) fprintf (lrs_ofp, "-"); else fprintf (lrs_ofp, " "); fprintf (lrs_ofp, "%lu", a[length (a) - 1]); for (i = length (a) - 2; i >= 1; i--) fprintf (lrs_ofp, FORMAT, a[i]); fprintf (lrs_ofp, " "); } void prat (char name[], lrs_mp Nin, lrs_mp Din) /*reduce and print Nin/Din */ { lrs_mp Nt, Dt; long i; fprintf (lrs_ofp, "%s", name); /* reduce fraction */ copy (Nt, Nin); copy (Dt, Din); reduce (Nt, Dt); /* print out */ if (sign (Nin) * sign (Din) == NEG) fprintf (lrs_ofp, "-"); else fprintf (lrs_ofp, " "); fprintf (lrs_ofp, "%lu", Nt[length (Nt) - 1]); for (i = length (Nt) - 2; i >= 1; i--) fprintf (lrs_ofp, FORMAT, Nt[i]); if (!(Dt[0] == 2 && Dt[1] == 1)) /* rational */ { fprintf (lrs_ofp, "/"); fprintf (lrs_ofp, "%lu", Dt[length (Dt) - 1]); for (i = length (Dt) - 2; i >= 1; i--) fprintf (lrs_ofp, FORMAT, Dt[i]); } fprintf (lrs_ofp, " "); } void readmp (lrs_mp a) /* read an integer and convert to lrs_mp with base BASE */ { char in[MAXINPUT]; fscanf (lrs_ifp, "%s", in); atomp (in, a); } long readrat (lrs_mp Na, lrs_mp Da) /* read a rational or integer and convert to lrs_mp with base BASE */ /* returns true if denominator is not one */ { char in[MAXINPUT], num[MAXINPUT], den[MAXINPUT]; fscanf (lrs_ifp, "%s", in); atoaa (in, num, den); /*convert rational to num/dem strings */ atomp (num, Na); if (den[0] == '\0') { itomp (1L, Da); return (FALSE); } atomp (den, Da); return (TRUE); } void addint (lrs_mp a, lrs_mp b, lrs_mp c) /* compute c=a+b */ { copy (c, a); linint (c, 1, b, 1); } void atomp (char s[], lrs_mp a) /*convert string to lrs_mp integer */ { lrs_mp mpone; long diff, ten, i, sig; itomp (1L, mpone); ten = 10L; for (i = 0; s[i] == ' ' || s[i] == '\n' || s[i] == '\t'; i++); /*skip white space */ sig = POS; if (s[i] == '+' || s[i] == '-') /* sign */ sig = (s[i++] == '+') ? POS : NEG; itomp (0L, a); while (s[i] >= '0' && s[i] <= '9') { diff = s[i] - '0'; linint (a, ten, mpone, diff); i++; } storesign (a, sig); if (s[i]) { fprintf (stderr, "\nIllegal character in number: '%s'\n", s + i); exit (1); } } /* end of atomp */ void subint (lrs_mp a, lrs_mp b, lrs_mp c) /* compute c=a-b */ { copy (c, a); linint (a, 1, b, -1); } void decint (lrs_mp a, lrs_mp b) /* compute a=a-b */ { linint (a, 1, b, -1); } long myrandom (long num, long nrange) /* return a random number in range 0..nrange-1 */ { long i; i = (num * 401 + 673) % nrange; return (i); } long atos (char s[]) /* convert s to integer */ { long i, j; j = 0; for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i) j = 10 * j + s[i] - '0'; return (j); } void stringcpy (char *s, char *t) /*copy t to s pointer version */ { while (((*s++) = (*t++)) != '\0'); } void rattodouble (lrs_mp a, lrs_mp b, double *x) /* convert lrs_mp rational to double */ { double y; mptodouble (a, &y); mptodouble (b, x); *x = y / (*x); } void atoaa (char in[], char num[], char den[]) /* convert rational string in to num/den strings */ { long i, j; for (i = 0; in[i] != '\0' && in[i] != '/'; i++) num[i] = in[i]; num[i] = '\0'; den[0] = '\0'; if (in[i] == '/') { for (j = 0; in[j + i + 1] != '\0'; j++) den[j] = in[i + j + 1]; den[j] = '\0'; } } /* end of atoaa */ void lcm (lrs_mp a, lrs_mp b) /* a = least common multiple of a, b; b is preserved */ { lrs_mp u, v; copy (u, a); copy (v, b); gcd (u, v); exactdivint (a, u, v); /* v=a/u no remainder*/ mulint (v, b, a); } /* end of lcm */ void reducearray (lrs_mp_vector p, long n) /* find largest gcd of p[0]..p[n-1] and divide through */ { lrs_mp divisor; lrs_mp Temp; long i = 0L; while ((i < n) && zero (p[i])) i++; if (i == n) return; copy (divisor, p[i]); storesign (divisor, POS); i++; while (i < n) { if (!zero (p[i])) { copy (Temp, p[i]); storesign (Temp, POS); gcd (divisor, Temp); } i++; } /* reduce by divisor */ for (i = 0; i < n; i++) if (!zero (p[i])) reduceint (p[i], divisor); } /* end of reducearray */ void reduceint (lrs_mp Na, lrs_mp Da) /* divide Na by Da and return */ { lrs_mp Temp; copy (Temp, Na); exactdivint (Temp, Da, Na); } void reduce (lrs_mp Na, lrs_mp Da) /* reduces Na Da by gcd(Na,Da) */ { lrs_mp Nb, Db, Nc, Dc; copy (Nb, Na); copy (Db, Da); storesign (Nb, POS); storesign (Db, POS); copy (Nc, Na); copy (Dc, Da); gcd (Nb, Db); /* Nb is the gcd(Na,Da) */ exactdivint (Nc, Nb, Na); exactdivint (Dc, Nb, Da); } long comprod (lrs_mp Na, lrs_mp Nb, lrs_mp Nc, lrs_mp Nd) /* +1 if Na*Nb > Nc*Nd */ /* -1 if Na*Nb < Nc*Nd */ /* 0 if Na*Nb = Nc*Nd */ { lrs_mp mc, md; mulint (Na, Nb, mc); mulint (Nc, Nd, md); linint (mc, ONE, md, -ONE); if (positive (mc)) return (1); if (negative (mc)) return (-1); return (0); } void notimpl (char s[]) { fflush (stdout); fprintf (stderr, "\nAbnormal Termination %s\n", s); exit (1); } void getfactorial (lrs_mp factorial, long k) /* compute k factorial in lrs_mp */ { lrs_mp temp; long i; itomp (ONE, factorial); for (i = 2; i <= k; i++) { itomp (i, temp); mulint (temp, factorial, factorial); } } /* end of getfactorial */ /***************************************************************/ /* Package of routines for rational arithmetic */ /***************************************************************/ void scalerat (lrs_mp Na, lrs_mp Da, long ka) /* scales rational by ka */ { lrs_mp Nt; copy (Nt, Na); itomp (ZERO, Na); linint (Na, ZERO, Nt, ka); reduce (Na, Da); } void linrat (lrs_mp Na, lrs_mp Da, long ka, lrs_mp Nb, lrs_mp Db, long kb, lrs_mp Nc, lrs_mp Dc) /* computes Nc/Dc = ka*Na/Da +kb* Nb/Db and reduces answer by gcd(Nc,Dc) */ { lrs_mp c; mulint (Na, Db, Nc); mulint (Da, Nb, c); linint (Nc, ka, c, kb); /* Nc = (ka*Na*Db)+(kb*Da*Nb) */ mulint (Da, Db, Dc); /* Dc = Da*Db */ reduce (Nc, Dc); } void divrat (lrs_mp Na, lrs_mp Da, lrs_mp Nb, lrs_mp Db, lrs_mp Nc, lrs_mp Dc) /* computes Nc/Dc = (Na/Da) / ( Nb/Db ) and reduces answer by gcd(Nc,Dc) */ { mulint (Na, Db, Nc); mulint (Da, Nb, Dc); reduce (Nc, Dc); } void mulrat (lrs_mp Na, lrs_mp Da, lrs_mp Nb, lrs_mp Db, lrs_mp Nc, lrs_mp Dc) /* computes Nc/Dc = Na/Da * Nb/Db and reduces by gcd(Nc,Dc) */ { mulint (Na, Nb, Nc); mulint (Da, Db, Dc); reduce (Nc, Dc); } /* End package of routines for rational arithmetic */ /***************************************************************/ /* */ /* End of package for multiple precision arithmetic */ /* */ /***************************************************************/ void * xcalloc (long n, long s, long l, char *f) { void *tmp; tmp = calloc (n, s); if (tmp == 0) { char buf[200]; sprintf (buf, "\n\nFatal error on line %ld of %s", l, f); perror (buf); exit (1); } return tmp; } void lrs_getdigits (long *a, long *b) { /* send digit information to user */ *a = DIG2DEC (lrs_digits); *b = DIG2DEC (lrs_record_digits); return; } void lrs_default_digits_overflow () { fprintf (lrs_ofp, "\nOverflow at digits=%ld", DIG2DEC (lrs_digits)); fprintf (lrs_ofp, "\nInitialize lrs_mp_init with n > %ldL\n", DIG2DEC (lrs_digits)); exit (1); } /* end of lrsmp.c */ gambit-0.2010.09.01/src/tools/enummixed/lrsmp.h0000644000076500007650000002307211350032206015664 00000000000000/* lrsmp.h (lrs extended precision arithmetic library) */ /* Copyright: David Avis 2000, avis@cs.mcgill.ca */ /* Version 4.0, February 17, 2000 */ /* 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /******************************************************************************/ /* See http://cgm.cs.mcgill.ca/~avis/C/lrs.html for lrs usage instructions */ /******************************************************************************/ /* This package contains the extended precision routines used by lrs and some other miscellaneous routines. The maximum precision depends on the parameter MAX_DIGITS defined below, with usual default of 255L. This gives a maximum of 1020 decimal digits on 32 bit machines. The procedure lrs_mp_init(dec_digits) may set a smaller number of dec_digits, and this is useful if arrays or matrices will be used. */ /***********/ /* defines */ /***********/ /* this is number of longwords. Increasing this won't cost you that much since only variables other than the A matrix are allocated this size. Changing affects running time in small but not very predictable ways. */ #define MAX_DIGITS 255L /* this is in decimal digits, you pay in memory if you increase this, unless you override by a line with digits n before the begin line of your file. */ #define DEFAULT_DIGITS 100L /**********MACHINE DEPENDENT CONSTANTS***********/ /* MAXD is 2^(k-1)-1 where k=16,32,64 word size */ /* MAXD must be at least 2*BASE^2 */ /* If BASE is 10^k, use "%k.ku" for FORMAT */ /* INTSIZE is number of bytes for integer */ /* 32/64 bit machines */ /***********************************************/ #ifndef B64 /*32 bit machines */ #define FORMAT "%4.4lu" #define MAXD 2147483647L #define BASE 10000L #define BASE_DIG 4 #define INTSIZE 8L #define BIT "32bit" #else /* 64 bit machines */ #define MAXD 9223372036854775807L #define BASE 1000000000L #define FORMAT "%9.9lu" #define BASE_DIG 9 #define INTSIZE 16L #define BIT "64bit" #endif #define MAXINPUT 1000 /*max length of any input rational */ #define POS 1L #define NEG -1L #ifndef TRUE #define TRUE 1L #endif #ifndef FALSE #define FALSE 0L #endif #define ONE 1L #define TWO 2L #define ZERO 0L /**********************************/ /* MACROS */ /* dependent on mp implementation */ /**********************************/ #define exactdivint(a,b,c) divint((a),(b),(c)) /*should use special code here */ #define positive(a) (((a)[0] < 2 || ((a)[0]==2 && (a)[1]==0))?FALSE:TRUE) #define negative(a) (((a)[0] > -2 || ((a)[0]==-2 && (a)[1]==0))?FALSE:TRUE) #define zero(a) ((((a)[0]==2 || (a)[0]==-2) && (a)[1]==0)?TRUE:FALSE) #define one(a) (((a)[0]==2 && (a)[1]==1)?TRUE:FALSE) #define length(a) (((a)[0] > 0) ? (a)[0] : -(a)[0]) #define sign(a) (((a)[0] < 0) ? NEG : POS) #define storesign(a,sa) a[0]=((a)[0] > 0) ? (sa)*((a)[0]) : -(sa)*((a)[0]) #define changesign(a) a[0]= -(a)[0] #define storelength(a,la) a[0]=((a)[0] > 0) ? (la) : -(la) /* * convert between decimal and machine (longword digits). Notice lovely * implementation of ceiling function :-) */ #define DEC2DIG(d) ( (d) % BASE_DIG ? (d)/BASE_DIG+1 : (d)/BASE_DIG) #define DIG2DEC(d) ((d)*BASE_DIG) #include #ifdef SIGNALS #include #include #define errcheck(s,e) if ((long)(e)==-1L){ perror(s);exit(1);} #endif #ifdef TIMES void ptimes (); #endif #define CALLOC(n,s) xcalloc(n,s,__LINE__,__FILE__) /*************/ /* typedefs */ /*************/ typedef long lrs_mp[MAX_DIGITS + 1]; /* type lrs_mp holds one multi-precision integer */ typedef long *lrs_mp_t; typedef long **lrs_mp_vector; typedef long ***lrs_mp_matrix; /*********************/ /*global variables */ /*********************/ long lrs_digits; /* max permitted no. of digits */ long lrs_record_digits; /* this is the biggest acheived so far. */ FILE *lrs_ifp; /* input file pointer */ FILE *lrs_ofp; /* output file pointer */ /*********************************************************/ /* Initialization and allocation procedures - must use! */ /******************************************************* */ /* next two functions are not used by lrsmp, but are for lrsgmp compatability */ #define lrs_alloc_mp(a) #define lrs_clear_mp(a) lrs_mp_t lrs_alloc_mp_t(); /* dynamic allocation of lrs_mp */ lrs_mp_vector lrs_alloc_mp_vector (long n); /* allocate lrs_mp_vector for n+1 lrs_mp numbers */ lrs_mp_matrix lrs_alloc_mp_matrix (long m, long n); /* allocate lrs_mp_matrix for m+1 x n+1 lrs_mp */ void lrs_clear_mp_vector (lrs_mp_vector a, long n); void lrs_clear_mp_matrix (lrs_mp_matrix a, long m, long n); long lrs_mp_init (long dec_digits, FILE * lrs_ifp, FILE * lrs_ofp); /* max number of decimal digits, fps */ /*********************************************************/ /* Core library functions - depend on mp implementation */ /******************************************************* */ void atomp (char s[], lrs_mp a); /* convert string to lrs_mp integer */ long compare (lrs_mp a, lrs_mp b); /* a ? b and returns -1,0,1 for <,=,> */ void copy (lrs_mp a, lrs_mp b); /* assigns a=b */ void divint (lrs_mp a, lrs_mp b, lrs_mp c); /* c=a/b, a contains remainder on return */ void gcd (lrs_mp u, lrs_mp v); /* returns u=gcd(u,v) destroying v */ long greater (lrs_mp a, lrs_mp b); /* tests if a > b and returns (TRUE=POS) */ void itomp (long in, lrs_mp a); /* convert integer i to lrs_mp */ void linint (lrs_mp a, long ka, lrs_mp b, long kb); /* compute a*ka+b*kb --> a */ void mptodouble (lrs_mp a, double *x); /* convert lrs_mp to double */ long mptoi (lrs_mp a); /* convert lrs_mp to long integer */ void mulint (lrs_mp a, lrs_mp b, lrs_mp c); /* multiply two integers a*b --> c */ void normalize (lrs_mp a); /* normalize lrs_mp after computation */ void pmp (char name[], lrs_mp a); /* print the long precision integer a */ void prat (char name[], lrs_mp Nt, lrs_mp Dt); /* reduce and print Nt/Dt */ void readmp (lrs_mp a); /* read an integer and convert to lrs_mp */ long readrat (lrs_mp Na, lrs_mp Da); /* read a rational or int and convert to lrs_mp */ void reduce (lrs_mp Na, lrs_mp Da); /* reduces Na Da by gcd(Na,Da) */ /*********************************************************/ /* Standard arithmetic & misc. functions */ /* should be independent of mp implementation */ /******************************************************* */ void atoaa (char in[], char num[], char den[]); /* convert rational string in to num/den strings */ void addint (lrs_mp a, lrs_mp b, lrs_mp c); /* compute c=a+b */ long atos (char s[]); /* convert s to integer */ long comprod (lrs_mp Na, lrs_mp Nb, lrs_mp Nc, lrs_mp Nd); /* +1 if Na*Nb > Nc*Nd,-1 if Na*Nb > Nc*Nd else 0 */ void decint (lrs_mp a, lrs_mp b); /* compute a=a-b */ void divrat (lrs_mp Na, lrs_mp Da, lrs_mp Nb, lrs_mp Db, lrs_mp Nc, lrs_mp Dc); /* computes Nc/Dc = (Na/Da) /( Nb/Db ) and reduce */ void getfactorial (lrs_mp factorial, long k); /* compute k factorial in lrs_mp */ void linrat (lrs_mp Na, lrs_mp Da, long ka, lrs_mp Nb, lrs_mp Db, long kb, lrs_mp Nc, lrs_mp Dc); void lcm (lrs_mp a, lrs_mp b); /* a = least common multiple of a, b; b is saved */ void mulrat (lrs_mp Na, lrs_mp Da, lrs_mp Nb, lrs_mp Db, lrs_mp Nc, lrs_mp Dc); /* computes Nc/Dc=(Na/Da)*(Nb/Db) and reduce */ long myrandom (long num, long nrange); /* return a random number in range 0..nrange-1 */ void notimpl (char s[]); /* bail out - help! */ void rattodouble (lrs_mp a, lrs_mp b, double *x); /* convert lrs_mp rational to double */ void reduceint (lrs_mp Na, lrs_mp Da); /* divide Na by Da and return it */ void reducearray (lrs_mp_vector p, long n); /* find gcd of p[0]..p[n-1] and divide through by */ void scalerat (lrs_mp Na, lrs_mp Da, long ka); /* scales rational by ka */ void subint (lrs_mp a, lrs_mp b, lrs_mp c); /* compute c=a-b */ /**********************************/ /* Miscellaneous functions */ /******************************** */ void free (void *); void lrs_getdigits (long *a, long *b); /* send digit information to user */ void stringcpy (char *s, char *t); /* copy t to s pointer version */ //void *calloc (); //void *malloc (); void *xcalloc (long n, long s, long l, char *f); void lrs_default_digits_overflow (); void digits_overflow (); /* end of lrsmp.h (vertex enumeration using lexicographic reverse search) */ gambit-0.2010.09.01/src/tools/enummixed/lrsnash.cc0000644000076500007650000007615111351773322016361 00000000000000// // $Source$ // $Date$ // $Revision$ // // DESCRIPTION: // Compute Nash equilibria via enumerating extreme points, lrslib version // // This file is part of Gambit // Copyright (c) 2006, The Gambit Project // Based on the implementation in lrslib 4.2b, which is // Copyright (c) 1995-2005, David Avis // // 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. // // // This file is based heavily on nash.c distributed with lrslib 4.2b. // I have tried where possible to maintain as much of the original, and // make a minimal set of changes to interface with Gambit's game // representation library. This way, hopefully, if future versions of lrslib // fix bugs or create enhancements that are relevant, it will be fairly // easy to port them to this program. -- TLT, 23.viii.2006 // #include #include #include // The order of these next includes is important, because of macro definitions #include "libgambit/libgambit.h" using namespace Gambit; extern "C" { #include "lrslib.h" } //========================================================================== // Building the problem representations //========================================================================== // // These two functions are based upon the program setupnash.c from the // lrslib distribution, and the user's guide documentation. // There are two separate functions, one for each player's problem. // According to the user's guide, the ordering of the constraint rows // is significant, and differs between the players; for player 1's problem // the nonnegativity constraints come first, whereas for player 2's problem // they appear later. Experiments suggest this is in fact true, and // reversing them breaks something. // void FillNonnegativityRows(lrs_dic *P, lrs_dat *Q, int firstRow, int lastRow, int n) { const int MAXCOL = 1000; /* maximum number of columns */ long num[MAXCOL], den[MAXCOL]; for (long row = firstRow; row <= lastRow; row++) { num[0] = 0; den[0] = 1; for (long col = 1; col < n; col++) { num[col] = (row-firstRow+1 == col) ? 1 : 0; den[col] = 1; } lrs_set_row(P, Q, row, num, den, GE); } } void FillConstraintRows(lrs_dic *P, lrs_dat *Q, const StrategySupport &p_support, int p1, int p2, int firstRow) { const int MAXCOL = 1000; /* maximum number of columns */ long num[MAXCOL], den[MAXCOL]; Game game = p_support.GetGame(); Rational min = game->GetMinPayoff() - Rational(1); PureStrategyProfile cont(game); for (long row = firstRow; row < firstRow + p_support.NumStrategies(p1); row++) { num[0] = 0; den[0] = 1; cont.SetStrategy(p_support.GetStrategy(p1, row - firstRow + 1)); for (long st = 1; st <= p_support.NumStrategies(p2); st++) { cont.SetStrategy(p_support.GetStrategy(p2, st)); Rational x = cont.GetPayoff(p1) - min; num[st] = -x.numerator().as_long(); den[st] = x.denominator().as_long(); } num[p_support.NumStrategies(p2)+1] = 1; den[p_support.NumStrategies(p2)+1] = 1; lrs_set_row(P, Q, row, num, den, GE); } } void FillLinearityRow(lrs_dic *P, lrs_dat *Q, int m, int n) { const int MAXCOL = 1000; /* maximum number of columns */ long num[MAXCOL], den[MAXCOL]; num[0] = -1; den[0] = 1; for (int i = 1; i < n-1; i++) { num[i] = 1; den[i] = 1; } num[n-1] = 0; den[n-1] = 1; lrs_set_row(P, Q, m, num, den, EQ); } // // Build the H-representation for player p1 // void BuildRep(lrs_dic *P, lrs_dat *Q, const StrategySupport &p_support, int p1, int p2) { long m=Q->m; /* number of inequalities */ long n=Q->n; if (p1 == 1) { FillConstraintRows(P, Q, p_support, p1, p2, 1); FillNonnegativityRows(P, Q, p_support.NumStrategies(p1) + 1, p_support.MixedProfileLength(), n); } else { FillNonnegativityRows(P, Q, 1, p_support.NumStrategies(p2), n); FillConstraintRows(P, Q, p_support, p1, p2, p_support.NumStrategies(p2) + 1); } FillLinearityRow(P, Q, m, n); } //======================================================================== // Forward declarations of useful functions //======================================================================== /* lrs driver, argv[2]= 2nd input file for nash equilibria */ long nash2_main (lrs_dic *P1, lrs_dat *Q1, lrs_dic *P2orig, lrs_dat *Q2, long *numequilib, lrs_mp_vector output1, lrs_mp_vector output2, const StrategySupport &p_support); long lrs_getfirstbasis2 (lrs_dic ** D_p, lrs_dat * Q, lrs_dic *P2orig, lrs_mp_matrix * Lin, long no_output); long getabasis2 (lrs_dic * P, lrs_dat * Q, lrs_dic * P2orig, long order[]); // This is a modified version of lrs_output from the original, in which // we output the equilibria found in Gambit format. void nashoutput(lrs_dat *Q1, lrs_mp_vector output1, lrs_dat *Q2, lrs_mp_vector output2, const StrategySupport &p_support); // // This is the main function, based on main() from lrslib's 'nash' driver. // void LrsSolve(const StrategySupport &p_support) { lrs_dic *P1,*P2; /* structure for holding current dictionary and indices */ lrs_dat *Q1,*Q2; /* structure for holding static problem data */ lrs_mp_vector output1; /* holds one line of output; ray,vertex,facet,linearity */ lrs_mp_vector output2; /* holds one line of output; ray,vertex,facet,linearity */ lrs_mp_matrix Lin; /* holds input linearities if any are found */ lrs_dic *P2orig; /* we will save player 2's dictionary in getabasis */ long col; /* output column index for dictionary */ long startcol = 0; long prune = FALSE; /* if TRUE, getnextbasis will prune tree and backtrack */ long numequilib=0; /* number of nash equilibria found */ long oldnum=0; /* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ /* they default to stdin and stdout, but may be overidden by command line parms. */ /*************************************************** Step 0: Do some global initialization that should only be done once, no matter how many lrs_dat records are allocated. db ***************************************************/ if (!lrs_init("")) { return; } /*********************************************************************************/ /* Step 1: Allocate lrs_dat, lrs_dic and set up the problem */ /*********************************************************************************/ Q1 = lrs_alloc_dat ("LRS globals"); /* allocate and init structure for static problem data */ if (Q1 == NULL) { return; } Q1->nash=TRUE; Q1->n = p_support.NumStrategies(1) + 2; Q1->m = p_support.MixedProfileLength() + 1; P1 = lrs_alloc_dic (Q1); /* allocate and initialize lrs_dic */ if (P1 == NULL) { return; } BuildRep(P1, Q1, p_support, 2, 1); output1 = lrs_alloc_mp_vector (Q1->n + Q1->m); /* output holds one line of output from dictionary */ /* allocate and init structure for player 2's problem data */ Q2 = lrs_alloc_dat ("LRS globals"); if (Q2 == NULL) { return; } Q2->nash=TRUE; Q2->n = p_support.NumStrategies(2) + 2; Q2->m = p_support.MixedProfileLength() + 1; P2 = lrs_alloc_dic (Q2); /* allocate and initialize lrs_dic */ if (P2 == NULL) { return; } BuildRep(P2, Q2, p_support, 1, 2); output2 = lrs_alloc_mp_vector (Q2->n + Q2->m); /* output holds one line of output from dictionary */ P2orig = lrs_getdic(Q2); /* allocate and initialize lrs_dic */ if (P2orig == NULL) return; copy_dict(Q2,P2orig,P2); /*********************************************************************************/ /* Step 2: Find a starting cobasis from default of specified order */ /* P1 is created to hold active dictionary data and may be cached */ /* Lin is created if necessary to hold linearity space */ /* Print linearity space if any, and retrieve output from first dict. */ /*********************************************************************************/ if (!lrs_getfirstbasis (&P1, Q1, &Lin, TRUE)) return; if (Q1->dualdeg) { printf("\n*Warning! Dual degenerate, ouput may be incomplete"); printf("\n*Recommendation: Add dualperturb option before maximize in first input file\n"); } if (Q1->unbounded) { printf("\n*Warning! Unbounded starting dictionary for p1, output may be incomplete"); printf("\n*Recommendation: Change/remove maximize option, or include bounds \n"); } /* Pivot to a starting dictionary */ /* There may have been column redundancy */ /* If so the linearity space is obtained and redundant */ /* columns are removed. User can access linearity space */ /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ if (Q1->homogeneous && Q1->hull) startcol++; /* col zero not treated as redundant */ for (col = startcol; col < Q1->nredundcol; col++) /* print linearity space */ lrs_printoutput (Q1, Lin[col]); /* Array Lin[][] holds the coeffs. */ /*********************************************************************************/ /* Step 3: Terminate if lponly option set, otherwise initiate a reverse */ /* search from the starting dictionary. Get output for each new dict. */ /*********************************************************************************/ /* We initiate reverse search from this dictionary */ /* getting new dictionaries until the search is complete */ /* User can access each output line from output which is */ /* vertex/ray/facet from the lrs_mp_vector output */ /* prune is TRUE if tree should be pruned at current node */ do { prune=lrs_checkbound(P1,Q1); if (!prune && lrs_getsolution (P1, Q1, output1, col)) { oldnum=numequilib; nash2_main(P1,Q1,P2orig,Q2,&numequilib,output1,output2,p_support); if (numequilib > oldnum || Q1->verbose) { if(Q1->verbose) prat(" \np2's obj value: ",P1->objnum,P1->objden); //fprintf (lrs_ofp, "\n"); } } } while (lrs_getnextbasis (&P1, Q1, prune)); lrs_clear_mp_vector(output1, Q1->m + Q1->n); lrs_clear_mp_vector(output2, Q2->m + Q2->n); Q2->Qhead = P2; /* reset this or you crash free_dic */ lrs_free_dic (P2,Q2); /* deallocate lrs_dic */ lrs_free_dat (Q2); /* deallocate lrs_dat */ lrs_free_dic (P1,Q1); /* deallocate lrs_dic */ lrs_free_dat (Q1); /* deallocate lrs_dat */ lrs_close (""); fclose(lrs_ofp); } /*********************************************/ /* end of nash driver */ /*********************************************/ /**********************************************************/ /* nash2_main is a second driver used in computing nash */ /* equilibria on a second polytope interleaved with first */ /**********************************************************/ long nash2_main (lrs_dic *P1, lrs_dat *Q1, lrs_dic *P2orig, lrs_dat *Q2, long *numequilib, lrs_mp_vector output1, lrs_mp_vector output2, const StrategySupport &p_support) { lrs_dic *P2; /* This can get resized, cached etc. Loaded from P2orig */ lrs_mp_matrix Lin; /* holds input linearities if any are found */ long col; /* output column index for dictionary */ long startcol = 0; long prune = FALSE; /* if TRUE, getnextbasis will prune tree and backtrack */ long nlinearity; long *linearity; static long firstwarning=TRUE; /* FALSE if dual deg warning for Q2 already given */ static long firstunbounded=TRUE; /* FALSE if dual deg warning for Q2 already given */ long i,j; /* global variables lrs_ifp and lrs_ofp are file pointers for input and output */ /* they default to stdin and stdout, but may be overidden by command line parms. */ /*********************************************************************************/ /* Step 1: Allocate lrs_dat, lrs_dic and set up the problem */ /*********************************************************************************/ P2=lrs_getdic(Q2); copy_dict(Q2,P2,P2orig); /* Here we take the linearities generated by the current vertex of player 1*/ /* and append them to the linearity in player 2's input matrix */ /* next is the key magic linking player 1 and 2 */ /* be careful if you mess with this! */ linearity=Q2->linearity; nlinearity=0; for(i=Q1->lastdv+1;i <= P1->m; i++) { if (!zero(P1->A[P1->Row[i]][0])) { j = Q1->inequality[P1->B[i]-Q1->lastdv]; if (j < Q1->linearity[0]) linearity[nlinearity++]= j; } } /* add back in the linearity for probs summing to one */ linearity[nlinearity++]= Q1->linearity[0]; /*sort linearities */ for (i = 1; i < nlinearity; i++) reorder (linearity, nlinearity); if(Q2->verbose) { fprintf(lrs_ofp,"\np2: linearities %ld",nlinearity); for (i=0;i < nlinearity; i++) fprintf(lrs_ofp," %ld",linearity[i]); } Q2->nlinearity = nlinearity; Q2->polytope = FALSE; /*********************************************************************************/ /* Step 2: Find a starting cobasis from default of specified order */ /* P2 is created to hold active dictionary data and may be cached */ /* Lin is created if necessary to hold linearity space */ /* Print linearity space if any, and retrieve output from first dict. */ /*********************************************************************************/ if (!lrs_getfirstbasis2 (&P2, Q2, P2orig, &Lin, TRUE)) goto sayonara; if (firstwarning && Q2->dualdeg) { firstwarning=FALSE; printf("\n*Warning! Dual degenerate, ouput may be incomplete"); printf("\n*Recommendation: Add dualperturb option before maximize in second input file\n"); } if (firstunbounded && Q2->unbounded) { firstunbounded=FALSE; printf("\n*Warning! Unbounded starting dictionary for p2, output may be incomplete"); printf("\n*Recommendation: Change/remove maximize option, or include bounds \n"); } /* Pivot to a starting dictionary */ /* There may have been column redundancy */ /* If so the linearity space is obtained and redundant */ /* columns are removed. User can access linearity space */ /* from lrs_mp_matrix Lin dimensions nredundcol x d+1 */ if (Q2->homogeneous && Q2->hull) startcol++; /* col zero not treated as redundant */ /* for (col = startcol; col < Q2->nredundcol; col++)*/ /* print linearity space */ /*lrs_printoutput (Q2, Lin[col]);*/ /* Array Lin[][] holds the coeffs. */ /*********************************************************************************/ /* Step 3: Terminate if lponly option set, otherwise initiate a reverse */ /* search from the starting dictionary. Get output for each new dict. */ /*********************************************************************************/ /* We initiate reverse search from this dictionary */ /* getting new dictionaries until the search is complete */ /* User can access each output line from output which is */ /* vertex/ray/facet from the lrs_mp_vector output */ /* prune is TRUE if tree should be pruned at current node */ do { prune=lrs_checkbound(P2,Q2); col=0; if (!prune && lrs_getsolution (P2, Q2, output2, col)) { (*numequilib)++; if (Q2->verbose) prat(" \np1's obj value: ",P2->objnum,P2->objden); nashoutput(Q1, output1, Q2, output2, p_support); } } while (lrs_getnextbasis (&P2, Q2, prune)); sayonara: lrs_free_dic(P2,Q2); return 0; } /*********************************************/ /* end of nash2_main */ /*********************************************/ /* In lrs_getfirstbasis and lrs_getnextbasis we use D instead of P */ /* since the dictionary P may change, ie. &P in calling routine */ #define D (*D_p) long lrs_getfirstbasis2 (lrs_dic ** D_p, lrs_dat * Q, lrs_dic * P2orig, lrs_mp_matrix * Lin, long no_output) /* gets first basis, FALSE if none */ /* P may get changed if lin. space Lin found */ /* no_output is TRUE supresses output headers */ { long i, j, k; /* assign local variables to structures */ lrs_mp_matrix A; long *B, *C, *Row, *Col; long *inequality; long *linearity; long hull = Q->hull; long m, d, lastdv, nlinearity, nredundcol; static long ocount=0; m = D->m; d = D->d; lastdv = Q->lastdv; nredundcol = 0L; /* will be set after getabasis */ nlinearity = Q->nlinearity; /* may be reset if new linearity read */ linearity = Q->linearity; A = D->A; B = D->B; C = D->C; Row = D->Row; Col = D->Col; inequality = Q->inequality; /* default is to look for starting cobasis using linearies first, then */ /* filling in from last rows of input as necessary */ /* linearity array is assumed sorted here */ /* note if restart/given start inequality indices already in place */ /* from nlinearity..d-1 */ for (i = 0; i < nlinearity; i++) /* put linearities first in the order */ inequality[i] = linearity[i]; k = 0; /* index for linearity array */ if (Q->givenstart) k = d; else k = nlinearity; for (i = m; i >= 1; i--) { j = 0; while (j < k && inequality[j] != i) j++; /* see if i is in inequality */ if (j == k) inequality[k++] = i; } if (Q->debug) { fprintf (lrs_ofp, "\n*Starting cobasis uses input row order"); for (i = 0; i < m; i++) fprintf (lrs_ofp, " %ld", inequality[i]); } if (!Q->maximize && !Q->minimize) for (j = 0; j <= d; j++) itomp (ZERO, A[0][j]); /* Now we pivot to standard form, and then find a primal feasible basis */ /* Note these steps MUST be done, even if restarting, in order to get */ /* the same index/inequality correspondance we had for the original prob. */ /* The inequality array is used to give the insertion order */ /* and is defaulted to the last d rows when givenstart=FALSE */ if (!getabasis2 (D, Q,P2orig, inequality)) return FALSE; if(Q->debug) { fprintf(lrs_ofp,"\nafter getabasis2"); printA(D, Q); } nredundcol = Q->nredundcol; lastdv = Q->lastdv; d = D->d; /********************************************************************/ /* now we start printing the output file unless no output requested */ /********************************************************************/ if (!no_output || Q->debug) { fprintf (lrs_ofp, "\nV-representation"); /* Print linearity space */ /* Don't print linearity if first column zero in hull computation */ k = 0; if (nredundcol > k) { fprintf (lrs_ofp, "\nlinearity %ld ", nredundcol - k); /*adjust nredundcol for homog. */ for (i = 1; i <= nredundcol - k; i++) fprintf (lrs_ofp, " %ld", i); } /* end print of linearity space */ fprintf (lrs_ofp, "\nbegin"); fprintf (lrs_ofp, "\n***** %ld rational", Q->n); } /* end of if !no_output ....... */ /* Reset up the inequality array to remember which index is which input inequality */ /* inequality[B[i]-lastdv] is row number of the inequality with index B[i] */ /* inequality[C[i]-lastdv] is row number of the inequality with index C[i] */ for (i = 1; i <= m; i++) inequality[i] = i; if (nlinearity > 0) /* some cobasic indices will be removed */ { for (i = 0; i < nlinearity; i++) /* remove input linearity indices */ inequality[linearity[i]] = 0; k = 1; /* counter for linearities */ for (i = 1; i <= m - nlinearity; i++) { while (k <= m && inequality[k] == 0) k++; /* skip zeroes in corr. to linearity */ inequality[i] = inequality[k++]; } } /* end if linearity */ if (Q->debug) { fprintf (lrs_ofp, "\ninequality array initialization:"); for (i = 1; i <= m - nlinearity; i++) fprintf (lrs_ofp, " %ld", inequality[i]); } if (nredundcol > 0) { *Lin = lrs_alloc_mp_matrix (nredundcol, Q->n); for (i = 0; i < nredundcol; i++) { if (!(Q->homogeneous && Q->hull && i == 0)) /* skip redund col 1 for homog. hull */ { lrs_getray (D, Q, Col[0], D->C[0] + i - hull, (*Lin)[i]); /* adjust index for deletions */ } if (!removecobasicindex (D, Q, 0L)) return FALSE; } } /* end if nredundcol > 0 */ if (Q->verbose) { fprintf (lrs_ofp, "\nNumber of pivots for starting dictionary: %ld",Q->count[3]); ocount=Q->count[3]; } /* Do dual pivots to get primal feasibility */ if (!primalfeasible (D, Q)) { if ( Q->verbose ) { fprintf (lrs_ofp, "\nNumber of pivots for feasible solution: %ld",Q->count[3]); fprintf (lrs_ofp, " - No feasible solution"); ocount=Q->count[3]; } return FALSE; } if (Q->verbose) { fprintf (lrs_ofp, "\nNumber of pivots for feasible solution: %ld",Q->count[3]); ocount=Q->count[3]; } /* Now solve LP if objective function was given */ if (Q->maximize || Q->minimize) { Q->unbounded = !lrs_solvelp (D, Q, Q->maximize); /* check to see if objective is dual degenerate */ j = 1; while (j <= d && !zero (A[0][j])) j++; if (j <= d) Q->dualdeg = TRUE; } else /* re-initialize cost row to -det */ { for (j = 1; j <= d; j++) { copy (A[0][j], D->det); storesign (A[0][j], NEG); } itomp (ZERO, A[0][0]); /* zero optimum objective value */ } /* reindex basis to 0..m if necessary */ /* we use the fact that cobases are sorted by index value */ if (Q->debug) printA (D, Q); while (C[0] <= m) { i = C[0]; j = inequality[B[i] - lastdv]; inequality[B[i] - lastdv] = inequality[C[0] - lastdv]; inequality[C[0] - lastdv] = j; C[0] = B[i]; B[i] = i; reorder1 (C, Col, ZERO, d); } if (Q->debug) { fprintf (lrs_ofp, "\n*Inequality numbers for indices %ld .. %ld : ", lastdv + 1, m + d); for (i = 1; i <= m - nlinearity; i++) fprintf (lrs_ofp, " %ld ", inequality[i]); printA (D, Q); } if (Q->restart) { if (Q->debug) fprintf (lrs_ofp, "\nPivoting to restart co-basis"); if (!restartpivots (D, Q)) return FALSE; D->lexflag = lexmin (D, Q, ZERO); /* see if lexmin basis */ if (Q->debug) printA (D, Q); } /* Check to see if necessary to resize */ if (Q->inputd > D->d) *D_p = resize (D, Q); return TRUE; } /********* end of lrs_getfirstbasis ***************/ long getabasis2 (lrs_dic * P, lrs_dat * Q, lrs_dic * P2orig, long order[]) /* Pivot Ax<=b to standard form */ /*Try to find a starting basis by pivoting in the variables x[1]..x[d] */ /*If there are any input linearities, these appear first in order[] */ /* Steps: (a) Try to pivot out basic variables using order */ /* Stop if some linearity cannot be made to leave basis */ /* (b) Permanently remove the cobasic indices of linearities */ /* (c) If some decision variable cobasic, it is a linearity, */ /* and will be removed. */ { long i, j, k; /* assign local variables to structures */ lrs_mp_matrix A = P->A; long *B = P->B; long *C = P->C; long *Row = P->Row; long *Col = P->Col; long *linearity = Q->linearity; long *redundcol = Q->redundcol; long m, d, nlinearity; long nredundcol = 0L; /* will be calculated here */ static long firsttime=TRUE; static long *linindex; m = P->m; d = P->d; nlinearity = Q->nlinearity; if(firsttime) { firsttime = FALSE; linindex = (long int *) calloc ((m + d + 2), sizeof (long)); } else /* after first time we update the change in linearities from the last time, saving many pivots */ { for(i=1;i<=m+d;i++) linindex[i]=FALSE; if(Q->debug) fprintf(lrs_ofp,"\nlindex ="); for(i=0;idebug) fprintf(lrs_ofp," %ld",d+linearity[i]); } for(i=1;i<=m;i++) { if(linindex[B[i]]) /* pivot out unwanted linearities */ { k=0; while(k B[j]) /* decrease i or we may skip a linearity */ i--; pivot (P, Q, j, k); update (P, Q, &j, &k); } else if(Q->debug || Q->verbose) fprintf(lrs_ofp,"\n*Couldn't remove linearity i=%ld B[i]=%ld",i,B[i]); /* this is not necessarily an error, eg. two identical rows/cols in payoff matrix */ } } goto hotstart; } /* standard lrs processing is done on only the first call to getabasis2 */ if (Q->debug) { fprintf (lrs_ofp, "\ngetabasis from inequalities given in order"); for (i = 0; i < m; i++) fprintf (lrs_ofp, " %ld", order[i]); } for (j = 0; j < m; j++) { i = 0; while (i <= m && B[i] != d + order[j]) i++; /* find leaving basis index i */ if (j < nlinearity && i > m) /* cannot pivot linearity to cobasis */ { if (Q->debug) printA (P, Q); #ifndef LRS_QUIET fprintf (lrs_ofp, "\nCannot find linearity in the basis"); #endif return FALSE; } if (i <= m) { /* try to do a pivot */ k = 0; while (C[k] <= d && zero (A[Row[i]][Col[k]])) k++; if (C[k] <= d) { pivot (P, Q, i, k); update (P, Q, &i, &k); } else if (j < nlinearity) { /* cannot pivot linearity to cobasis */ if (zero (A[Row[i]][0])) { #ifndef LRS_QUIET fprintf (lrs_ofp, "\n*Input linearity in row %ld is redundant--skipped\n", order[j]); #endif linearity[j] = 0; } else { if (Q->debug) printA (P, Q); if (Q->verbose) fprintf (lrs_ofp, "\nInconsistent linearities"); return FALSE; } } /* end if j < nlinearity */ } /* end of if i <= m .... */ } /* end of for */ /* update linearity array to get rid of redundancies */ i = 0; k = 0; /* counters for linearities */ while (k < nlinearity) { while (k < nlinearity && linearity[k] == 0) k++; if (k < nlinearity) linearity[i++] = linearity[k++]; } nlinearity = i; /* column dependencies now can be recorded */ /* redundcol contains input column number 0..n-1 where redundancy is */ k = 0; while (k < d && C[k] <= d) { if (C[k] <= d) /* decision variable still in cobasis */ redundcol[nredundcol++] = C[k] - Q->hull; /* adjust for hull indices */ k++; } /* now we know how many decision variables remain in problem */ Q->nredundcol = nredundcol; Q->lastdv = d - nredundcol; /* if not first time we continue from here after loading dictionary */ hotstart: if (Q->debug) { fprintf (lrs_ofp, "\nend of first phase of getabasis2: "); fprintf (lrs_ofp, "lastdv=%ld nredundcol=%ld", Q->lastdv, Q->nredundcol); fprintf (lrs_ofp, "\nredundant cobases:"); for (i = 0; i < nredundcol; i++) fprintf (lrs_ofp, " %ld", redundcol[i]); printA (P, Q); } /* here we save dictionary for use next time, *before* we resize */ copy_dict(Q,P2orig,P); /* Remove linearities from cobasis for rest of computation */ /* This is done in order so indexing is not screwed up */ for (i = 0; i < nlinearity; i++) { /* find cobasic index */ k = 0; while (k < d && C[k] != linearity[i] + d) k++; if (k >= d) { if(Q->debug || Q->verbose) fprintf (lrs_ofp, "\nCould not remove cobasic index"); /* not neccesarily an error as eg., could be repeated row/col in payoff */ } else { removecobasicindex (P, Q, k); d = P->d; } } if (Q->debug && nlinearity > 0) printA (P, Q); /* set index value for first slack variable */ /* Check feasability */ if (Q->givenstart) { i = Q->lastdv + 1; while (i <= m && !negative (A[Row[i]][0])) i++; if (i <= m) fprintf (lrs_ofp, "\n*Infeasible startingcobasis - will be modified"); } return TRUE; } /* end of getabasis2 */ //========================================================================== // Outputting equilibria //========================================================================== // This is just a modified 'prat' from lrsmp.c void printrat (char name[], lrs_mp Nin, lrs_mp Din) /*reduce and print Nin/Din */ { lrs_mp Nt, Dt; long i; fprintf (stdout, "%s", name); /* reduce fraction */ copy (Nt, Nin); copy (Dt, Din); reduce (Nt, Dt); /* print out */ if (sign (Nin) * sign (Din) == NEG) fprintf (stdout, "-"); // else // fprintf (stdout, ""); fprintf (stdout, "%lu", Nt[length (Nt) - 1]); for (i = length (Nt) - 2; i >= 1; i--) fprintf (stdout, FORMAT, Nt[i]); if (!(Dt[0] == 2 && Dt[1] == 1)) /* rational */ { fprintf (stdout, "/"); fprintf (stdout, "%lu", Dt[length (Dt) - 1]); for (i = length (Dt) - 2; i >= 1; i--) fprintf (stdout, FORMAT, Dt[i]); } } void nashoutput(lrs_dat *Q1, lrs_mp_vector output1, lrs_dat *Q2, lrs_mp_vector output2, const StrategySupport &p_support) { std::cout << "NE"; // The -1 is because the last entry in the vector is the payoff // of the other player long i = 1; GamePlayer player1 = p_support.GetGame()->GetPlayer(1); for (int j = 1; j <= player1->NumStrategies(); j++) { if (p_support.Contains(player1->GetStrategy(j))) { std::cout << ","; printrat("", output1[i++], output1[0]); } else { std::cout << ",0"; } } i = 1; GamePlayer player2 = p_support.GetGame()->GetPlayer(2); for (int j = 1; j <= player2->NumStrategies(); j++) { if (p_support.Contains(player2->GetStrategy(j))) { std::cout << ","; printrat("", output2[i++], output2[0]); } else { std::cout << ",0"; } } std::cout << std::endl; fflush(stdout); } gambit-0.2010.09.01/src/tools/enummixed/ludecomp.cc0000644000076500007650000000210711435216101016473 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/ludecomp.cc // Instantiation of LU decomposition // // 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 "ludecomp.imp" template class EtaMatrix; template class LUdecomp; template class EtaMatrix; template class LUdecomp; gambit-0.2010.09.01/src/tools/enummixed/ludecomp.h0000644000076500007650000001121111435216101016331 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/ludecomp.h // Interface to LU decomposition classes // // 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 LUDECOMP_H #define LUDECOMP_H #include "libgambit/libgambit.h" #include "basis.h" template class Tableau; // --------------------------------------------------------------------------- // Class EtaMatrix // --------------------------------------------------------------------------- template class EtaMatrix { public: int col; Gambit::Vector etadata; EtaMatrix(int c, Gambit::Vector &v) : col(c), etadata(v) {}; // required for list class bool operator==(const EtaMatrix &) const; bool operator!=(const EtaMatrix &) const; }; // --------------------------------------------------------------------------- // Class LUdecomp // --------------------------------------------------------------------------- template class LUdecomp { private: Tableau &tab; Basis &basis; Gambit::List< EtaMatrix > L; Gambit::List< EtaMatrix > U; Gambit::List< EtaMatrix > E; Gambit::List< int > P; Gambit::Vector scratch1; // scratch vectors so we don't reallocate them Gambit::Vector scratch2; // everytime we do something. int refactor_number; int iterations; int total_operations; const LUdecomp *parent; int copycount; // don't use this copy constructor LUdecomp( const LUdecomp &a); // don't use the equals operator, use the Copy function instead LUdecomp& operator=(const LUdecomp&); public: class BadPivot : public Gambit::Exception { public: virtual ~BadPivot(); std::string GetDescription(void) const; }; class BadCount : public Gambit::Exception { public: virtual ~BadCount(); std::string GetDescription(void) const; }; // ------------------------ // Constructors, Destructor // ------------------------ // copy constructor // note: Copying will fail an assertion if you try to update or delete // the original before the copy has been deleted, refactored // Or set to something else. LUdecomp( const LUdecomp &, Tableau & ); // Decompose given matrix LUdecomp( Tableau &, int rfac = 0 ); // Destructor ~LUdecomp(); // -------------------- // Public Members // -------------------- // copies the LUdecomp given (expect for the basis &). void Copy( const LUdecomp &, Tableau & ); // replace (update) the column given with the vector given. void update( int, int matcol ); // matcol is the column number in the matrix // refactor void refactor(); // solve: Bk d = a void solve (const Gambit::Vector &, Gambit::Vector & ) const; // solve: y Bk = c void solveT( const Gambit::Vector &, Gambit::Vector & ) const; // set number of etamatrices added before refactoring; // if number is set to zero, refactoring is done automatically. // if number is < 0, no refactoring is done; void SetRefactor( int ); //------------------- // Private Members //------------------- private: void FactorBasis(); void GaussElem( Gambit::Matrix &, int, int ); bool CheckBasis(); bool RefactorCheck(); void BTransE( Gambit::Vector & ) const; void FTransE( Gambit::Vector & ) const; void BTransU( Gambit::Vector & ) const; void FTransU( Gambit::Vector & ) const; void LPd_Trans( Gambit::Vector & ) const; void yLP_Trans( Gambit::Vector & ) const; void VectorEtaSolve( const Gambit::Vector &v, const EtaMatrix &, Gambit::Vector &y ) const; void EtaVectorSolve( const Gambit::Vector &v, const EtaMatrix &, Gambit::Vector &d ) const; void yLP_mult( const Gambit::Vector &y, int j, Gambit::Vector &) const; void LPd_mult( Gambit::Vector &d, int j, Gambit::Vector &) const; }; // end of class LUdecomp #endif // LUDECOMP_H gambit-0.2010.09.01/src/tools/enummixed/ludecomp.imp0000644000076500007650000002570711435216101016706 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/ludecomp.imp // Implementation of LU decomposition // // 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 "libgambit/libgambit.h" #include "ludecomp.h" #include "tableau.h" // --------------------------------------------------------------------------- // Class EtaMatrix // --------------------------------------------------------------------------- template bool EtaMatrix::operator==(const EtaMatrix &a) const { return ( col == a.col && etadata == a.etadata ); } template bool EtaMatrix::operator!=(const EtaMatrix &a) const { return ( col != a.col || etadata != a.etadata ); } // --------------------------------------------------------------------------- // Class LUdecomp // --------------------------------------------------------------------------- // ------------------------- // C-tors, D-tor, Operators // ------------------------- // copy constructor template LUdecomp::LUdecomp( const LUdecomp &a, Tableau &t) : tab(t), basis(t.GetBasis()), scratch1(basis.First(), basis.Last()), scratch2(basis.First(), basis.Last()), refactor_number( a.refactor_number ), iterations(a.iterations), total_operations( a.total_operations), parent(&a), copycount(0) { ((LUdecomp &)*parent).copycount++; } // Decomposes given matrix template LUdecomp::LUdecomp( Tableau &t, int rfac/* = 0 */) : tab(t), basis(t.GetBasis()), scratch1(basis.First(), basis.Last()), scratch2(basis.First(), basis.Last()), refactor_number(rfac), iterations(0), parent(NULL), copycount(0) { int m = basis.Last() - basis.First() +1; total_operations = (m - 1) * m * (2 * m - 1) / 6; } // Destructor template LUdecomp::~LUdecomp() { if ( parent != NULL ) ((LUdecomp &) *parent).copycount--; if(copycount != 0) throw BadCount(); } // ------------------------- // Public Members // ------------------------- // use this to copy ludecomps.... template void LUdecomp::Copy(const LUdecomp &orig, Tableau &t) { if(this != &orig) { if (parent != NULL) ((LUdecomp &) *parent).copycount--; tab = t; basis = t.GetBasis(); L = Gambit::List >(); P = Gambit::List(); E = Gambit::List >(); U = Gambit::List >(); refactor_number = orig.refactor_number; iterations = orig.iterations; total_operations = orig.total_operations; parent = &orig; copycount = 0; ((LUdecomp &)*parent).copycount++; } } template void LUdecomp::update( int col, int matcol ) { if( copycount != 0 ) throw BadCount(); int m = basis.Last() - basis.First() + 1; iterations++; if (( refactor_number > 0 && iterations >= refactor_number ) || ( refactor_number == 0 && RefactorCheck()) ) refactor(); else { tab.GetColumn( matcol, scratch1); solve( scratch1, scratch1 ); if ( scratch1[col] == (T) 0 ) throw BadPivot(); E.Append( EtaMatrix( col, scratch1 ) ); total_operations += iterations * m + 2 * m * m; } } template void LUdecomp::refactor( ) { L = Gambit::List >(); U = Gambit::List >(); E = Gambit::List >(); P = Gambit::List(); if ( !basis.IsIdent() ) FactorBasis(); iterations = 0; int m = basis.Last() - basis.First() + 1; total_operations = (m - 1) * m * (2 * m - 1) / 6; if (parent != NULL) ((LUdecomp &)*parent).copycount--; parent = NULL; } template void LUdecomp::solveT( const Gambit::Vector &c, Gambit::Vector &y ) const { if ( c.First() != y.First() || c.Last() != y.Last() ) throw Gambit::DimensionException(); if ( c.First() != basis.First() || c.Last() != basis.Last()) throw Gambit::DimensionException(); y = c; if ( basis.IsIdent() != true ) { BTransE( y ); if ( parent != NULL ) (*parent).solveT( y, y ); else { FTransU( y ); yLP_Trans( y ); } } } template void LUdecomp::solve( const Gambit::Vector &a, Gambit::Vector &d ) const { if ( a.First() != d.First() || a.Last() != d.Last() ) throw Gambit::DimensionException(); if ( a.First() != basis.First() || a.Last() != basis.Last()) throw Gambit::DimensionException(); d = a; if ( basis.IsIdent() != true ) { if ( parent != NULL ) (*parent).solve(a,d); else { LPd_Trans( d ); BTransU( d ); } FTransE( d ); } } template void LUdecomp::SetRefactor( int a ) { refactor_number = a; } // ----------------- // Private Members // ----------------- template void LUdecomp::FactorBasis() { int i, j, piv; T pivVal; Gambit::Matrix B(basis.First(), basis.Last(), basis.First(), basis.Last()); for( i = basis.First(); i <= basis.Last(); i++ ) { tab.GetColumn( basis.Label(i), scratch2 ); basis.CheckBasis(); B.SetColumn( i, scratch2 ); } for ( i = B.MinRow(); i <= B.MaxRow(); i++) { pivVal = Gambit::abs ( B(i, i)); piv = i; for ( j = i+1; j <= B.MaxRow(); j++) { if ( B( j, i ) * B( j, i ) > pivVal * pivVal ) { piv = j; pivVal = B( j, i ); } } P.Append(piv); B.SwitchRows(i,piv); scratch2 = (T) 0; scratch2[i] = (T) 1 / B( i, i ); for ( j = i+1; j <= B.MaxRow(); j++ ) { scratch2[j] = - B(j, i) / B(i,i); } L.Append( EtaMatrix(i, scratch2) ); GaussElem(B, i, i); } for ( j = B.MinCol(); j <= B.MaxCol(); j++ ) { B.GetColumn( j, scratch2 ); U.Append( EtaMatrix( j, scratch2 )); } } template void LUdecomp::GaussElem(Gambit::Matrix &B, int row, int col) { if( B(row, col) == (T) 0) throw BadPivot(); int i,j; for ( j = col+1; j <= B.MaxCol(); j++) B( row, j ) = B( row, j ) / B( row, col ); for ( i = row+1; i <= B.MaxRow(); i++ ) for ( j = col+1; j <= B.MaxCol(); j++ ) { B( i, j ) = B( i, j ) - ( B( i, col ) * B( row, j ) ); } for ( i = row+1; i <= B.MaxRow(); i++ ) B( i , col ) = 0; B( row, col ) = (T) 1; } template void LUdecomp::BTransE( Gambit::Vector &y ) const { int i; for ( i = E.Length(); i >= 1; i-- ) { ((LUdecomp &) *this).scratch2 = y; VectorEtaSolve(scratch2, E[i], y ); } } template void LUdecomp::FTransU( Gambit::Vector &y ) const { int i; for ( i = 1; i <= U.Length(); i++ ) { ((LUdecomp &) *this).scratch2 = y; VectorEtaSolve(scratch2, U[i], y ); } } template void LUdecomp::VectorEtaSolve( const Gambit::Vector &v, const EtaMatrix &eta, Gambit::Vector &y ) const { int i, j; if ( v.First() != y.First() || v.Last() != y.Last() ) throw Gambit::DimensionException(); for ( i = v.First(); i <= v.Last(); i++ ) { y[i] = v[i]; if ( i == eta.col ) { for ( j = v.First(); j <= v.Last(); j++ ) if ( j != eta.col ) y[i] -= v[j] * eta.etadata[j]; y[i] /= eta.etadata[i]; } } } template void LUdecomp::FTransE( Gambit::Vector &y ) const { int i; for ( i = 1; i <= E.Length(); i++ ) { ((LUdecomp &) *this).scratch2 = y; EtaVectorSolve(scratch2, E[i], y ); } } template void LUdecomp::BTransU( Gambit::Vector &y ) const { int i; for ( i = U.Length(); i >= 1; i-- ) { ((LUdecomp &) *this).scratch2 = y; EtaVectorSolve(scratch2, U[i], y ); } } template void LUdecomp::EtaVectorSolve( const Gambit::Vector &v, const EtaMatrix &eta, Gambit::Vector &d ) const { int i; T temp; if ( v.First() != d.First() || v.Last() != d.Last() ) throw Gambit::DimensionException(); if ( eta.etadata[eta.col] == (T)0 ) throw BadPivot(); // or we would have a singular matrix temp = v[eta.col] / eta.etadata[eta.col]; for ( i = v.First(); i <= v.Last(); i++) { if ( i == eta.col ) d[i] = temp; else { d[i] = v[i] - temp * eta.etadata[i]; } } } template void LUdecomp::yLP_Trans( Gambit::Vector &y ) const { int j; for (j = L.Length(); j >= 1; j--) { yLP_mult( y, j, ((LUdecomp &) *this).scratch2 ); y = scratch2; } } template void LUdecomp::yLP_mult( const Gambit::Vector &y, int j, Gambit::Vector &ans ) const { if ( ans.First() != y.First() || ans.Last() != y.Last() ) throw Gambit::DimensionException(); T temp; int i, k, l; l = j + y.First() - 1; for (i = y.First(); i <= y.Last(); i++) { if ( i != L[j].col) ans[i] = y[i]; else { for ( k = ans.First(), temp = (T) 0; k <= ans.Last(); k++) { temp += y[k] * L[j].etadata[k]; } ans[i] = temp; } } temp = ans[l]; ans[l] = ans[P[j]]; ans[P[j]] = temp; } template void LUdecomp::LPd_Trans( Gambit::Vector &d ) const { int j; for (j = 1; j <= L.Length(); j++) { LPd_mult( d, j, ((LUdecomp &) *this).scratch2 ); d = scratch2; } } template void LUdecomp::LPd_mult( Gambit::Vector &d, int j, Gambit::Vector &ans ) const { if ( d.First() != ans.First() || d.Last() != ans.Last() ) throw Gambit::DimensionException(); T temp; int i, k; k = j + d.First() - 1; temp = d[k]; d[k] = d[P[j]]; d[P[j]] = temp; for (i = d.First(); i <= d.Last(); i++) { if ( i == L[j].col ) ans[i] = d[i] * L[j].etadata[i]; else { ans[i] = d[i] + d[ L[j].col ] * L[j].etadata[i]; } } d[P[j]] = d[k]; d[k] = temp; } template bool LUdecomp::CheckBasis() { int i; bool ret = true; for (i = basis.First(); i <= basis.Last() && ret != false; i++) ret = ret && ( basis.Label(i) == -i ); return ret; } template bool LUdecomp::RefactorCheck() { int m = basis.Last() - basis.First() + 1; int i = iterations * (iterations * m + 2 * m * m ); int k = total_operations + iterations * m + 2 * m * m; bool tmp; tmp = ( i > k ); return tmp; } template LUdecomp::BadCount::~BadCount() { } template std::string LUdecomp::BadCount::GetDescription(void) const { return "Bad Reference count in LUdecomp"; } template LUdecomp::BadPivot::~BadPivot() { } template std::string LUdecomp::BadPivot::GetDescription(void) const { return "Bad Pivot in LUdecomp"; } gambit-0.2010.09.01/src/tools/enummixed/tableau.h0000644000076500007650000001145011435216101016143 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/tableau.h // Interface to tableau class // // 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 TABLEAU_H #define TABLEAU_H #include "btableau.h" #include "ludecomp.h" template class Tableau; template class LPTableau; // --------------------------------------------------------------------------- // We have different implementations of Tableau for double and gbtRational, // but with the same interface // --------------------------------------------------------------------------- // // Tableau // template<> class Tableau : public TableauInterface{ private: LUdecomp B; // LU decomposition Gambit::Vector tmpcol; // temporary column vector, to avoid allocation public: // constructors and destructors Tableau(const Gambit::Matrix &A, const Gambit::Vector &b); Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); Tableau(const Tableau&); virtual ~Tableau(); Tableau& operator=(const Tableau&); // pivoting int CanPivot(int outgoing,int incoming); void Pivot(int outrow,int col); // pivot -- outgoing is row, incoming is column void BasisVector(Gambit::Vector &x) const; // solve M x = (*b) void SolveColumn(int, Gambit::Vector &); // column in new basis void Solve(const Gambit::Vector &b, Gambit::Vector &x); // solve M x = b void SolveT(const Gambit::Vector &c, Gambit::Vector &y); // solve y M = c // raw Tableau functions void Refactor(); void SetRefactor(int); void SetConst(const Gambit::Vector &bnew); void SetBasis( const Basis &); // set new Tableau bool IsFeasible(); bool IsLexMin(); }; // // Tableau // template<> class Tableau : public TableauInterface{ private: int remap(int col_index) const; // aligns the column indexes Gambit::Matrix GetInverse(); Gambit::Matrix Tabdat; // This caries the full tableau Gambit::Vector Coeff; // and coeffieient vector Gambit::Integer totdenom; // This carries the denominator for Q data or 1 for Z Gambit::Integer denom; // This is the denominator for the simplex Gambit::Vector tmpcol; // temporary column vector, to avoid allocation void MySolveColumn(int, Gambit::Vector &); // column in new basis protected: Gambit::Array nonbasic; //** nonbasic variables -- should be moved to Basis public: class BadDenom : public Gambit::Exception { public: virtual ~BadDenom(); std::string GetDescription(void) const; }; // constructors and destructors Tableau(const Gambit::Matrix &A, const Gambit::Vector &b); Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); Tableau(const Tableau&); virtual ~Tableau(); Tableau& operator=(const Tableau&); // pivoting int CanPivot(int outgoing,int incoming); void Pivot(int outrow,int col); // pivot -- outgoing is row, incoming is column void SolveColumn(int, Gambit::Vector &); // column in new basis void GetColumn(int, Gambit::Vector &) const; // column in new basis // raw Tableau functions void Refactor(); void SetRefactor(int); void SetConst(const Gambit::Vector &bnew); void SetBasis( const Basis &); // set new Tableau void Solve(const Gambit::Vector &b, Gambit::Vector &x); // solve M x = b void SolveT(const Gambit::Vector &c, Gambit::Vector &y); // solve y M = c bool IsFeasible(); bool IsLexMin(); void BasisVector(Gambit::Vector &out) const; Gambit::Integer TotDenom() const; }; #endif // TABLEAU_H gambit-0.2010.09.01/src/tools/enummixed/tableau.imp0000644000076500007650000003672611435216101016516 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/tableau.imp // Implementation of tableau class // // 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 "tableau.h" // --------------------------------------------------------------------------- // Tableau method definitions // --------------------------------------------------------------------------- // Constructors and Destructor Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Vector &b) : TableauInterface(A,b), B(*this), tmpcol(b.First(),b.Last()) { Solve(b, solution); }; Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : TableauInterface(A,art,b), B(*this), tmpcol(b.First(),b.Last()) { Solve(b, solution); }; Tableau::Tableau(const Tableau &orig) : TableauInterface(orig), B(orig.B,*this), tmpcol(orig.tmpcol) { } Tableau::~Tableau() { } Tableau& Tableau::operator=(const Tableau &orig) { TableauInterface::operator=(orig); if(this!= &orig) { B.Copy(orig.B,*this); tmpcol = orig.tmpcol; } return *this; } // // pivoting operations // int Tableau::CanPivot(int outlabel, int col) { SolveColumn(col,tmpcol); double val = tmpcol[basis.Find(outlabel)]; if(val <=eps2 && val >= -eps2) return 0; return 1; } void Tableau::Pivot(int outrow,int col) { if(!RowIndex(outrow) || !ValidIndex(col)) throw BadPivot(); // int outlabel = Label(outrow); // gout << "\noutrow:" << outrow; // gout << " outlabel: " << outlabel; // gout << " inlabel: " << col; // BigDump(gout); basis.Pivot(outrow,col); B.update(outrow, col); Solve(*b, solution); npivots++; // BigDump(gout); } void Tableau::SolveColumn(int col, Gambit::Vector &out) { //** can we use tmpcol here, instead of allocating new vector? Gambit::Vector tmpcol2(MinRow(),MaxRow()); GetColumn(col,tmpcol2); Solve(tmpcol2,out); } void Tableau::BasisVector(Gambit::Vector &out) const { out= solution; } // // raw Tableau functions // void Tableau::Refactor() { B.refactor(); //** is re-solve necessary here? Solve(*b, solution); } void Tableau::SetRefactor(int n) { B.SetRefactor(n); } void Tableau::SetConst(const Gambit::Vector &bnew) { if(bnew.First()!=b->First() || bnew.Last()!=b->Last()) throw Gambit::DimensionException(); b=&bnew; Solve(*b, solution); } //** this function is not currently used. Drop it? void Tableau::SetBasis(const Basis &in) { basis= in; B.refactor(); Solve(*b, solution); } void Tableau::Solve(const Gambit::Vector &b, Gambit::Vector &x) { B.solve(b,x); } void Tableau::SolveT(const Gambit::Vector &c, Gambit::Vector &y) { B.solveT(c,y); //** gout << "\nTableau::SolveT(), y: " << y; // gout << "\nc: " << c; } bool Tableau::IsFeasible() { //** is it really necessary to solve first here? Solve(*b, solution); for(int i=solution.First();i<=solution.Last();i++) if(solution[i]>=eps2) return false; return true; } bool Tableau::IsLexMin() { int i,j; for(i=MinRow();i<=MaxRow();i++) if(EqZero(solution[i])) for(j=-MaxRow();j method definitions // --------------------------------------------------------------------------- Gambit::Integer find_lcd(const Gambit::Matrix &mat) { Gambit::Integer lcd(1); for(int i=mat.MinRow();i<=mat.MaxRow();i++) for(int j=mat.MinCol();j<=mat.MaxCol();j++) lcd = lcm(mat(i,j).denominator(),lcd); return lcd; } Gambit::Integer find_lcd(const Gambit::Vector &vec) { Gambit::Integer lcd(1); for(int i=vec.First();i<=vec.Last();i++) lcd = lcm(vec[i].denominator(),lcd); return lcd; } // Constructors and Destructor Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Vector &b) : TableauInterface(A,b), Tabdat(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()), Coeff(b.First(),b.Last()), denom(1), tmpcol(b.First(),b.Last()), nonbasic(A.MinCol(),A.MaxCol()) { int j; for(j=MinCol();j<=MaxCol();j++) nonbasic[j] = j; totdenom = lcm(find_lcd(A),find_lcd(b)); if(totdenom<=0) throw BadDenom(); for (int i = b.First();i<=b.Last();i++) { Gambit::Rational x = b[i]*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Coeff[i] = x.numerator(); } for (int i = MinRow();i<=MaxRow();i++) for (int j = MinCol();j<=MaxCol();j++) { Gambit::Rational x = A(i,j)*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Tabdat(i,j) = x.numerator(); } for (int i = b.First();i<=b.Last();i++) solution[i] = (Gambit::Rational)Coeff[i]; } Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : TableauInterface(A,art,b), Tabdat(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()+art.Length()), Coeff(b.First(),b.Last()), denom(1), tmpcol(b.First(),b.Last()), nonbasic(A.MinCol(),A.MaxCol()+art.Length()) { int j; for(j=MinCol();j<=MaxCol();j++) nonbasic[j] = j; totdenom = lcm(find_lcd(A),find_lcd(b)); if(totdenom<=0) throw BadDenom(); for (int i = b.First();i<=b.Last();i++) { Gambit::Rational x = b[i]*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Coeff[i] = x.numerator(); } for (int i = MinRow();i<=MaxRow();i++) { for (int j = MinCol();j<=A.MaxCol();j++) { Gambit::Rational x = A(i,j)*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Tabdat(i,j) = x.numerator(); } for (int j = A.MaxCol()+1;j<=MaxCol();j++) Tabdat(artificial[j],j) = totdenom; } for (int i = b.First();i<=b.Last();i++) solution[i] = (Gambit::Rational)Coeff[i]; } Tableau::Tableau(const Tableau &orig) : TableauInterface(orig), Tabdat(orig.Tabdat), Coeff(orig.Coeff), totdenom(orig.totdenom), denom(orig.denom), tmpcol(orig.tmpcol), nonbasic(orig.nonbasic) { } Tableau::~Tableau() { } Tableau& Tableau::operator=(const Tableau &orig) { TableauInterface::operator=(orig); if(this!= &orig) { Tabdat = orig.Tabdat; Coeff = orig.Coeff; totdenom = orig.totdenom; denom = orig.denom; tmpcol = orig.tmpcol; nonbasic = orig.nonbasic; } return *this; } // Aligns the column indexes int Tableau::remap(int col_index) const { int i = nonbasic.First(); while(i <= nonbasic.Last() && nonbasic[i] !=col_index) { i++;} if(i > nonbasic.Last()) throw Gambit::DimensionException(); return i; } Gambit::Matrix Tableau::GetInverse() { Gambit::Vector mytmpcol(tmpcol.First(),tmpcol.Last()); Gambit::Matrix inv(MinRow(),MaxRow(),MinRow(),MaxRow()); for(int i=inv.MinCol();i<=inv.MaxCol();i++){ MySolveColumn(-i,mytmpcol); inv.SetColumn(i,mytmpcol); } return inv; } // pivoting operations int Tableau::CanPivot(int outlabel, int col) { MySolveColumn(col,tmpcol); Gambit::Rational val = tmpcol[basis.Find(outlabel)]; if(val == (Gambit::Rational)0) return 0; // if(val <=eps2 && val >= -eps2) return 0; return 1; } void Tableau::Pivot(int outrow,int in_col) { // gout << "\nIn Tableau::Pivot() "; // gout << " outrow:" << outrow; // gout << " inlabel: " << in_col; if(!RowIndex(outrow) || !ValidIndex(in_col)) throw BadPivot(); int outlabel = Label(outrow); // gout << "\noutrow:" << outrow; // gout << " outlabel: " << outlabel; // gout << " inlabel: " << in_col; // BigDump(gout); // gout << "\ndenom: " << denom << " totdenom: " << totdenom; // gout << " product: " << denom*totdenom; // gout << "\nTabdat: loc 1\n " << Tabdat; // gout << "\nInverse: loc 1\n " << GetInverse(); int col; int row(outrow); int i,j; // loop-control variables col = remap(in_col); // Pivot Algorithm: // i* denotes Pivot Row // j* denotes Pivot Column // C is the Tableau // Cij is the (i,j)th component of C // X denotes multiplication // d is the denominator (initially 1) // // 1: Copy row i (don't need to implement this) // 2: Zero column j excepting the Pivot Element (done second) // 3: Cij=(Ci*j*XCij-Ci*jXCij*)/d for all other elements (done first) // 4: d=Ci*j* (done last) // Step 3 for(i=Tabdat.MinRow();i<=Tabdat.MaxRow();++i){ if(i!=row){ for(j=Tabdat.MinCol();j<=Tabdat.MaxCol();++j){ if(j!=col){ Tabdat(i,j) = (Tabdat(row,col)*Tabdat(i,j)-Tabdat(row,j)*Tabdat(i,col))/denom; } } Coeff[i] = (Tabdat(row,col)*Coeff[i]-Coeff[row]*Tabdat(i,col))/denom; } } // Step 2 // Note: here we are moving the old basis column into column 'col' for(i=Tabdat.MinRow();i<=Tabdat.MaxRow();++i){ if(i!=row) Tabdat(i,col)=-Tabdat(i,col); } // Step 4 Gambit::Integer old_denom = denom; denom=Tabdat(row,col); Tabdat(row,col)=old_denom; // BigDump(gout); npivots++; basis.Pivot(outrow,in_col); nonbasic[col] = outlabel; for (i = solution.First();i<=solution.Last();i++) //** solution[i] = (Gambit::Rational)(Coeff[i])/(Gambit::Rational)(denom*totdenom); solution[i] = Gambit::Rational(Coeff[i]*sign(denom*totdenom)); //gout << "Bottom \n" << Tabdat << '\n'; // BigDump(gout); // gout << "\ndenom: " << denom << " totdenom: " << totdenom; // gout << "\nTabdat: loc 2\n " << Tabdat; // gout << "\nInverse: loc 2\n " << GetInverse(); // Refactor(); } void Tableau::SolveColumn(int in_col, Gambit::Vector &out) { Gambit::Vector tempcol(tmpcol.First(),tmpcol.Last()); if(Member(in_col)) { out = (Gambit::Rational)0; out[Find(in_col)] = Gambit::Rational(abs(denom)); } else { int col = remap(in_col); Tabdat.GetColumn(col,tempcol); for(int i=tempcol.First();i<=tempcol.Last();i++) out[i] = (Gambit::Rational)(tempcol[i]) * (Gambit::Rational)(sign(denom*totdenom)); } out=out/(Gambit::Rational)abs(denom); if(in_col < 0) out*=totdenom; for(int i=out.First();i<=out.Last();i++) if(Label(i)<0) out[i]=(Gambit::Rational)out[i]/(Gambit::Rational)totdenom; } void Tableau::MySolveColumn(int in_col, Gambit::Vector &out) { Gambit::Vector tempcol(tmpcol.First(),tmpcol.Last()); if(Member(in_col)) { out = (Gambit::Rational)0; out[Find(in_col)] = Gambit::Rational(abs(denom)); } else { int col = remap(in_col); Tabdat.GetColumn(col,tempcol); for(int i=tempcol.First();i<=tempcol.Last();i++) out[i] = (Gambit::Rational)(tempcol[i]) * (Gambit::Rational)(sign(denom*totdenom)); } } void Tableau::GetColumn(int col, Gambit::Vector &out) const { TableauInterface::GetColumn(col,out); if(col>=0) out*=Gambit::Rational(totdenom); } void Tableau::Refactor() { Gambit::Vector mytmpcol(tmpcol); //BigDump(gout); //** Note -- we may need to recompute totdenom here, if A and b have changed. //gout << "\ndenom: " << denom << " totdenom: " << totdenom; totdenom = lcm(find_lcd(*A),find_lcd(*b)); if(totdenom<=0) throw BadDenom(); // gout << "\ndenom: " << denom << " totdenom: " << totdenom; int i,j; Gambit::Matrix inv(GetInverse()); Gambit::Matrix Tabnew(Tabdat.MinRow(),Tabdat.MaxRow(),Tabdat.MinCol(),Tabdat.MaxCol()); for(i=nonbasic.First();i<=nonbasic.Last();i++) { GetColumn(nonbasic[i],mytmpcol); // if(nonbasic[i]>=0) mytmpcol*=Gambit::Rational(totdenom); Tabnew.SetColumn(i,inv * mytmpcol * (Gambit::Rational)sign(denom*totdenom)); //gout << "\nMyTmpCol \n" << mytmpcol; } //gout << "\nInv: \n" << inv; //gout << "\nTabdat:\n" << Tabdat; //gout << "\nTabnew:\n" << Tabnew; Gambit::Vector Coeffnew(Coeff.First(),Coeff.Last()); Coeffnew = inv * (*b) * totdenom * (Gambit::Rational)sign(denom*totdenom); //gout << "\nCoeff:\n" << Coeff; //gout << "\nCoeffew:\n" << Coeffnew; for(i=Tabdat.MinRow();i<=Tabdat.MaxRow();i++) { if(Coeffnew[i].denominator() != 1) throw BadDenom(); Coeff[i] = Coeffnew[i].numerator(); for(j=Tabdat.MinCol();j<=Tabdat.MaxCol();j++) { if(Tabnew(i,j).denominator() != 1) throw BadDenom(); Tabdat(i,j) = Tabnew(i,j).numerator(); } } //BigDump(gout); } void Tableau::SetRefactor(int) { } void Tableau::SetConst(const Gambit::Vector &bnew) { b=&bnew; Refactor(); } //** this function is not currently used. Drop it? void Tableau::SetBasis(const Basis &in) { basis= in; //** this has to be changed -- Need to start over and pivot to new basis. // B.refactor(); // B.solve(*b, solution); } // solve M x = b void Tableau::Solve(const Gambit::Vector &b, Gambit::Vector &x) { // Here, we do x = V * b, where V = M inverse x = (GetInverse() * b )/(Gambit::Rational)abs(denom); } // solve y M = c void Tableau::SolveT(const Gambit::Vector &c, Gambit::Vector &y) { // Here we do y = c * V, where V = M inverse y = (c * GetInverse()) /(Gambit::Rational)abs(denom); } bool Tableau::IsFeasible() { for(int i=solution.First();i<=solution.Last();i++) if(solution[i]>=eps2) return false; return true; } bool Tableau::IsLexMin() { int i,j; for(i=MinRow();i<=MaxRow();i++) if(EqZero(solution[i])) for(j=-MaxRow();j::BasisVector(Gambit::Vector &out) const { out = solution; out= out/(Gambit::Rational)abs(denom) ; for(int i=out.First();i<=out.Last();i++) if(Label(i)<0) out[i]=out[i]/(Gambit::Rational)totdenom; } Gambit::Integer Tableau::TotDenom() const { return totdenom; } Tableau::BadDenom::~BadDenom() { } std::string Tableau::BadDenom::GetDescription(void) const { return "Bad Denominator in Tableau"; } gambit-0.2010.09.01/src/tools/enummixed/vertenum.h0000644000076500007650000000456411435216101016403 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/vertenum.h // Interface to vertex enumerator // // 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 VERTENUM_H #define VERTENUM_H #include "libgambit/libgambit.h" #include "lptab.h" #include "bfs.h" // // This class enumerates the vertices of the convex polyhedron // // P = {y:Ay + b <= 0, y>=0 } // // where b <= 0. Enumeration starts from the vertex y = 0. // All computation is done in the class constructor. The // list of vertices can be accessed by VertexList() // // The code is based on the reverse Pivoting algorithm of Avis // and Fukuda, Discrete Computational Geom (1992) 8:295-313. // template class VertEnum { private: int mult_opt,depth; int n; // N is the number of columns, which is the # of dimensions. int k; // K is the number of inequalities given. // Removed const on A and b (Geoff) const Gambit::Matrix &A; const Gambit::Vector &b; Gambit::Vector btemp,c; Gambit::List > List; Gambit::List > DualList; Gambit::List > Verts; long npivots,nodes; Gambit::List visits,branches; void Enum(); void Deeper(); void Report(); void Search(LPTableau &tab); void DualSearch(LPTableau &tab); public: VertEnum(const Gambit::Matrix &, const Gambit::Vector &); VertEnum(LPTableau &); virtual ~VertEnum(); const Gambit::List > &VertexList() const; const Gambit::List > &DualVertexList() const; void Vertices(Gambit::List > &verts) const; long NumPivots() const; }; #ifdef _A #undef _A #endif #endif // VERTENUM_H gambit-0.2010.09.01/src/tools/enummixed/vertenum.imp0000644000076500007650000001166511435216101016741 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enummixed/vertenum.imp // Implementation of vertex enumerator // // 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 "vertenum.h" template VertEnum::VertEnum(const Gambit::Matrix &_A, const Gambit::Vector &_b) : mult_opt(0), depth(0), A(_A), b(_b), btemp(_b), c(_A.MinCol(),_A.MaxCol()), npivots(0), nodes(0) { Enum(); } template VertEnum::VertEnum(LPTableau &tab) : mult_opt(0), depth(0), A(tab.Get_A()), b(tab.Get_b()), btemp(tab.Get_b()), c(tab.GetCost()), npivots(0), nodes(0) { // gout << "\nin VertEnum(tab)\n"; // tab.Dump(gout); int i; for(i=b.First();i<=b.Last();i++) if(b[i]==(T)0) mult_opt=1; // gout << "\nb: " << b; // Is this stuff right? btemp = -(T)1; Gambit::Vector uc(tab.MinRow(),tab.MaxRow()); c = (T)1; uc = (T)1; for(i=-tab.MaxRow();i<=-tab.MinRow();i++) if(tab.Member(i)) uc[-i]=(T)0; for(i=tab.MinCol();i<=tab.MaxCol();i++) if(tab.Member(i)) c[i]=(T)0; // gout << "\nc: " << c; // gout << "\nuc: " << uc; tab.SetCost(uc,c); DualSearch(tab); } template VertEnum::~VertEnum() { } template void VertEnum::Enum() { // Check dimensions if(A.NumRows() != b.Length() || A.NumColumns() != c.Length()) throw Gambit::DimensionException(); // assert(A.NumRows() == b.Length() && A.NumColumns() == c.Length()); // Initialize the tableau int i; for(i=b.First();i<=b.Last();i++) if(b[i]==(T)0) mult_opt=1; btemp = -(T)1; c = (T)1; LPTableau tab(A,b); tab.SetCost(c); // gout << "\nInitial Tableau = \n"; // tab.Dump(gout); DualSearch(tab); } template void VertEnum::Report() { int i = 1; double x, estNodes; estNodes=x=(double)1; while(i<=visits.Length()) { if(visits[i]) { x*=(double)branches[i]/(double)visits[i]; estNodes+=x; } i++; } } template void VertEnum::Deeper() { depth++; if(visits.Length() void VertEnum::Search(LPTableau &tab) { int k; Deeper(); Gambit::List > PivotList; Gambit::Array pivot(2); if(tab.IsLexMin()) { List.Append(tab.GetBFS1()); DualList.Append(tab.DualBFS()); } if(PivotList.Length()!=0) throw Gambit::DimensionException(); // assert(PivotList.Length()==0); tab.ReversePivots(PivotList); // get list of reverse pivots if(PivotList.Length()) { branches[depth]+=PivotList.Length(); LPTableau tab2(tab); for(k=1;k<=PivotList.Length();k++) { pivot = PivotList[k]; npivots++; tab2=tab; tab2.Pivot(pivot[1],pivot[2]); Search(tab2); } } else Report(); // Report progress at terminal leafs depth--; } template void VertEnum::DualSearch(LPTableau &tab) { int i,j; Deeper(); branches[depth]+=1; // Gambit::List > PivotList; // Gambit::Array pivot(2); // gout << "\nin DualSearch"; if(mult_opt) { tab.SetConst(btemp); // install artifical constraint vector LPTableau tab2(tab); for (i=b.First();i<=b.Last(); i++) { if(b[i]==(T)0) for(j=-b.Last();j<=c.Last();j++) { if(j && !tab.Member(j) && !tab.IsBlocked(j)) if(tab.IsDualReversePivot(i,j)) { branches[depth]+=1; npivots++; tab2=tab; tab2.Pivot(i,j); DualSearch(tab2); } } } } tab.SetConst(b); // install original constraint vector Search(tab); // do primal search depth--; } template const Gambit::List > &VertEnum::VertexList() const { return List; } template const Gambit::List > &VertEnum::DualVertexList() const { return DualList; } template void VertEnum::Vertices(Gambit::List > &verts) const { for(int i=1;i<=List.Length();i++) { Gambit::Vector vert(A.NumColumns()); vert = (T)0; for(int j=1;j<=vert.Length();j++) if(List[i].IsDefined(j)) vert[j]=-List[i](j); verts.Append(vert); } } template long VertEnum::NumPivots() const { return npivots; } gambit-0.2010.09.01/src/tools/enumpoly/0000777000076500007650000000000011441457120014322 500000000000000gambit-0.2010.09.01/src/tools/enumpoly/behavextend.cc0000644000076500007650000004761611435216101017053 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/behavextend.cc // Algorithms for extending behavior profiles to Nash equilibria // // 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 "behavextend.h" #include "gpoly.h" #include "gpolylst.h" #include "rectangl.h" #include "ineqsolv.h" void TerminalDescendants(Gambit::GameNode p_node, Gambit::List ¤t) { if (p_node->IsTerminal()) { current.Append(p_node); } else { for (int i = 1; i <= p_node->NumChildren(); i++) { TerminalDescendants(p_node->GetChild(i), current); } } } Gambit::List TerminalNodes(Gambit::Game p_efg) { Gambit::List ret; TerminalDescendants(p_efg->GetRoot(), ret); return ret; } // // Design choice: the auxiliary functions here are made static // rather than members to help hide the gPoly-related details of // the implementation. Some of these functions might be more // generally useful, in which case they should be made visible // somehow. Also, a namespace would be preferable to using // static, but static is used for portability. -- TLT, 5/2001. // //========================================================================= // class algExtendsToNash //========================================================================= static void DeviationInfosets(Gambit::List &answer, const Gambit::BehavSupport & big_supp, const Gambit::GamePlayer &pl, const Gambit::GameNode &node, const Gambit::GameAction &act) { Gambit::GameNode child = node->GetChild(act->GetNumber()); if (!child->IsTerminal()) { Gambit::GameInfoset iset = child->GetInfoset(); if ( iset->GetPlayer() == pl ) { int insert = 0; bool done = false; while (!done) { insert ++; if (insert > answer.Length() || iset->Precedes(answer[insert]->GetMember(1))) done = true; } answer.Insert(iset,insert); } Gambit::List action_list; for (int j = 1; j <= iset->NumActions(); j++) { action_list.Append(iset->GetAction(j)); } for (int j = 1; j <= action_list.Length(); j++) { DeviationInfosets(answer,big_supp,pl,child,action_list[j]); } } } static Gambit::List DeviationInfosets(const Gambit::BehavSupport &big_supp, const Gambit::GamePlayer &pl, const Gambit::GameInfoset &iset, const Gambit::GameAction &act) { Gambit::List answer; Gambit::List node_list; for (int i = 1; i <= iset->NumMembers(); i++) { node_list.Append(iset->GetMember(i)); } for (int i = 1; i <= node_list.Length(); i++) { DeviationInfosets(answer,big_supp,pl,node_list[i],act); } return answer; } static gPolyList ActionProbsSumToOneIneqs(const Gambit::MixedBehavProfile &p_solution, const gSpace &BehavStratSpace, const term_order &Lex, const Gambit::BehavSupport &big_supp, const Gambit::List > &var_index) { gPolyList answer(&BehavStratSpace, &Lex); for (int pl = 1; pl <= p_solution.GetGame()->NumPlayers(); pl++) for (int i = 1; i <= p_solution.GetGame()->GetPlayer(pl)->NumInfosets(); i++) { Gambit::GameInfoset current_infoset = p_solution.GetGame()->GetPlayer(pl)->GetInfoset(i); if ( !big_supp.HasActiveActionAt(current_infoset) ) { int index_base = var_index[pl][i]; gPoly factor(&BehavStratSpace, (double)1.0, &Lex); for (int k = 1; k < current_infoset->NumActions(); k++) factor -= gPoly(&BehavStratSpace, index_base + k, 1, &Lex); answer += factor; } } return answer; } static Gambit::List DeviationSupports(const Gambit::BehavSupport & big_supp, const Gambit::List & isetlist, const Gambit::GamePlayer &/*pl*/, const Gambit::GameInfoset &/*iset*/, const Gambit::GameAction &/*act*/) { Gambit::List answer; Gambit::Array active_act_no(isetlist.Length()); for (int k = 1; k <= active_act_no.Length(); k++) active_act_no[k] = 0; Gambit::BehavSupport new_supp(big_supp); for (int i = 1; i <= isetlist.Length(); i++) { for (int j = 1; j < isetlist[i]->NumActions(); j++) new_supp.RemoveAction(isetlist[i]->GetAction(j)); new_supp.AddAction(isetlist[i]->GetAction(1)); active_act_no[i] = 1; for (int k = 1; k < i; k++) if (isetlist[k]->Precedes(isetlist[i]->GetMember(1))) if (isetlist[k]->GetAction(1)->Precedes(isetlist[i]->GetMember(1))) { new_supp.RemoveAction(isetlist[i]->GetAction(1)); active_act_no[i] = 0; } } answer.Append(new_supp); int iset_cursor = isetlist.Length(); while (iset_cursor > 0) { if ( active_act_no[iset_cursor] == 0 || active_act_no[iset_cursor] == isetlist[iset_cursor]->NumActions() ) iset_cursor--; else { new_supp.RemoveAction(isetlist[iset_cursor]-> GetAction(active_act_no[iset_cursor])); active_act_no[iset_cursor]++; new_supp.AddAction(isetlist[iset_cursor]-> GetAction(active_act_no[iset_cursor])); for (int k = iset_cursor + 1; k <= isetlist.Length(); k++) { if (active_act_no[k] > 0) new_supp.RemoveAction(isetlist[k]->GetAction(1)); int h = 1; bool active = true; while (active && h < k) { if (isetlist[h]->Precedes(isetlist[k]->GetMember(1))) if (active_act_no[h] == 0 || !isetlist[h]->GetAction(active_act_no[h])-> Precedes(isetlist[k]->GetMember(1))) { active = false; if (active_act_no[k] > 0) { new_supp.RemoveAction(isetlist[k]-> GetAction(active_act_no[k])); active_act_no[k] = 0; } } h++; } if (active){ new_supp.AddAction(isetlist[k]->GetAction(1)); active_act_no[k] = 1; } } answer.Append(new_supp); } } return answer; } static bool NashNodeProbabilityPoly(const Gambit::MixedBehavProfile &p_solution, gPoly & node_prob, const gSpace &BehavStratSpace, const term_order &Lex, const Gambit::BehavSupport &dsupp, const Gambit::List > &var_index, Gambit::GameNode tempnode, const Gambit::GamePlayer &/*pl*/, const Gambit::GameInfoset &iset, const Gambit::GameAction &act) { while (tempnode != p_solution.GetGame()->GetRoot()) { Gambit::GameAction last_action = tempnode->GetPriorAction(); Gambit::GameInfoset last_infoset = last_action->GetInfoset(); if (last_infoset->IsChanceInfoset()) node_prob *= (double) last_infoset->GetActionProb(last_action->GetNumber()); else if (dsupp.HasActiveActionAt(last_infoset)) { if (last_infoset == iset) { if (act != last_action) { return false; } } else if (dsupp.Contains(last_action)) { if ( last_action->GetInfoset()->GetPlayer() != act->GetInfoset()->GetPlayer() || !act->Precedes(tempnode) ) node_prob *= (double) p_solution.GetActionProb(last_action); } else { return false; } } else { int initial_var_no = var_index[last_infoset->GetPlayer()->GetNumber()][last_infoset->GetNumber()]; if (last_action->GetNumber() < last_infoset->NumActions()){ int varno = initial_var_no + last_action->GetNumber(); node_prob *= gPoly(&BehavStratSpace, varno, 1, &Lex); } else { gPoly factor(&BehavStratSpace, (double)1.0, &Lex); int k; for (k = 1; k < last_infoset->NumActions(); k++) factor -= gPoly(&BehavStratSpace, initial_var_no + k, 1, &Lex); node_prob *= factor; } } tempnode = tempnode->GetParent(); } return true; } static gPolyList NashExpectedPayoffDiffPolys(const Gambit::MixedBehavProfile &p_solution, const gSpace &BehavStratSpace, const term_order &Lex, const Gambit::BehavSupport &little_supp, const Gambit::BehavSupport &big_supp, const Gambit::List > &var_index) { gPolyList answer(&BehavStratSpace, &Lex); Gambit::List terminal_nodes = TerminalNodes(p_solution.GetGame()); for (int pl = 1; pl <= p_solution.GetGame()->NumPlayers(); pl++) { Gambit::Array isets_for_pl; for (int iset = 1; iset <= p_solution.GetGame()->GetPlayer(pl)->NumInfosets(); iset++) { isets_for_pl.Append(p_solution.GetGame()->GetPlayer(pl)->GetInfoset(iset)); } for (int i = 1; i <= isets_for_pl.Length(); i++) { if (little_supp.MayReach(isets_for_pl[i])) { Gambit::Array acts_for_iset; for (int act = 1; act <= isets_for_pl[i]->NumActions(); act++) { acts_for_iset.Append(isets_for_pl[i]->GetAction(act)); } for (int j = 1; j <= acts_for_iset.Length(); j++) if ( !little_supp.Contains(acts_for_iset[j]) ) { Gambit::List isetlist = DeviationInfosets(big_supp, p_solution.GetGame()->GetPlayer(pl), isets_for_pl[i], acts_for_iset[j]); Gambit::List dsupps = DeviationSupports(big_supp, isetlist, p_solution.GetGame()->GetPlayer(pl), isets_for_pl[i], acts_for_iset[j]); for (int k = 1; k <= dsupps.Length(); k++) { // This will be the utility difference between the // payoff resulting from the profile and deviation to // the strategy for pl specified by dsupp[k] gPoly next_poly(&BehavStratSpace, &Lex); for (int n = 1; n <= terminal_nodes.Length(); n++) { gPoly node_prob(&BehavStratSpace, (double)1.0, &Lex); if (NashNodeProbabilityPoly(p_solution, node_prob, BehavStratSpace, Lex, dsupps[k], var_index, terminal_nodes[n], p_solution.GetGame()->GetPlayer(pl), isets_for_pl[i], acts_for_iset[j])) { if (terminal_nodes[n]->GetOutcome()) { node_prob *= (double) terminal_nodes[n]->GetOutcome()->GetPayoff(pl); } next_poly += node_prob; } } answer += -next_poly + (double) p_solution.GetPayoff(pl); } } } } } return answer; } static gPolyList ExtendsToNashIneqs(const Gambit::MixedBehavProfile &p_solution, const gSpace &BehavStratSpace, const term_order &Lex, const Gambit::BehavSupport &little_supp, const Gambit::BehavSupport &big_supp, const Gambit::List > &var_index) { gPolyList answer(&BehavStratSpace, &Lex); answer += ActionProbsSumToOneIneqs(p_solution, BehavStratSpace, Lex, big_supp, var_index); answer += NashExpectedPayoffDiffPolys(p_solution, BehavStratSpace, Lex, little_supp, big_supp, var_index); return answer; } bool algExtendsToNash::ExtendsToNash(const Gambit::MixedBehavProfile &p_solution, const Gambit::BehavSupport &little_supp, const Gambit::BehavSupport &big_supp) { // This asks whether there is a Nash extension of the Gambit::MixedBehavProfile to // all information sets at which the behavioral probabilities are not // specified. The assumption is that the support has active actions // at infosets at which the behavioral probabilities are defined, and // no others. Also, the BehavSol is assumed to be already a Nash // equilibrium for the truncated game obtained by eliminating stuff // outside little_supp. // First we compute the number of variables, and indexing information int num_vars(0); Gambit::List > var_index; int pl; for (pl = 1; pl <= p_solution.GetGame()->NumPlayers(); pl++) { Gambit::List list_for_pl; for (int i = 1; i <= p_solution.GetGame()->GetPlayer(pl)->NumInfosets(); i++) { list_for_pl.Append(num_vars); if ( !big_supp.HasActiveActionAt(p_solution.GetGame()->GetPlayer(pl)->GetInfoset(i)) ) { num_vars += p_solution.GetGame()->GetPlayer(pl)->GetInfoset(i)->NumActions() - 1; } } var_index.Append(list_for_pl); } // We establish the space gSpace BehavStratSpace(num_vars); ORD_PTR ptr = &lex; term_order Lex(&BehavStratSpace, ptr); num_vars = BehavStratSpace.Dmnsn(); gPolyList inequalities = ExtendsToNashIneqs(p_solution, BehavStratSpace, Lex, little_supp, big_supp, var_index); // set up the rectangle of search Gambit::Vector bottoms(num_vars), tops(num_vars); bottoms = (double)0; tops = (double)1; gRectangle Cube(bottoms, tops); // Set up the test and do it IneqSolv extension_tester(inequalities); Gambit::Vector sample(num_vars); bool answer = extension_tester.ASolutionExists(Cube,sample); // assert (answer == m_profile->ExtendsToNash(little_supp, big_supp, m_status)); return answer; } //========================================================================= // class algExtendsToAgentNash //========================================================================= static bool ANFNodeProbabilityPoly(const Gambit::MixedBehavProfile &p_solution, gPoly & node_prob, const gSpace &BehavStratSpace, const term_order &Lex, const Gambit::BehavSupport &big_supp, const Gambit::List > &var_index, Gambit::GameNode tempnode, const int &pl, const int &i, const int &j) { while (tempnode != p_solution.GetGame()->GetRoot()) { Gambit::GameAction last_action = tempnode->GetPriorAction(); Gambit::GameInfoset last_infoset = last_action->GetInfoset(); if (last_infoset->IsChanceInfoset()) node_prob *= (double) last_infoset->GetActionProb(last_action->GetNumber()); else if (big_supp.HasActiveActionAt(last_infoset)) { if (last_infoset == p_solution.GetGame()->GetPlayer(pl)->GetInfoset(i)) { if (j != last_action->GetNumber()) return false; } else if (big_supp.Contains(last_action)) node_prob *= (double) p_solution.GetActionProb(last_action); else return false; } else { int initial_var_no = var_index[last_infoset->GetPlayer()->GetNumber()][last_infoset->GetNumber()]; if (last_action->GetNumber() < last_infoset->NumActions()){ int varno = initial_var_no + last_action->GetNumber(); node_prob *= gPoly(&BehavStratSpace, varno, 1, &Lex); } else { gPoly factor(&BehavStratSpace, (double)1.0, &Lex); int k; for (k = 1; k < last_infoset->NumActions(); k++) factor -= gPoly(&BehavStratSpace, initial_var_no + k, 1, &Lex); node_prob *= factor; } } tempnode = tempnode->GetParent(); } return true; } static gPolyList ANFExpectedPayoffDiffPolys(const Gambit::MixedBehavProfile &p_solution, const gSpace &BehavStratSpace, const term_order &Lex, const Gambit::BehavSupport &little_supp, const Gambit::BehavSupport &big_supp, const Gambit::List > &var_index) { gPolyList answer(&BehavStratSpace, &Lex); Gambit::List terminal_nodes = TerminalNodes(p_solution.GetGame()); for (int pl = 1; pl <= p_solution.GetGame()->NumPlayers(); pl++) for (int i = 1; i <= p_solution.GetGame()->GetPlayer(pl)->NumInfosets(); i++) { Gambit::GameInfoset infoset = p_solution.GetGame()->GetPlayer(pl)->GetInfoset(i); if (little_supp.MayReach(infoset)) for (int j = 1; j <= infoset->NumActions(); j++) if (!little_supp.Contains(infoset->GetAction(j))) { // This will be the utility difference between the // payoff resulting from the profile and deviation to // action j gPoly next_poly(&BehavStratSpace, &Lex); for (int n = 1; n <= terminal_nodes.Length(); n++) { gPoly node_prob(&BehavStratSpace, (double)1.0, &Lex); if (ANFNodeProbabilityPoly(p_solution, node_prob, BehavStratSpace, Lex, big_supp, var_index, terminal_nodes[n], pl,i,j)) { if (terminal_nodes[n]->GetOutcome()) { node_prob *= (double) terminal_nodes[n]->GetOutcome()->GetPayoff(pl); } next_poly += node_prob; } } answer += -next_poly + (double) p_solution.GetPayoff(pl); } } return answer; } static gPolyList ExtendsToANFNashIneqs(const Gambit::MixedBehavProfile &p_solution, const gSpace &BehavStratSpace, const term_order &Lex, const Gambit::BehavSupport &little_supp, const Gambit::BehavSupport &big_supp, const Gambit::List > &var_index) { gPolyList answer(&BehavStratSpace, &Lex); answer += ActionProbsSumToOneIneqs(p_solution, BehavStratSpace, Lex, big_supp, var_index); answer += ANFExpectedPayoffDiffPolys(p_solution, BehavStratSpace, Lex, little_supp, big_supp, var_index); return answer; } bool algExtendsToAgentNash::ExtendsToAgentNash(const Gambit::MixedBehavProfile &p_solution, const Gambit::BehavSupport &little_supp, const Gambit::BehavSupport &big_supp) { // This asks whether there is an ANF Nash extension of the Gambit::MixedBehavProfile to // all information sets at which the behavioral probabilities are not // specified. The assumption is that the support has active actions // at infosets at which the behavioral probabilities are defined, and // no others. // First we compute the number of variables, and indexing information int num_vars(0); Gambit::List > var_index; int pl; for (pl = 1; pl <= p_solution.GetGame()->NumPlayers(); pl++) { Gambit::List list_for_pl; for (int i = 1; i <= p_solution.GetGame()->GetPlayer(pl)->NumInfosets(); i++) { list_for_pl.Append(num_vars); if ( !big_supp.HasActiveActionAt(p_solution.GetGame()->GetPlayer(pl)->GetInfoset(i)) ) { num_vars += p_solution.GetGame()->GetPlayer(pl)->GetInfoset(i)->NumActions() - 1; } } var_index.Append(list_for_pl); } // We establish the space gSpace BehavStratSpace(num_vars); ORD_PTR ptr = &lex; term_order Lex(&BehavStratSpace, ptr); num_vars = BehavStratSpace.Dmnsn(); gPolyList inequalities = ExtendsToANFNashIneqs(p_solution, BehavStratSpace, Lex, little_supp, big_supp, var_index); // set up the rectangle of search Gambit::Vector bottoms(num_vars), tops(num_vars); bottoms = (double)0; tops = (double)1; gRectangle Cube(bottoms, tops); // Set up the test and do it IneqSolv extension_tester(inequalities); Gambit::Vector sample(num_vars); // Temporarily, we check the old set up vs. the new bool ANFanswer = extension_tester.ASolutionExists(Cube,sample); // assert (ANFanswer == m_profile->ExtendsToANFNash(little_supp, // big_supp, // m_status)); /* bool NASHanswer = m_profile->ExtendsToNash(Support(),Support(),m_status); //DEBUG if (ANFanswer && !NASHanswer) gout << "The following should be extendable to an ANF Nash, but not to a Nash:\n" << *m_profile << "\n\n"; if (NASHanswer && !ANFanswer) gout << "ERROR: said to be extendable to a Nash, but not to an ANF Nash:\n" << *m_profile << "\n\n"; */ return ANFanswer; } gambit-0.2010.09.01/src/tools/enumpoly/behavextend.h0000644000076500007650000000271311435216101016702 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/behavextend.h // Algorithms for extending behavior profiles to Nash equilibria // // 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 BEHAVEXTEND_H #define BEHAVEXTEND_H #include "libgambit/libgambit.h" class algExtendsToNash { public: bool ExtendsToNash(const Gambit::MixedBehavProfile &p_solution, const Gambit::BehavSupport &p_littleSupport, const Gambit::BehavSupport &p_bigSupport); }; class algExtendsToAgentNash { public: bool ExtendsToAgentNash(const Gambit::MixedBehavProfile &p_solution, const Gambit::BehavSupport &p_littleSupport, const Gambit::BehavSupport &p_bigSupport); }; #endif // BEHAVEXTEND_H gambit-0.2010.09.01/src/tools/enumpoly/complex.cc0000644000076500007650000001175311435216101016216 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/complex.cc // Implementation of a complex number class // // 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. // #if defined(__GNUG__) && !defined(__APPLE_CC__) #pragma implementation #endif #include #include #include #include #include #include #include "libgambit/libgambit.h" #include "complex.h" //-------------------------------------------------------------------------- // class: gComplex //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // constructors and a destructor //-------------------------------------------------------------------------- gComplex::gComplex() : re(0), im(0) {} gComplex::gComplex(const double& x, const double& y) : re(x), im(y) {} gComplex::gComplex(const gComplex& y) : re(y.re), im(y.im) {} gComplex::gComplex(const int& n) : re(n), im(0) {} gComplex::gComplex(const long& n) : re(n), im(0) {} gComplex::~gComplex() {} //-------------------------------------------------------------------------- // operators //-------------------------------------------------------------------------- double gComplex::RealPart() const { return re; } double gComplex::ImaginaryPart() const { return im; } gComplex& gComplex::operator = (const gComplex& y) { if (this == &y) return *this; re = y.re; im = y.im; return *this; } bool gComplex::operator == (const gComplex& y) const { if (re == y.re && im == y.im) return true; else return false; } bool gComplex::operator != (const gComplex& y) const { return !(*this == y); } void gComplex::operator += (const gComplex& y) { *this = gComplex(re + y.re,im + y.im); } void gComplex::operator -= (const gComplex& y) { *this = gComplex(re - y.re,im - y.im); } void gComplex::operator *= (const gComplex& y) { *this = gComplex(re*y.re - im*y.im,re*y.im + im*y.re); } void gComplex::operator /= (const gComplex& y) { if (y == (gComplex)0) error("Attempt to divide by 0."); *this = gComplex((re*y.re + im*y.im)/(y.re*y.re + y.im*y.im), (- re*y.im + im*y.re)/(y.re*y.re + y.im*y.im)); } gComplex gComplex::operator + (const gComplex& y) const { return gComplex(re + y.re,im + y.im); } gComplex gComplex::operator - (const gComplex& y) const { return gComplex(re - y.re,im - y.im); } gComplex gComplex::operator * (const gComplex& y) const { return gComplex(re*y.re - im*y.im,re*y.im + im*y.re); } gComplex gComplex::operator / (const gComplex& y) const { if (y == (gComplex)0) error("Attempt to divide by 0."); return gComplex((re*y.re + im*y.im)/(y.re*y.re + y.im*y.im), (- re*y.im + im*y.re)/(y.re*y.re + y.im*y.im)); } gComplex gComplex::operator - () const { return gComplex(-re,-im); } //-------------------------------------------------------------------------- // errors //-------------------------------------------------------------------------- void gComplex::error(const char* msg) const { // gerr << "gComplex class error: " << msg << '\n'; assert(0); } // FUNCTIONS OUTSIDE THE CLASS double fabs(const gComplex& x) { return sqrt(x.re*x.re + x.im*x.im); } gComplex sqr(const gComplex& x) { return x*x; } gComplex pow(const gComplex& x, const long y) { if (y < 0) { assert (x != (gComplex)0); gComplex x1((gComplex)1/x); return pow(x1,-y); } else if (y == 0) return gComplex(1); else if (y == 1) return x; else { gComplex sqrt_of_answer = pow(x,y/2); gComplex answer = sqrt_of_answer * sqrt_of_answer; if (y % 2 == 1) answer *= x; return answer; } } std::string ToText(const gComplex /* d */) { // gout << "\nError: ToText(gComplex) must be defined for compilation,"; // gout << " but is not functional.\n"; exit(0); return ""; } // conversions from strings to numbers gComplex TOgComplex(const std::string & /* s */) { // gout << "\nError: TOgComplex must be defined for compilation,"; // gout << " but is not functional.\n"; exit(0); return gComplex(0, 0); } #include "libgambit/vector.imp" template class Gambit::Vector; gambit-0.2010.09.01/src/tools/enumpoly/complex.h0000644000076500007650000000473211435216101016057 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/complex.h // Declaration of a complex number class // // 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 _Complex_h #if defined(__GNUG__) && !defined(__APPLE_CC__) #pragma interface #endif #define _Complex_h 1 #include class gComplex { protected: double re; double im; public: // Constructors, and the destructor gComplex(); gComplex(const double&, const double&); gComplex(const gComplex&); gComplex(const int& n); gComplex(const long& n); ~gComplex(); // Operators double RealPart() const; double ImaginaryPart() const; gComplex& operator = (const gComplex& y); bool operator == (const gComplex& y) const; bool operator != (const gComplex& y) const; gComplex operator + (const gComplex& y) const; gComplex operator - (const gComplex& y) const; gComplex operator * (const gComplex& y) const; gComplex operator / (const gComplex& y) const; gComplex operator - () const; void operator += (const gComplex& y); void operator -= (const gComplex& y); void operator *= (const gComplex& y); void operator /= (const gComplex& y); // error reporting void error(const char* msg) const; // friends outside the class friend double fabs(const gComplex& x); friend gComplex sqr(const gComplex& x); friend gComplex pow(const gComplex& x, const long y); }; // The following are facilities that are required of all arithmetic types. // For other types they are given in gmisc.h class gString; gString ToString(gComplex); gComplex TOgComplex(const gString &); #endif gambit-0.2010.09.01/src/tools/enumpoly/efgensup.cc0000644000076500007650000004365511435216101016371 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/efgensup.cc // Enumerate undominated subsupports // // 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 #include "efgensup.h" // We build a series of functions of increasing complexity. The // final one, which is our goal, is the undominated support function. // We begin by simply enumerating all subsupports. void AllSubsupportsRECURSIVE(const Gambit::BehavSupport &s, Gambit::BehavSupport *sact, ActionCursorForSupport *c, Gambit::List &list) { list.Append(*sact); ActionCursorForSupport c_copy(*c); do { if ( sact->Contains(c_copy.GetAction()) ) { sact->RemoveAction(c_copy.GetAction()); AllSubsupportsRECURSIVE(s,sact,&c_copy,list); sact->AddAction(c_copy.GetAction()); } } while (c_copy.GoToNext()) ; } Gambit::List AllSubsupports(const Gambit::BehavSupport &S) { Gambit::List answer; Gambit::BehavSupport SAct(S); ActionCursorForSupport cursor(S); AllSubsupportsRECURSIVE(S, &SAct, &cursor, answer); return answer; } // Subsupports of a given support are _path equivalent_ if they // agree on every infoset that can be reached under either, hence both, // of them. The next routine outputs one support for each equivalence // class. It is not for use in solution routines, but is instead a // prototype of the eventual path enumerator, which will also perform // dominance elimination. void AllInequivalentSubsupportsRECURSIVE(const Gambit::BehavSupport &s, Gambit::BehavSupport *sact, ActionCursorForSupport *c, Gambit::List &list) { if (sact->HasActiveActionsAtActiveInfosetsAndNoOthers()) list.Append(*sact); ActionCursorForSupport c_copy(*c); do { if ( sact->Contains(c_copy.GetAction()) ) { Gambit::List deactivated_infosets; sact->RemoveAction(c_copy.GetAction(), deactivated_infosets); if (!c_copy.DeletionsViolateActiveCommitments(sact, &deactivated_infosets)) AllInequivalentSubsupportsRECURSIVE(s,sact,&c_copy,list); sact->AddAction(c_copy.GetAction()); } } while (c_copy.GoToNext()) ; } Gambit::List AllInequivalentSubsupports(const Gambit::BehavSupport &S) { Gambit::List answer; Gambit::BehavSupport SAct(S); ActionCursorForSupport cursor(S); AllInequivalentSubsupportsRECURSIVE(S, &SAct, &cursor, answer); return answer; } void AllUndominatedSubsupportsRECURSIVE(const Gambit::BehavSupport &s, Gambit::BehavSupport *sact, ActionCursorForSupport *c, bool strong, bool conditional, Gambit::List &list) { bool abort = false; bool no_deletions = true; bool check_domination = false; if (sact->HasActiveActionsAtActiveInfosets()) check_domination = true; Gambit::List deletion_list; ActionCursorForSupport scanner(s); // First we collect all the actions that can be deleted. do { Gambit::GameAction this_action = scanner.GetAction(); bool delete_this_action = false; if ( sact->Contains(this_action) ) if ( !sact->IsActive(this_action->GetInfoset()) ) delete_this_action = true; else if (check_domination) if (sact->IsDominated(this_action,strong,conditional) ) delete_this_action = true; if (delete_this_action) { no_deletions = false; if (c->IsSubsequentTo(this_action)) abort = true; else deletion_list.Append(this_action); } } while (!abort && scanner.GoToNext()); // Now we delete them, recurse, then restore if (!abort && !no_deletions) { Gambit::List actual_deletions; for (int i = 1; !abort && i <= deletion_list.Length(); i++) { actual_deletions.Append(deletion_list[i]); Gambit::List deactivated_infosets; sact->RemoveAction(deletion_list[i], deactivated_infosets); if (c->DeletionsViolateActiveCommitments(sact,&deactivated_infosets)) abort = true; } if (!abort) AllUndominatedSubsupportsRECURSIVE(s, sact, c, strong, conditional, list); for (int i = 1; i <= actual_deletions.Length(); i++) sact->AddAction(actual_deletions[i]); } // If there are no deletions, we ask if it is consistent, then recurse. if (!abort && no_deletions) { if (sact->HasActiveActionsAtActiveInfosetsAndNoOthers()) list.Append(*sact); ActionCursorForSupport c_copy(*c); do { if ( sact->Contains(c_copy.GetAction()) ) { Gambit::List deactivated_infosets; sact->RemoveAction(c_copy.GetAction(), deactivated_infosets); if (!c_copy.DeletionsViolateActiveCommitments(sact, &deactivated_infosets)) AllUndominatedSubsupportsRECURSIVE(s, sact, &c_copy, strong, conditional, list); sact->AddAction(c_copy.GetAction()); } } while (c_copy.GoToNext()) ; } } Gambit::List AllUndominatedSubsupports(const Gambit::BehavSupport &S, bool strong, bool conditional) { Gambit::List answer; Gambit::BehavSupport sact(S); ActionCursorForSupport cursor(S); AllUndominatedSubsupportsRECURSIVE(S, &sact, &cursor, strong, conditional, answer); return answer; } void PossibleNashSubsupportsRECURSIVE(const Gambit::BehavSupport &s, Gambit::BehavSupport *sact, ActionCursorForSupport *c, Gambit::List &list) { bool abort = false; bool add_support = true; bool check_domination = false; if (sact->HasActiveActionsAtActiveInfosets()) check_domination = true; Gambit::List deletion_list; ActionCursorForSupport scanner(s); do { Gambit::GameAction this_action = scanner.GetAction(); bool delete_this_action = false; if ( sact->Contains(this_action) ) if ( !sact->IsActive(this_action->GetInfoset()) ) delete_this_action = true; else if (check_domination) if ( sact->IsDominated(this_action,true,true) || sact->IsDominated(this_action,true,false) ) { add_support = false; if ( c->InfosetGuaranteedActiveByPriorCommitments(sact, this_action->GetInfoset()) ) delete_this_action = true; } if (delete_this_action) { if (c->IsSubsequentTo(this_action)) abort = true; else deletion_list.Append(this_action); } } while (!abort && scanner.GoToNext()); std::cout << "length of deletion list = " << deletion_list.Length() << std::endl; if (!abort) { Gambit::List actual_deletions; for (int i = 1; !abort && i <= deletion_list.Length(); i++) { Gambit::List deactivated_infosets; sact->RemoveAction(deletion_list[i], deactivated_infosets); if (c->DeletionsViolateActiveCommitments(sact,&deactivated_infosets)) { abort = true; } actual_deletions.Append(deletion_list[i]); } if (!abort && deletion_list.Length() > 0) PossibleNashSubsupportsRECURSIVE(s,sact,c,list); for (int i = 1; i <= actual_deletions.Length(); i++) { sact->AddAction(actual_deletions[i]); } } if (!abort && deletion_list.Length() == 0) { if (add_support && sact->HasActiveActionsAtActiveInfosetsAndNoOthers()) list.Append(*sact); ActionCursorForSupport c_copy(*c); do { if ( sact->Contains(c_copy.GetAction()) ) { Gambit::List deactivated_infosets; sact->RemoveAction(c_copy.GetAction(), deactivated_infosets); if (!c_copy.DeletionsViolateActiveCommitments(sact, &deactivated_infosets)) PossibleNashSubsupportsRECURSIVE(s,sact,&c_copy,list); sact->AddAction(c_copy.GetAction()); } } while (c_copy.GoToNext()) ; } } Gambit::List SortSupportsBySize(Gambit::List &list) { Gambit::Array sizes(list.Length()); for (int i = 1; i <= list.Length(); i++) sizes[i] = list[i].NumDegreesOfFreedom(); Gambit::Array listproxy(list.Length()); for (int i = 1; i <= list.Length(); i++) listproxy[i] = i; int maxsize(0); for (int i = 1; i <= list.Length(); i++) if (sizes[i] > maxsize) maxsize = sizes[i]; int cursor(1); for (int j = 0; j < maxsize; j++) { int scanner(list.Length()); while (cursor < scanner) if (sizes[scanner] != j) scanner--; else { while (sizes[cursor] == j) cursor++; if (cursor < scanner) { int tempindex = listproxy[cursor]; listproxy[cursor] = listproxy[scanner]; listproxy[scanner] = tempindex; int tempsize = sizes[cursor]; sizes[cursor] = sizes[scanner]; sizes[scanner] = tempsize; cursor++; } } } Gambit::List answer; for (int i = 1; i <= list.Length(); i++) answer.Append(list[listproxy[i]]); return answer; } namespace { // to keep the recursive function private using namespace Gambit; void PrintSupport(std::ostream &p_stream, const std::string &p_label, const Gambit::BehavSupport &p_support) { p_stream << p_label; for (int pl = 1; pl <= p_support.GetGame()->NumPlayers(); pl++) { GamePlayer player = p_support.GetGame()->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); p_stream << ","; for (int act = 1; act <= infoset->NumActions(); act++) { if (p_support.Contains(infoset->GetAction(act))) { p_stream << "1"; } else { p_stream << "0"; } } } } p_stream << std::endl; } void PossibleNashSubsupports(const Gambit::BehavSupport &p_support, const ActionCursorForSupport &p_cursor, Gambit::List &p_list) { ActionCursorForSupport copy(p_cursor); if (!copy.GoToNext()) { if (p_support.HasActiveActionsAtActiveInfosetsAndNoOthers()) { p_list.Append(p_support); } Gambit::BehavSupport copySupport(p_support); copySupport.RemoveAction(p_cursor.GetAction()); if (copySupport.HasActiveActionsAtActiveInfosetsAndNoOthers()) { p_list.Append(copySupport); } return; } PossibleNashSubsupports(p_support, copy, p_list); Gambit::BehavSupport copySupport(p_support); copySupport.RemoveAction(p_cursor.GetAction()); PossibleNashSubsupports(copySupport, copy, p_list); } } // // This is a naive version of the real thing. The original one // (see below, commented out) no longer works after underlying API // changes. I suspect the problem is that the behavior support class // was hacked to make this work, and recent refactorings have undone // the hacks it depended on. So, for now, we do a really simple // implementation that works (but may be inefficient), and we will // go from there later. // Gambit::List PossibleNashSubsupports(const Gambit::BehavSupport &p_support) { ActionCursorForSupport cursor(p_support); Gambit::List supports; Gambit::BehavSupport support(p_support); PossibleNashSubsupports(support, cursor, supports); return supports; } /* Gambit::List PossibleNashSubsupports(const Gambit::BehavSupport &S) { Gambit::List answer; Gambit::BehavSupport sact(S); ActionCursorForSupport cursor(S); PossibleNashSubsupportsRECURSIVE(S, &sact, &cursor, answer); // At this point answer has all consistent subsupports without // any strong dominations. We now edit the list, removing all // subsupports that exhibit weak dominations, and we also eliminate // subsupports exhibiting domination by currently inactive actions. for (int i = answer.Length(); i >= 1; i--) { Gambit::BehavSupport current(answer[i]); ActionCursorForSupport crsr(S); bool remove = false; do { Gambit::GameAction act = crsr.GetAction(); if (current.Contains(act)) for (int j = 1; j <= act->GetInfoset()->NumActions(); j++) { Gambit::GameAction other_act = act->GetInfoset()->GetAction(j); if (other_act != act) if (current.Contains(other_act)) { if (current.Dominates(other_act,act,false,true) || current.Dominates(other_act,act,false,false)) remove = true; } else { current.AddAction(other_act); if (current.HasActiveActionsAtActiveInfosetsAndNoOthers()) if (current.Dominates(other_act,act,false,true) || current.Dominates(other_act,act,false,false)) { remove = true; } current.RemoveAction(other_act); } } } while (crsr.GoToNext() && !remove); if (remove) answer.Remove(i); } return SortSupportsBySize(answer); } */ //---------------------------------------------------- // ActionCursorForSupport // --------------------------------------------------- ActionCursorForSupport::ActionCursorForSupport(const Gambit::BehavSupport &S) : support(S), pl(1), iset(1), act(1) { Gambit::Game efg = S.GetGame(); // Make sure that (pl,iset) points to a valid information set: // when solving by subgames, some players may not have any information // sets at all. for (pl = 1; pl <= efg->NumPlayers(); pl++) { if (efg->GetPlayer(pl)->NumInfosets() > 0) { for (iset = 1; iset <= efg->GetPlayer(pl)->NumInfosets(); iset++) { if (S.NumActions(pl, iset) > 0) { return; } } } } } ActionCursorForSupport::ActionCursorForSupport( const ActionCursorForSupport &ac) : support(ac.support), pl(ac.pl), iset(ac.iset), act(ac.act) {} ActionCursorForSupport::~ActionCursorForSupport() {} ActionCursorForSupport& ActionCursorForSupport::operator=(const ActionCursorForSupport &rhs) { if (this != &rhs) { support = rhs.support; pl = rhs.pl; iset = rhs.iset; act = rhs.act; } return *this; } bool ActionCursorForSupport::operator==(const ActionCursorForSupport &rhs) const { if (support != rhs.support || pl != rhs.pl || iset != rhs.iset || act != rhs.act) return false; return true; } bool ActionCursorForSupport::operator!=(const ActionCursorForSupport &rhs) const { return (!(*this==rhs)); } bool ActionCursorForSupport::GoToNext() { if (act != support.NumActions(pl,iset)) { act++; return true; } int temppl(pl); int tempiset(iset); tempiset ++; while (temppl <= support.GetGame()->NumPlayers()) { while (tempiset <= support.GetGame()->GetPlayer(temppl)->NumInfosets()) { if (support.NumActions(temppl,tempiset) > 0) { pl = temppl; iset = tempiset; act = 1; return true; } else tempiset++; } tempiset = 1; temppl++; } return false; } Gambit::GameAction ActionCursorForSupport::GetAction() const { return support.GetAction(pl, iset, act); } int ActionCursorForSupport::ActionIndex() const { return act; } Gambit::GameInfoset ActionCursorForSupport::GetInfoset() const { return support.GetGame()->GetPlayer(pl)->GetInfoset(iset); } int ActionCursorForSupport::InfosetIndex() const { return iset; } Gambit::GamePlayer ActionCursorForSupport::GetPlayer() const { return support.GetGame()->GetPlayer(pl); } int ActionCursorForSupport::PlayerIndex() const { return pl; } bool ActionCursorForSupport::IsLast() const { if (pl == support.GetGame()->NumPlayers()) if (iset == support.GetGame()->GetPlayer(pl)->NumInfosets()) if (act == support.NumActions(pl,iset)) return true; return false; } bool ActionCursorForSupport::IsSubsequentTo(const Gambit::GameAction &a) const { if (pl > a->GetInfoset()->GetPlayer()->GetNumber()) return true; else if (pl < a->GetInfoset()->GetPlayer()->GetNumber()) return false; else if (iset > a->GetInfoset()->GetNumber()) return true; else if (iset < a->GetInfoset()->GetNumber()) return false; else if (act > a->GetNumber()) return true; else return false; } bool ActionCursorForSupport:: DeletionsViolateActiveCommitments(const Gambit::BehavSupport *S, const Gambit::List *infosetlist) { for (int i = 1; i <= infosetlist->Length(); i++) { Gambit::GameInfoset infoset = (*infosetlist)[i]; if (infoset->GetPlayer()->GetNumber() < PlayerIndex() || ( infoset->GetPlayer()->GetNumber() == PlayerIndex() && infoset->GetNumber() < InfosetIndex()) ) if (S->NumActions(infoset->GetPlayer()->GetNumber(), infoset->GetNumber()) > 0) return true; if (infoset->GetPlayer()->GetNumber() == PlayerIndex() && infoset->GetNumber() == InfosetIndex() ) for (int act = 1; act < ActionIndex(); act++) if ( S->Contains(infoset->GetAction(act))) return true; } return false; } bool ActionCursorForSupport:: InfosetGuaranteedActiveByPriorCommitments(const Gambit::BehavSupport *S, const Gambit::GameInfoset &infoset) { Gambit::List members; for (int i = 1; i <= infoset->NumMembers(); i++) { members.Append(infoset->GetMember(i)); } for (int i = 1; i <= members.Length(); i++) { Gambit::GameNode current = members[i]; if ( current == S->GetGame()->GetRoot() ) return true; else while ( S->Contains(current->GetPriorAction()) && IsSubsequentTo(current->GetPriorAction()) ) { current = current->GetParent(); if ( current == S->GetGame()->GetRoot() ) return true; } } return false; } gambit-0.2010.09.01/src/tools/enumpoly/efgensup.h0000644000076500007650000001207011435216101016216 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/efgensup.h // Enumerate undominated subsupports // // 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 "libgambit/libgambit.h" class ActionCursorForSupport; // We build a series of functions of increasing complexity. The // final one, which is our goal, is the undominated support function. // We begin by simply enumerating all subsupports. void AllSubsupportsRECURSIVE(const Gambit::BehavSupport &s, Gambit::BehavSupport *sact, ActionCursorForSupport *c, Gambit::List &list); Gambit::List AllSubsupports(const Gambit::BehavSupport &S); // Subsupports of a given support are _path equivalent_ if they // agree on every infoset that can be reached under either, hence both, // of them. The next routine outputs one support for each equivalence // class by outputting only those subsupports with _no_ active // actions at each unreached infoset. void AllInequivalentSubsupportsRECURSIVE(const Gambit::BehavSupport &s, Gambit::BehavSupport *sact, ActionCursorForSupport *c, Gambit::List &list); Gambit::List AllInequivalentSubsupports(const Gambit::BehavSupport &S); // The following routines combine to return all supports that do not // exhibit particular type of domination. This was a prototype for // PossibleNashSubsupports, and displays the methods used there, // but it does NOT do exactly what is advertised with respect to // weak domination. This is because the recursion may eliminate // an action that is weakly dominated at some stage of the truncation // process, when, after more truncations, it might be no longer weakly // dominated, and thus part of an allowed subsupport. void AllUndominatedSubsupportsRECURSIVE(const Gambit::BehavSupport &s, Gambit::BehavSupport *sact, ActionCursorForSupport *c, bool strong, bool conditional, Gambit::List &list); Gambit::List AllUndominatedSubsupports(const Gambit::BehavSupport &S, bool strong, bool conditional); // The following two routines combine to produce all subsupports that could // host the path of a behavioral Nash equilibrium. These are subsupports // that have no action, at an active infoset, that is weakly dominated by // another active action, either in the conditional sense (for any active // node in the infoset) or the unconditional sense. In addition we // check for domination by actions that are inactive, but whose activation // would not activate any currently inactive infosets, so that the // subsupport resulting from activation is consistent, in the sense // of having active actions at all active infosets, and not at other // infosets. void PossibleNashSubsupportsRECURSIVE(const Gambit::BehavSupport &s, Gambit::BehavSupport *sact, ActionCursorForSupport *c, Gambit::List &list); Gambit::List SortSupportsBySize(Gambit::List &); Gambit::List PossibleNashSubsupports(const Gambit::BehavSupport &S); ///////////////// Utility Cursor Class ///////////////////// class ActionCursorForSupport { protected: Gambit::BehavSupport support; int pl; int iset; int act; public: //Constructors and dtor ActionCursorForSupport(const Gambit::BehavSupport &S); ActionCursorForSupport(const ActionCursorForSupport &a); ~ActionCursorForSupport(); // Operators ActionCursorForSupport &operator =(const ActionCursorForSupport &); bool operator==(const ActionCursorForSupport &) const; bool operator!=(const ActionCursorForSupport &) const; // Manipulation bool GoToNext(); // Information Gambit::GameAction GetAction() const; int ActionIndex() const; Gambit::GameInfoset GetInfoset() const; int InfosetIndex() const; Gambit::GamePlayer GetPlayer() const; int PlayerIndex() const; bool IsLast() const; bool IsSubsequentTo(const Gambit::GameAction &) const; // Special bool InfosetGuaranteedActiveByPriorCommitments(const Gambit::BehavSupport *, const Gambit::GameInfoset &); bool DeletionsViolateActiveCommitments(const Gambit::BehavSupport *, const Gambit::List *); }; gambit-0.2010.09.01/src/tools/enumpoly/efgpoly.cc0000644000076500007650000002631711436506767016243 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/efgpoly.cc // Enumerates all Nash equilibria of a game, via polynomial equations // // 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 #include #include "libgambit/libgambit.h" using namespace Gambit; #include "efgensup.h" #include "sfg.h" #include "gpoly.h" #include "gpolylst.h" #include "rectangl.h" #include "quiksolv.h" #include "behavextend.h" extern int g_numDecimals; extern bool g_verbose; // // A class to organize the data needed to build the polynomials // class ProblemData { public: const BehavSupport &support; Sfg SF; gSpace *Space; term_order *Lex; int nVars; Array > var; ProblemData(const BehavSupport &p_support) : support(p_support), SF(p_support) { } }; //======================================================================= // Constructing the equilibrium conditions //======================================================================= // The strategy is to develop the polynomial for each agent's expected // payoff as a function of the behavior strategies on the support, // eliminating the last last action probability for each information set. // The system is obtained by requiring that all of the partial // derivatives vanish, and that the sum of action probabilities at // each information set be less than one. gPoly ProbOfSequence(const ProblemData &p_data, int p, int seq) { gPoly equation(p_data.Space, p_data.Lex); Vector exps(p_data.nVars); int j = 0; int isetrow = p_data.SF.InfosetRowNumber(p,seq); int act = p_data.SF.ActionNumber(p,seq); int varno = p_data.var[p][seq]; GameInfoset infoset = p_data.SF.GetInfoset(p, seq); if(seq==1) { exps=0; exp_vect const_exp(p_data.Space,exps); gMono const_term(1.0, const_exp); gPoly new_term(p_data.Space,const_term,p_data.Lex); equation+=new_term; } else if(act const_term(1.0, const_exp); gPoly new_term(p_data.Space,const_term,p_data.Lex); equation+=new_term; } else { for(j=1;j GetPayoff(const ProblemData &p_data, int pl) { gIndexOdometer index(p_data.SF.NumSequences()); Rational pay; gPoly equation(p_data.Space, p_data.Lex); while (index.Turn()) { pay=p_data.SF.Payoff(index.CurrentIndices(),pl); if( pay != Rational(0)) { gPoly term(p_data.Space,(double) pay, p_data.Lex); int k; for(k=1;k<=p_data.support.GetGame()->NumPlayers();k++) term*=ProbOfSequence(p_data, k,(index.CurrentIndices())[k]); equation+=term; } } return equation; } gPolyList IndifferenceEquations(const ProblemData &p_data) { gPolyList equations(p_data.Space, p_data.Lex); int kk = 0; for (int pl = 1; pl <= p_data.SF.NumPlayers(); pl++) { gPoly payoff = GetPayoff(p_data, pl); int n_vars = p_data.SF.NumSequences(pl) - p_data.SF.NumInfosets(pl) - 1; for (int j = 1; j <= n_vars; j++) { equations += payoff.PartialDerivative(kk+j); } kk+=n_vars; } return equations; } gPolyList LastActionProbPositiveInequalities(const ProblemData &p_data) { gPolyList equations(p_data.Space, p_data.Lex); for (int i = 1; i <= p_data.SF.NumPlayers(); i++) for (int j = 2; j <= p_data.SF.NumSequences(i); j++) { int act_num = p_data.SF.ActionNumber(i,j); GameInfoset infoset = p_data.SF.GetInfoset(i, j); if ( act_num == p_data.support.NumActions(infoset) && act_num > 1 ) equations += ProbOfSequence(p_data, i,j); } return equations; } gPolyList NashOnSupportEquationsAndInequalities(const ProblemData &p_data) { gPolyList equations(p_data.Space, p_data.Lex); equations += IndifferenceEquations(p_data); equations += LastActionProbPositiveInequalities(p_data); return equations; } //======================================================================= // Mapping solution vectors to sequences //======================================================================= double NumProbOfSequence(const ProblemData &p_data, int p, int seq, const Vector &x) { int isetrow = p_data.SF.InfosetRowNumber(p,seq); int act = p_data.SF.ActionNumber(p,seq); int varno = p_data.var[p][seq]; GameInfoset infoset = p_data.SF.GetInfoset(p, seq); if (seq == 1) { return 1.0; } else if (act < p_data.support.NumActions(infoset)) { return x[varno]; } else { double value = 0.0; for (int j = 1; j < seq; j++) { if (p_data.SF.Constraints(p)(isetrow,j) == Rational(-1)) { value -= NumProbOfSequence(p_data, p, j, x); } else if (p_data.SF.Constraints(p)(isetrow,j) == Rational(1)) { value += NumProbOfSequence(p_data, p, j, x); } } return value; } } PVector SeqFormVectorFromSolFormVector(const ProblemData &p_data, const Vector &v) { PVector x(p_data.SF.NumSequences()); for (int i = 1; i <= p_data.support.GetGame()->NumPlayers(); i++) { for (int j = 1; j <= p_data.SF.NumSequences()[i]; j++) { x(i,j) = NumProbOfSequence(p_data, i, j, v); } } return x; } bool ExtendsToNash(const MixedBehavProfile &bs) { algExtendsToNash algorithm; return algorithm.ExtendsToNash(bs, BehavSupport(bs.GetGame()), BehavSupport(bs.GetGame())); } List > SolveSupport(const BehavSupport &p_support, bool &p_isSingular) { ProblemData data(p_support); data.nVars = (data.SF.TotalNumSequences() - data.SF.NumPlayerInfosets() - data.SF.NumPlayers()); data.Space = new gSpace(data.nVars); data.Lex = new term_order(data.Space, lex); int tnv = 0; data.var = p_support.GetGame()->NumPlayers(); for (int pl = 1; pl <= p_support.GetGame()->NumPlayers(); pl++) { data.var[pl] = Array(data.SF.NumSequences(pl)); data.var[pl][1] = 0; for (int seq = 2; seq <= data.SF.NumSequences(pl); seq++) { int act = data.SF.ActionNumber(pl, seq); GameInfoset infoset = data.SF.GetInfoset(pl, seq); if (act < p_support.NumActions(infoset)) { data.var[pl][seq] = ++tnv; } else { data.var[pl][seq] = 0; } } } gPolyList equations = NashOnSupportEquationsAndInequalities(data); // set up the rectangle of search Vector bottoms(data.nVars), tops(data.nVars); bottoms = (double) 0; tops = (double) 1; gRectangle Cube(bottoms, tops); QuikSolv quickie(equations); #ifdef UNUSED if(params.trace>0) { (*params.tracefile) << "\nThe equilibrium equations are \n" << quickie.UnderlyingEquations() ; } #endif // UNUSED // 2147483647 = 2^31-1 = MaxInt try { if(quickie.FindCertainNumberOfRoots(Cube,2147483647,0)) { #ifdef UNUSED if(params.trace>0) { (*params.tracefile) << "\nThe system has the following roots in [0,1]^" << num_vars << " :\n" << quickie.RootList(); } #endif // UNUSED } } catch (SingularMatrixException) { p_isSingular = true; } List > solutionlist = quickie.RootList(); List > solutions; for (int k = 1; k <= solutionlist.Length(); k++) { PVector y = SeqFormVectorFromSolFormVector(data, solutionlist[k]); MixedBehavProfile sol(data.SF.ToBehav(y)); if (ExtendsToNash(sol)) { solutions.Append(sol); } } delete data.Lex; delete data.Space; return solutions; } PVector SeqFormProbsFromSolVars(const ProblemData &p_data, const Vector &v) { PVector x(p_data.SF.NumSequences()); for(int pl=1;pl<=p_data.support.GetGame()->NumPlayers();pl++) for(int seq=1;seq<=p_data.SF.NumSequences()[pl];seq++) x(pl,seq) = NumProbOfSequence(p_data, pl,seq,v); return x; } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedBehavProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << "," << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } MixedBehavProfile ToFullSupport(const MixedBehavProfile &p_profile) { Game efg = p_profile.GetGame(); const BehavSupport &support = p_profile.GetSupport(); MixedBehavProfile fullProfile(efg); for (int i = 1; i <= fullProfile.Length(); fullProfile[i++] = 0.0); int index = 1; for (int pl = 1; pl <= efg->NumPlayers(); pl++) { GamePlayer player = efg->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); for (int act = 1; act <= infoset->NumActions(); act++) { if (support.Contains(infoset->GetAction(act))) { fullProfile(pl, iset, act) = p_profile[index++]; } } } } return fullProfile; } void PrintSupport(std::ostream &p_stream, const std::string &p_label, const BehavSupport &p_support) { p_stream << p_label; for (int pl = 1; pl <= p_support.GetGame()->NumPlayers(); pl++) { GamePlayer player = p_support.GetGame()->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); p_stream << ","; for (int act = 1; act <= infoset->NumActions(); act++) { if (p_support.Contains(infoset->GetAction(act))) { p_stream << "1"; } else { p_stream << "0"; } } } } p_stream << std::endl; } void SolveExtensive(const Game &p_game) { List supports = PossibleNashSubsupports(p_game); for (int i = 1; i <= supports.Length(); i++) { if (g_verbose) { PrintSupport(std::cout, "candidate", supports[i]); } bool isSingular = false; List > newsolns = SolveSupport(supports[i], isSingular); for (int j = 1; j <= newsolns.Length(); j++) { MixedBehavProfile fullProfile = ToFullSupport(newsolns[j]); if (fullProfile.GetLiapValue(true) < 1.0e-6) { PrintProfile(std::cout, "NE", fullProfile); } } if (isSingular && g_verbose) { PrintSupport(std::cout, "singular", supports[i]); } } } gambit-0.2010.09.01/src/tools/enumpoly/enumpoly.cc0000644000076500007650000000744011435216101016415 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/enumpoly.cc // Enumerates all Nash equilibria via support enumeration // // 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 #include #include #include "libgambit/libgambit.h" #include "nfghs.h" int g_numDecimals = 6; bool g_verbose = false; void PrintBanner(std::ostream &p_stream) { p_stream << "Compute Nash equilibria by solving polynomial systems\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "Heuristic search implementation Copyright (C) 2006, Litao Wei\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "With no options, reports all Nash equilibria found.\n\n"; std::cerr << "Options:\n"; std::cerr << " -d DECIMALS show equilibrium probabilities with DECIMALS digits\n"; std::cerr << " -h print this help message\n"; std::cerr << " -S use strategic game\n"; std::cerr << " -H use heuristic search method to optimize time\n"; std::cerr << " to find first equilibrium (strategic games only)\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; std::cerr << " -v verbose mode (shows supports investigated)\n"; std::cerr << " (default is only to show equilibria)\n"; exit(1); } extern void SolveStrategic(const Gambit::Game &); extern void SolveExtensive(const Gambit::Game &); int main(int argc, char *argv[]) { opterr = 0; bool quiet = false; bool useHeuristic = false, useStrategic = false; int c; while ((c = getopt(argc, argv, "d:hHSqv")) != -1) { switch (c) { case 'd': g_numDecimals = atoi(optarg); break; case 'h': PrintHelp(argv[0]); break; case 'H': useHeuristic = true; break; case 'S': useStrategic = true; break; case 'q': quiet = true; break; case 'v': g_verbose = true; break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Gambit::Game game = Gambit::ReadGame(std::cin); if (!game->IsTree() || useStrategic) { game->BuildComputedValues(); if (useHeuristic) { gbtNfgHs algorithm(0); algorithm.Solve(game); } else { SolveStrategic(game); } } else { SolveExtensive(game); } return 0; } catch (Gambit::InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } } gambit-0.2010.09.01/src/tools/enumpoly/gnarray.h0000644000076500007650000000327511435216101016054 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gnarray.h // Interface declaration for N-dimensional arrays // // 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 GNARRAY_H #define GNARRAY_H #include #include "libgambit/libgambit.h" // // Basic n-dimensional array // template class gNArray { protected: long storage_size; T *storage; Gambit::Array dim; public: gNArray(void); gNArray(const Gambit::Array &d); gNArray(const gNArray& a); ~gNArray(); gNArray &operator=(const gNArray &); /* not used for now T operator[](const Gambit::Vector &) const; T &operator[](const Gambit::Vector &); */ T operator[](const Gambit::Array &) const; T &operator[](const Gambit::Array &); const T &operator[](long l) const; T &operator[](long l); const Gambit::Array &Dimensionality(void) const; }; #endif // GNARRAY_H gambit-0.2010.09.01/src/tools/enumpoly/gnarray.imp0000644000076500007650000000762711435216101016417 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gnarray.imp // Implementation for N-dimensional arrays // // 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 #include "gnarray.h" template gNArray::gNArray(void) : storage_size(0), storage(0) { } template gNArray::gNArray(const Gambit::Array &d) : dim(d) { if (dim.Length() <= 0) { storage = 0; storage_size = 0; } else { assert(dim.First() == 1); storage_size = 1; int i; for (i = 1; i <= dim.Length(); i++) { assert(dim[i] >= 1); storage_size *= dim[i]; } storage = new T[storage_size]; for (i = 0; i < storage_size; storage[i++] = 0); } } template gNArray::gNArray(const gNArray &a) : storage_size(a.storage_size), dim(a.dim) { storage = (storage_size > 0) ? new T[storage_size] : 0; for (int i = 0; i < storage_size; i++) storage[i] = a.storage[i]; } template gNArray::~gNArray() { if (storage) delete [] storage; } template gNArray &gNArray::operator=(const gNArray &a) { if (this != &a) { if (storage) delete [] storage; dim = a.dim; storage_size = a.storage_size; storage = (storage_size > 0) ? new T[storage_size] : 0; for (int i = 0; i < storage_size; i++) storage[i] = a.storage[i]; } return *this; } /* template T gNArray::operator[](const Gambit::Vector &v) const { assert(dim.Length() > 0 && dim.Length() == v.Length()); int i,location,offset; for (i = 1, location = 0, offset = 1; i <= dim.Length(); i++) { assert(v[i] > 0 && v[i] <= dim[i]); location += (v[i] - 1) * offset; offset *= dim[i]; } return storage[location]; } template T &gNArray::operator[](const Gambit::Vector &v) { assert(dim.Length() > 0 && dim.Length() == v.Length()); int i, location, offset; for (i = 1, location = 0, offset = 1; i <= dim.Length(); i++) { assert(v[i] > 0 && v[i] <= dim[i]); location += (v[i] - 1) * offset; offset *= dim[i]; } return storage[location]; } */ template T gNArray::operator[](const Gambit::Array &v) const { assert(dim.Length() > 0 && dim.Length() == v.Length()); int i, location, offset; for (i = 1, location = 0, offset = 1; i <= dim.Length(); i++) { assert(v[i] > 0 && v[i] <= dim[i]); location += (v[i] - 1) * offset; offset *= dim[i]; } return storage[location]; } template T &gNArray::operator[](const Gambit::Array &v) { assert(dim.Length() > 0 && dim.Length() == v.Length()); int i, location, offset; for (i = 1, location = 0, offset = 1; i <= dim.Length(); i++) { assert(v[i] > 0 && v[i] <= dim[i]); location += (v[i] - 1) * offset; offset *= dim[i]; } return storage[location]; } template const T &gNArray::operator[](long l) const { assert(l >= 0 && l < storage_size); return storage[l]; } template T &gNArray::operator[](long l) { assert(l >= 0 && l < storage_size); return storage[l]; } template const Gambit::Array &gNArray::Dimensionality(void) const { return dim; } gambit-0.2010.09.01/src/tools/enumpoly/gpartltr.cc0000644000076500007650000000376411435216101016411 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpartltr.cc // Instantiations of tree of partials classes // // 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 "gpartltr.imp" template class TreeOfPartials; template class ListOfPartialTrees; //template class TreeOfPartials; //template class ListOfPartialTrees; //template class TreeOfPartials; //template gOutput &operator<<(gOutput &f, const TreeOfPartials &y); //template class Gambit::List >; //template gOutput &operator<<(gOutput &f, // const Gambit::List > &y); //template class Gambit::List > >; //template gOutput &operator<<(gOutput &f, // const Gambit::List > > &y); //template class Gambit::List > > >; //template class ListOfPartialTrees; //template gOutput &operator<<(gOutput &f, // const ListOfPartialTrees &y); #include "gtree.imp" //template class gTreeNode >; //template class gTree >; template class gTreeNode >; template class gTree >; gambit-0.2010.09.01/src/tools/enumpoly/gpartltr.h0000644000076500007650000001174411435216101016250 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpartltr.h // Interface to TreeOfPartials // // 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 GPARTLTR_H #define GPARTLTR_H #include "libgambit/libgambit.h" #include "gtree.h" #include "rectangl.h" #include "gpoly.h" #include "gpolylst.h" // **************************** // class TreeOfPartials // **************************** template class TreeOfPartials { private: gTree > PartialTree; /// Recursive Constructions and Computations /// void TreeOfPartialsRECURSIVE(gTree >&, gTreeNode >*) const; T MaximalNonconstantContributionRECURSIVE( const gTreeNode >*, const Gambit::Vector&, const Gambit::Vector&, Gambit::Vector&) const; T MaximalNonconstantDifferenceRECURSIVE( const gTreeNode >*, const gTreeNode >*, const Gambit::Vector&, const Gambit::Vector&, Gambit::Vector&) const; public: TreeOfPartials(const gPoly &); TreeOfPartials(const TreeOfPartials &); ~TreeOfPartials(); inline bool operator ==(const TreeOfPartials& rhs) const { return (PartialTree == rhs.PartialTree); } inline bool operator !=(const TreeOfPartials& rhs) const { return !(*this == rhs); } inline int Dmnsn() const { return RootNode()->GetData().Dmnsn(); } T EvaluateRootPoly(const Gambit::Vector& point) const; T MaximalNonconstantContribution(const Gambit::Vector&, const Gambit::Vector&) const; T MaximalNonconstantDifference(const TreeOfPartials&, const Gambit::Vector&, const Gambit::Vector&) const; inline gTreeNode >* RootNode() const { return PartialTree.RootNode(); } inline gPoly RootPoly() const { return RootNode()->GetData(); } T ValueOfRootPoly(const Gambit::Vector& point) const; T ValueOfPartialOfRootPoly(const int&, const Gambit::Vector&) const; Gambit::Vector VectorOfPartials(const Gambit::Vector&) const; bool PolyHasNoRootsIn(const gRectangle&) const; bool MultiaffinePolyHasNoRootsIn(const gRectangle&) const; bool PolyEverywhereNegativeIn(const gRectangle&) const; bool MultiaffinePolyEverywhereNegativeIn(const gRectangle&) const; //friend gOutput& operator << (gOutput& output, const TreeOfPartials& x); }; // ********************************* // class ListOfPartialTrees // ********************************* template class ListOfPartialTrees { private: Gambit::List > PartialTreeList; // Disabling this operator -- we don't want it called ListOfPartialTrees &operator=(const ListOfPartialTrees &); public: ListOfPartialTrees(const Gambit::List >&); ListOfPartialTrees(const gPolyList&); ListOfPartialTrees(const ListOfPartialTrees &); ~ListOfPartialTrees(); // operators bool operator == (const ListOfPartialTrees&) const; bool operator != (const ListOfPartialTrees&) const; inline const TreeOfPartials& operator[](const int& i) const { return PartialTreeList[i]; } // Information inline int Length() const { return PartialTreeList.Length(); } inline int Dmnsn() const { assert (Length() > 0); return PartialTreeList[1].Dmnsn(); } Gambit::Matrix DerivativeMatrix(const Gambit::Vector&) const; Gambit::Matrix DerivativeMatrix(const Gambit::Vector&, const int&) const; Gambit::SquareMatrix SquareDerivativeMatrix(const Gambit::Vector&) const; Gambit::Vector ValuesOfRootPolys(const Gambit::Vector&, const int&) const; T MaximalNonconstantDifference(const int&, const int&, const Gambit::Vector&, const Gambit::Vector&) const; //friend gOutput& operator << (gOutput& output, const ListOfPartialTrees& x); }; #endif // GPARTLTR_H gambit-0.2010.09.01/src/tools/enumpoly/gpartltr.imp0000644000076500007650000003240111435216101016577 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpartltr.imp // Implementation of TreeOfPartials // // 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 "gpartltr.h" //--------------------------------------------------------------- // class: TreeOfPartials //--------------------------------------------------------------- //--------------------------- // Constructors / Destructors //--------------------------- template TreeOfPartials::TreeOfPartials(const gPoly& given) : PartialTree(given) { TreeOfPartialsRECURSIVE(PartialTree, PartialTree.RootNode()); } //------------------------------------------------------------------------- // Recursive generation of all partial derivatives of the root polynomial //------------------------------------------------------------------------- template void TreeOfPartials::TreeOfPartialsRECURSIVE(gTree >& t, gTreeNode >* n) const { if (n->GetData().Degree() >= 1) { for (int i = 1; i <= n->GetData().Dmnsn(); i++) { t.InsertAt(n->GetData().PartialDerivative(i),n); TreeOfPartialsRECURSIVE(t,n->GetYoungest()); } } } template TreeOfPartials::TreeOfPartials(const TreeOfPartials& qs) : PartialTree(qs.PartialTree) { } template TreeOfPartials::~TreeOfPartials() { } template T TreeOfPartials::ValueOfPartialOfRootPoly(const int& coord, const Gambit::Vector& p) const { if (RootPoly().Degree() <= 0) return (T)0; else { int i = 1; gTreeNode >* node = RootNode()->GetEldest(); while (i < coord) { i++; node = node->GetNext(); } T answer = node->GetData().Evaluate(p); return answer; } } template Gambit::Vector TreeOfPartials::VectorOfPartials(const Gambit::Vector& point) const { Gambit::Vector answer(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) answer[i] = ValueOfPartialOfRootPoly(i,point); return answer; } template T TreeOfPartials::MaximalNonconstantContributionRECURSIVE( const gTreeNode >* n, const Gambit::Vector& p, const Gambit::Vector& halvesoflengths, Gambit::Vector& wrtos) const { T answer = (T)0; if (n->GetEldest() != NULL) { Gambit::List >*> children = PartialTree.Children(n); for (int i = 1; i <= children.Length(); i++) { wrtos[i]++; T increment = children[i]->GetData().Evaluate(p); if (increment < (T)0) increment = -increment; for (int j = 1; j <= p.Length(); j++) for (int k = 1; k <= wrtos[j]; k++) { increment *= halvesoflengths[j]; increment /= (T)k; } answer += increment; answer += MaximalNonconstantContributionRECURSIVE(children[i], p, halvesoflengths, wrtos); wrtos[i]--; } } return answer; } template T TreeOfPartials::MaximalNonconstantDifferenceRECURSIVE( const gTreeNode >* n1, const gTreeNode >* n2, const Gambit::Vector& p, const Gambit::Vector& halvesoflengths, Gambit::Vector& wrtos) const { T answer = (T)0; if (n1->GetEldest() != NULL && n2->GetEldest() != NULL) { Gambit::List >*> children1 = PartialTree.Children(n1); Gambit::List >*> children2 = PartialTree.Children(n2); for (int i = 1; i <= children1.Length(); i++) { wrtos[i]++; T increment = children1[i]->GetData().Evaluate(p) - children2[i]->GetData().Evaluate(p); if (increment < (T)0) increment = -increment; for (int j = 1; j <= p.Length(); j++) for (int k = 1; k <= wrtos[j]; k++) { increment *= halvesoflengths[j]; increment /= (T)k; } answer += increment; answer += MaximalNonconstantDifferenceRECURSIVE(children1[i], children2[i], p, halvesoflengths, wrtos); wrtos[i]--; } } else if (n1->GetEldest() != NULL && n2->GetEldest() == NULL) { Gambit::List >*> children1 = PartialTree.Children(n1); for (int i = 1; i <= children1.Length(); i++) { wrtos[i]++; T increment = children1[i]->GetData().Evaluate(p); if (increment < (T)0) increment = -increment; for (int j = 1; j <= p.Length(); j++) for (int k = 1; k <= wrtos[j]; k++) { increment *= halvesoflengths[j]; increment /= (T)k; } answer += increment; answer += MaximalNonconstantContributionRECURSIVE(children1[i], p, halvesoflengths, wrtos); wrtos[i]--; } } else if (n1->GetEldest() == NULL && n2->GetEldest() != NULL) { Gambit::List >*> children2 = PartialTree.Children(n2); for (int i = 1; i <= children2.Length(); i++) { wrtos[i]++; T increment = children2[i]->GetData().Evaluate(p); if (increment < (T)0) increment = -increment; for (int j = 1; j <= p.Length(); j++) for (int k = 1; k <= wrtos[j]; k++) { increment *= halvesoflengths[j]; increment /= (T)k; } answer += increment; answer += MaximalNonconstantContributionRECURSIVE(children2[i], p, halvesoflengths, wrtos); wrtos[i]--; } } return answer; } template T TreeOfPartials::MaximalNonconstantContribution(const Gambit::Vector& p, const Gambit::Vector& halvesoflengths) const { Gambit::Vector WithRespectTos(p.Length()); for (int i = 1; i <= p.Length(); i++) WithRespectTos[i] = 0; return MaximalNonconstantContributionRECURSIVE(RootNode(), p, halvesoflengths, WithRespectTos); } template T TreeOfPartials::MaximalNonconstantDifference(const TreeOfPartials& other, const Gambit::Vector& p, const Gambit::Vector& halvesoflengths) const { Gambit::Vector WithRespectTos(p.Length()); for (int i = 1; i <= p.Length(); i++) WithRespectTos[i] = 0; return MaximalNonconstantDifferenceRECURSIVE(other.RootNode(), RootNode(), p, halvesoflengths, WithRespectTos); } template T TreeOfPartials::EvaluateRootPoly(const Gambit::Vector& point) const { return RootNode()->GetData().Evaluate(point); } template T TreeOfPartials::ValueOfRootPoly(const Gambit::Vector& point) const { return RootPoly().Evaluate(point); } template bool TreeOfPartials::PolyHasNoRootsIn(const gRectangle& r) const { if (this->RootNode()->GetData().IsMultiaffine()) return MultiaffinePolyHasNoRootsIn(r); else { Gambit::Vector center = r.Center(); T constant = this->RootNode()->GetData().Evaluate(center); if (constant < (T)0) constant = - constant; Gambit::Vector HalvesOfSideLengths = r.SideLengths(); for (int k = 1; k <= Dmnsn(); k++) HalvesOfSideLengths[k] /= (T)2; T max = this->MaximalNonconstantContribution(center, HalvesOfSideLengths); if (max >= constant) return false; else return true; } } template bool TreeOfPartials::MultiaffinePolyHasNoRootsIn(const gRectangle& r) const { int sign; if (this->RootNode()->GetData().Evaluate(r.Center()) > (T)0) sign = 1; else sign = -1; Gambit::Array zeros(Dmnsn()); Gambit::Array ones(Dmnsn()); for (int j = 1; j <= Dmnsn(); j++) { zeros[j] = 0; if (this->RootNode()->GetData().DegreeOfVar(j) > 0) ones[j] = 1; //Equation_i_uses_var_j(index,j)) ones[j] = 1; else ones[j] = 0; } gIndexOdometer topbottoms(zeros,ones); while (topbottoms.Turn()) { Gambit::Vector point(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) if (topbottoms[i] == 0) point[i] = r.LowerBoundOfCoord(i); else point[i] = r.UpperBoundOfCoord(i); if ((T)sign * this->RootNode()->GetData().Evaluate(point) <= (T)0) return false; } return true; } template bool TreeOfPartials::MultiaffinePolyEverywhereNegativeIn( const gRectangle& r) const { if (Dmnsn() == 0) { Gambit::Vector point(Dmnsn()); if (this->RootNode()->GetData().Evaluate(point) >= (T)0) return false; else return true; } Gambit::Array zeros(Dmnsn()); Gambit::Array ones(Dmnsn()); for (int j = 1; j <= Dmnsn(); j++) { zeros[j] = 0; if (this->RootNode()->GetData().DegreeOfVar(j) > 0) ones[j] = 1; else ones[j] = 0; } gIndexOdometer topbottoms(zeros,ones); while (topbottoms.Turn()) { Gambit::Vector point(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) if (topbottoms[i] == 0) point[i] = r.LowerBoundOfCoord(i); else point[i] = r.UpperBoundOfCoord(i); if (this->RootNode()->GetData().Evaluate(point) >= (T)0) return false; } return true; } template bool TreeOfPartials ::PolyEverywhereNegativeIn(const gRectangle& r) const { if (this->RootNode()->GetData().IsMultiaffine()) return MultiaffinePolyEverywhereNegativeIn(r); else { Gambit::Vector center = r.Center(); T constant = this->RootNode()->GetData().Evaluate(center); if (constant >= (T)0) return false; Gambit::Vector HalvesOfSideLengths = r.SideLengths(); for (int k = 1; k <= Dmnsn(); k++) HalvesOfSideLengths[k] /= (T)2; T max = this->MaximalNonconstantContribution(center, HalvesOfSideLengths); if (max + constant >= (T)0) return false; else return true; } } //--------------------------------------------------------------- // class: ListOfPartialTrees //--------------------------------------------------------------- //--------------------------- // Constructors / Destructors //--------------------------- template ListOfPartialTrees::ListOfPartialTrees(const Gambit::List >& given) : PartialTreeList() { for (int i = 1; i <= given.Length(); i++) PartialTreeList.Append(TreeOfPartials(given[i])); } template ListOfPartialTrees::ListOfPartialTrees(const gPolyList& given) : PartialTreeList() { for (int i = 1; i <= given.Length(); i++) PartialTreeList.Append(TreeOfPartials(given[i])); } template ListOfPartialTrees::ListOfPartialTrees(const ListOfPartialTrees& qs) : PartialTreeList(qs.PartialTreeList) { } template ListOfPartialTrees::~ListOfPartialTrees() { } template bool ListOfPartialTrees::operator ==(const ListOfPartialTrees& rhs) const { if (Length() != rhs.Length()) return false; for (int i = 1; i <= Length(); i++) if ((*this)[i] != rhs[i]) return false; return true; } template bool ListOfPartialTrees::operator !=(const ListOfPartialTrees& rhs) const { return !(*this == rhs); } template Gambit::Matrix ListOfPartialTrees::DerivativeMatrix(const Gambit::Vector& p) const { Gambit::Matrix answer(Length(),Dmnsn()); int i; for (i = 1; i <= Length(); i++) for (int j = 1; j <= Dmnsn(); j++) answer(i,j) = (*this)[i].ValueOfPartialOfRootPoly(j,p); return answer; } template Gambit::Matrix ListOfPartialTrees::DerivativeMatrix(const Gambit::Vector& p, const int& NoEquations) const { Gambit::Matrix answer(NoEquations,Dmnsn()); int i; for (i = 1; i <= NoEquations; i++) for (int j = 1; j <= Dmnsn(); j++) answer(i,j) = (*this)[i].ValueOfPartialOfRootPoly(j,p); return answer; } template Gambit::SquareMatrix ListOfPartialTrees::SquareDerivativeMatrix(const Gambit::Vector& p) const { assert (Length() >= Dmnsn()); Gambit::SquareMatrix answer(Dmnsn()); int i; for (i = 1; i <= Dmnsn(); i++) for (int j = 1; j <= Dmnsn(); j++) answer(i,j) = (*this)[i].ValueOfPartialOfRootPoly(j,p); return answer; } template Gambit::Vector ListOfPartialTrees::ValuesOfRootPolys(const Gambit::Vector& point, const int& NoEquations) const { Gambit::Vector answer(NoEquations); for (int i = 1; i <= NoEquations; i++) answer[i] = PartialTreeList[i].EvaluateRootPoly(point); return answer; } template T ListOfPartialTrees::MaximalNonconstantDifference(const int& i, const int& j, const Gambit::Vector& point, const Gambit::Vector& halvesoflengths) const { return PartialTreeList[i].MaximalNonconstantDifference(PartialTreeList[j], point, halvesoflengths); } gambit-0.2010.09.01/src/tools/enumpoly/gpoly.cc0000644000076500007650000000503611435216101015676 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpoly.cc // Instantiation of common gPoly classes // // 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 #include "gpoly.imp" #include "libgambit/libgambit.h" template<> double gPoly::String_Coeff(double nega) { std::string Coeff = ""; while (charc >= '0' && charc <= '9' || charc == '.'){ Coeff += charc; charnum++; GetChar(); } if (Coeff == "") return (nega); else return (nega * strtod(Coeff.c_str(), NULL)); } template class gPoly; template gPoly operator+(const gPoly &poly, const double val); template gPoly operator*(const double val, const gPoly &poly); template gPoly operator*(const gPoly &poly, const double val); template gPoly TogDouble(const gPoly&); template gPoly NormalizationOfPoly(const gPoly&); template std::string &operator<<(std::string &, const gPoly &); /* template<> Gambit::Rational gPoly::String_Coeff(Gambit::Rational nega) { Gambit::Rational rat; std::string Coeff = ""; while (charc >= '0' && charc <= '9' || charc == '/' || charc == '.'){ Coeff += charc; charnum++; GetChar(); } if (Coeff == "") return (nega); else return (nega * Gambit::ToRational(Coeff)); } template class gPoly; template gPoly operator*(const Gambit::Rational val, const gPoly &poly); template gPoly operator*(const gPoly &poly, const Gambit::Rational val); template gPoly TogDouble(const gPoly&); template gPoly NormalizationOfPoly(const gPoly&); template std::string &operator<<(std::string &, const gPoly &); */ gambit-0.2010.09.01/src/tools/enumpoly/gpoly.h0000644000076500007650000002004711435216101015537 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpoly.h // Declaration of multivariate polynomial type // // 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 GPOLY_H #define GPOLY_H #include #include #include "monomial.h" #include "poly.h" // These classes are used to store and mathematically manipulate polynomials. // **NOTE** // Every type T to be used needs a procedure to convert a gText coefficient // to the type T for the gText SOP input form and a procedure to convert // the coefficient into a gText for the SOP output form. // ******************* // gPoly declaration // ******************* template class gPoly { private: const gSpace* Space; // pointer to variable Space of space const term_order* Order; Gambit::List > Terms; // alternative implementation // used for gText parsing; unsigned int charnum; char charc; std::string TheString; //---------------------- // some private members //---------------------- // Information exp_vect OrderMaxMonomialDivisibleBy(const term_order& order, const exp_vect& expv); // Arithmetic Gambit::List > Adder(const Gambit::List >&, const Gambit::List >&) const; Gambit::List > Mult(const Gambit::List >&, const Gambit::List >&) const; gPoly DivideByPolynomial(const gPoly &den) const; // The following is used to construct the translate of *this. gPoly TranslateOfMono(const gMono&, const Gambit::Vector&) const; gPoly MonoInNewCoordinates(const gMono&, const Gambit::SquareMatrix&) const; //----------------------------------------------- // Going back and forth from std::strings to gPoly's //----------------------------------------------- // std::string input parser functions void String_Term(T nega); T String_Coeff(T nega); int String_GetPow(void); void String_VarAndPow(Gambit::Array &PowArray); void GetChar(); // Is the string a valid polynomial? bool Check_String(const std::string &Hold); //---------------------- // private friends //---------------------- // friend gPoly operator*<>(const gPoly &poly, const T val); // friend gPoly operator*(const T val, const gPoly &poly); public: //--------------------------- // Construction, destruction: //--------------------------- // Null gPoly constructor gPoly(const gSpace *, const term_order *); // Constructs a gPoly equal to the SOP representation in the std::string gPoly(const gSpace *, const std::string &, const term_order *); // Constructs a constant gPoly gPoly(const gSpace *, const T &, const term_order *); // Constructs a gPoly equal to another; gPoly(const gPoly &); // Constructs a gPoly that is x_{var_no}^exp; gPoly(const gSpace *p, int var_no, int exp, const term_order *); // Constructs a gPoly that is the monomial coeff*vars^exps; gPoly(const gSpace *p, exp_vect exps, T coeff, const term_order *); // Constructs a gPoly with single monomial gPoly(const gSpace *p, const gMono&, const term_order *); ~gPoly(); //---------- //Operators: //---------- gPoly& operator = (const gPoly &); gPoly& operator = (const std::string &); //Set polynomial equal to the SOP form in the string gPoly operator - () const; gPoly operator - (const gPoly &) const; void operator -= (const gPoly &); gPoly operator + (const gPoly &) const; void operator += (const gPoly &); void operator += (const T&); gPoly operator * (const gPoly &) const; void operator *= (const gPoly &); void operator *= (const T&); gPoly operator / (const T val) const;// division by a constant gPoly operator / (const gPoly &) const;// division by a polynomial bool operator == (const gPoly &p) const; bool operator != (const gPoly &p) const; //------------- // Information: //------------- const gSpace* GetSpace(void) const; const term_order* GetOrder(void) const; int Dmnsn() const; bool IsZero() const; int DegreeOfVar(int var_no) const; int Degree() const; T GetCoef(const Gambit::Array &Powers) const; T GetCoef(const exp_vect &Powers) const; gPoly LeadingCoefficient(int varnumber) const; T NumLeadCoeff() const; // deg == 0 bool IsConstant() const; bool IsMultiaffine() const; int UniqueActiveVariable() const; // returns 0 if constant, -1 if truly multivariate polynomial UnivariateEquivalent(int activar) const; // assumes UniqueActiveVariable() is true T Evaluate(const Gambit::Array &values) const; gPoly EvaluateOneVar(int varnumber, T val) const; gPoly PartialDerivative(int varnumber) const; int No_Monomials() const; Gambit::List ExponentVectors() const; Gambit::List > MonomialList() const; gPoly TranslateOfPoly(const Gambit::Vector&) const; gPoly PolyInNewCoordinates(const Gambit::SquareMatrix&) const; T MaximalValueOfNonlinearPart(const T&) const; //-------------------- // Term Order Concepts //-------------------- exp_vect LeadingPowerProduct(const term_order &) const; T LeadingCoefficient(const term_order &) const; gPoly LeadingTerm(const term_order &) const; void ToMonic(const term_order &) ; void ReduceByDivisionAtExpV(const term_order &, const gPoly &, const exp_vect &); void ReduceByRepeatedDivision(const term_order &, const gPoly &); gPoly S_Polynomial(const term_order &, const gPoly &) const; //--------------- // Printing Stuff //--------------- // Print polynomial in SOP form void Output(std::string &) const; }; template std::string &operator<< (std::string &, const gPoly &); //------------- // Conversion: //------------- template gPoly TogDouble(const gPoly&); template gPoly NormalizationOfPoly(const gPoly&); // global multiply by scalar operators template gPoly operator*(const T val, const gPoly &poly); template gPoly operator*(const gPoly &poly, const T val); // global add to scalar operators template gPoly operator+(const T val, const gPoly &poly); template gPoly operator+(const gPoly &poly, const T val); template std::string ToText(const gPoly &p); #endif //# GPOLY_H gambit-0.2010.09.01/src/tools/enumpoly/gpoly.imp0000644000076500007650000005773511435216102016114 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpoly.imp // Implementation of multivariate polynomial type // // 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 #include "gpoly.h" #include "libgambit/libgambit.h" //--------------------------------------------------------------- // gPoly //--------------------------------------------------------------- //--------------------------- // Constructors / Destructor //--------------------------- template gPoly::gPoly(const gSpace* p, const term_order* o) : Space(p), Order(o), Terms() { } template gPoly::gPoly(const gSpace* p, const T& constant, const term_order* o) : Space(p), Order(o), Terms() { if (constant != (T)0) Terms.Append(gMono(p,constant)); } template gPoly::gPoly(const gSpace *p, const std::string &s, const term_order* o) : Space(p), Order(o), Terms() { *this=s; // Operator = needs to be fixed } template gPoly::gPoly(const gSpace *p, int var_no, int exp, const term_order* o) : Space(p), Order(o), Terms() { Terms.Append(gMono((T)1,exp_vect(p,var_no,exp))); } template gPoly::gPoly(const gSpace* p, exp_vect exps, T coeff, const term_order* o) : Space(p), Order(o), Terms() { Terms.Append(gMono(coeff,exps)); } template gPoly::gPoly(const gSpace* p, const gMono& mono, const term_order* o) : Space(p), Order(o), Terms() { Terms.Append(mono); } template gPoly::gPoly(const gPoly &p) : Space(p.Space), Order(p.Order), Terms(p.Terms) { *this=p; } template gPoly::~gPoly() { } //---------------------------------- // Operators //---------------------------------- template gPoly &gPoly::operator=(const gPoly &p) { assert (Space == p.Space && Order == p.Order); Terms = p.Terms; return (*this); } template gPoly& gPoly::operator=(const std::string &Hold) { Gambit::List > nullTerms; Terms = nullTerms; // get rid of old Terms charnum = 0; int contflag = 1; T nega = 1; Gambit::Array PowArray(Space->Dmnsn()); TheString = Hold + " +"; charc = TheString[charnum]; while (charnum <= TheString.length() && contflag){ switch (charc) { case '+' : case ' ': charnum++; charc = TheString[charnum]; break; case '-': charnum++; charc = TheString[charnum]; nega = -nega; break; case 0: //Null termination of string contflag = 0; break; default: String_Term(nega); nega = T (1); break; } } Gambit::List > newTerms; for (int j = 1; j <= Terms.Length(); j++) { int low = 0; int high = newTerms.Length() + 1; while (low +1 < high) { int test = low + (high - low)/2; if (1 <= test && test <= newTerms.Length()) assert (Terms[j].ExpV() != newTerms[test].ExpV()); if ( Order->Less(Terms[j].ExpV(),newTerms[test].ExpV()) ) high = test; else low = test; } newTerms.Insert(Terms[j],high); } Terms = newTerms; return (*this); } template gPoly gPoly::operator-() const { gPoly neg(*this); for (int j = 1; j <= Terms.Length(); j++) neg.Terms[j] = -Terms[j]; return neg; } template gPoly gPoly::operator-(const gPoly &p) const { gPoly dif(*this); dif -= p; return dif; } template void gPoly::operator-=(const gPoly &p) { assert(Space == p.Space); gPoly neg = p; for (int i = 1; i <= neg.Terms.Length(); i++) neg.Terms[i] = - neg.Terms[i]; Terms = Adder(Terms,neg.Terms); } template gPoly gPoly::operator+(const gPoly &p) const { gPoly sum(*this); sum += p; return sum; } template void gPoly::operator+=(const gPoly &p) { assert(Space == p.Space); Terms = Adder(Terms,p.Terms); } template void gPoly::operator+=(const T& val) { *this += gPoly(Space,val,Order); } template gPoly gPoly::operator*(const gPoly &p) const { gPoly prod(*this); prod *= p; return prod; } template gPoly gPoly::operator/(const T val) const { assert (val != (T)0); T one = (T)1; return (one/val) * (*this); } template gPoly gPoly::operator/(const gPoly & den) const { return DivideByPolynomial(den); } template void gPoly::operator*=(const gPoly &p) { assert(Space == p.Space); Terms = Mult(Terms,p.Terms); } template void gPoly::operator*=(const T& val) { for (int j = 1; j <= Terms.Length(); j++) Terms[j] *= val; } template bool gPoly::operator==(const gPoly &p) const { assert(Space == p.Space && Order == p.Order); if (Terms.Length() != p.Terms.Length()) return false; if (Terms.Length() == 0 && p.Terms.Length() == 0) return true; return (Terms == p.Terms); } template bool gPoly::operator!=(const gPoly &p) const { return !(*this == p); } //---------------------------------- // Member Functions //---------------------------------- template void gPoly::String_Term(T nega) { Gambit::Array PowArray(Dmnsn()); for (int a=1; a<= Dmnsn(); a++) PowArray[a] = 0; T val; val = String_Coeff(nega); while (charc != '+' && charc != '-') { if (charc == ' ') { charnum++; charc = TheString[charnum]; } else String_VarAndPow(PowArray); } Terms.Append(gMono(val, exp_vect(Space,PowArray))); } template int gPoly::String_GetPow(void) { std::string Pow = ""; while (charc == ' '){ charnum++; charc = TheString[charnum]; } while (charc >= '0' && charc <= '9'){ Pow += charc; charnum++; charc = TheString[charnum]; } return (atoi(Pow.c_str())); } template void gPoly::String_VarAndPow(Gambit::Array &PowArray) { std::string VarName = ""; int pow, varname; while (charc != '^' && charc != ' '){ VarName += charc; charnum++; charc = TheString[charnum]; } if (charc == '^') { charnum++; charc = TheString[charnum]; pow = String_GetPow(); } else pow = 1; for(varname = 1;varname <= Dmnsn() && VarName != (Space->VariableWithNumber(varname))->Name; varname ++); if (varname <= Dmnsn()) PowArray[varname] = pow; } // bool function to check the string in &Hold template bool gPoly::Check_String(const std::string &Hold){ unsigned int charnum=0; int boolflag=0; // state variables int statenumber=0; int statevar=0; int statesign=1; //values of the state variables enum number {nonumberbef, numberbef}; enum var {novarbef, varbef}; enum sign {nosignbef, signbef}; std::string TheString = Hold; char charc = TheString[charnum]; //movement along the string with a switch case while (charnum < TheString.length()){ switch (charc){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': statenumber=numberbef; statesign=nosignbef; break; case 'n': if (statenumber==0 && statesign==0) boolflag++; if (charnum == (TheString.length()-1)) boolflag++; statenumber=number(0); statevar=varbef; statesign=nosignbef; break; case '^': if (statenumber==0) boolflag++; if (statevar==0) boolflag++; if (charnum == (TheString.length()-1)) boolflag++; statenumber=nonumberbef; statevar=novarbef; statesign=nosignbef; break; case '/': case '.': if (statenumber==0) boolflag++; if (charnum == (TheString.length()-1)) boolflag++; statenumber=nonumberbef; statesign=nosignbef; break; case '+': case '-': if (statenumber==0 && charnum!=0) boolflag++; if (charnum == (TheString.length()-1)) boolflag++; statenumber=nonumberbef; statevar=novarbef; statesign=signbef; break; case ' ': break; default: boolflag++; break; } charnum++; charc = TheString[charnum]; } // return values if (boolflag==0) return true; else return false; } template void gPoly::GetChar(void) { charc = TheString[charnum]; } //---------------------------------- // Information //---------------------------------- template const gSpace* gPoly::GetSpace(void) const { return (gSpace *) Space; } template const term_order* gPoly::GetOrder(void) const { return (term_order *) Order; } template int gPoly::Dmnsn() const { return Space->Dmnsn(); } template int gPoly::DegreeOfVar(int var_no) const { int max = 0; for (int j = 1; j <= Terms.Length(); j++) if (max < Terms[j].ExpV()[var_no]) max = Terms[j].ExpV()[var_no]; return max; } template bool gPoly::IsZero() const { if (Terms.Length() == 0) return true; else return false; } template int gPoly::Degree() const { int max = 0; for (int j = 1; j <= Terms.Length(); j++) if (Terms[j].TotalDegree() > max) max = Terms[j].TotalDegree(); return max; } template T gPoly::GetCoef(const Gambit::Array &Powers) const { return GetCoef(exp_vect(Space,Powers)); } template T gPoly::GetCoef(const exp_vect &Powers) const { for (int j = 1; j <= Terms.Length(); j++) if (Terms[j].ExpV() == Powers) return Terms[j].Coef(); return (T)0; } template T gPoly::NumLeadCoeff() const { assert (Degree() == 0 && Terms.Length() <= 1); if (Terms.Length() == 1) return Terms[1].Coef(); else return (T)0; } template bool gPoly::IsConstant() const { for (int i = 1; i <= Terms.Length(); i++) if (!Terms[i].IsConstant()) return false; return true; } template bool gPoly::IsMultiaffine() const { for (int i = 1; i <= Terms.Length(); i++) if (!Terms[i].IsMultiaffine()) return false; return true; } template T gPoly::Evaluate(const Gambit::Array &values) const { T answer=0; for (int j = 1; j <= Terms.Length(); j++) answer += Terms[j].Evaluate(values); return answer; } template Gambit::List gPoly::ExponentVectors() const { Gambit::List result; for (int j = 1; j <= Terms.Length(); j++) result.Append(exp_vect(Terms[j].ExpV())); return result; } template Gambit::List > gPoly::MonomialList() const { return Terms; } template int gPoly::No_Monomials() const { // gout << "Eliminate old code in No_monomials, if successful.\n"; return Terms.Length(); } template int gPoly::UniqueActiveVariable() const { Gambit::List ExpVecs = ExponentVectors(); int activar = 0; for (int i = 1; i <= ExpVecs.Length(); i++) { for (int j = 1; j <= Dmnsn(); j++) { if (ExpVecs[i][j] > 0) if (activar > 0 && activar != j) return -1;// multivariate! else activar = j; } } return activar; } template polynomial gPoly::UnivariateEquivalent(int activar) const { assert(UniqueActiveVariable() >= 0); Gambit::List coefs; if (!IsZero()) { for (int h = 0; h <= DegreeOfVar(activar); h++) coefs.Append((T)0); for (int i = 1; i <= Terms.Length(); i++) coefs[Terms[i].ExpV()[activar] + 1] = Terms[i].Coef(); } return polynomial(coefs); } //------------------------------------------------------------- // Private Versions of Arithmetic Operators //------------------------------------------------------------- template Gambit::List< gMono > gPoly::Adder(const Gambit::List >& One, const Gambit::List >& Two) const { if (One.Length() == 0) return Two; if (Two.Length() == 0) return One; Gambit::List > answer; int i = 1; int j = 1; while (i <= One.Length() || j <= Two.Length()) { if (i > One.Length()) { answer.Append(Two[j]); j++; } else if (j > Two.Length()) { answer.Append(One[i]); i++; } else { if ( Order->Less( One[i].ExpV(),Two[j].ExpV()) ) { answer.Append(One[i]); i++; } else if ( Order->Greater(One[i].ExpV(),Two[j].ExpV()) ) { answer.Append(Two[j]); j++; } else { if (One[i].Coef() + Two[j].Coef() != (T)0) answer.Append(One[i] + Two[j]); i++; j++; } } } return answer; } template Gambit::List< gMono > gPoly::Mult(const Gambit::List >& One, const Gambit::List >& Two) const { Gambit::List > answer; if (One.Length() == 0 || Two.Length() == 0) return answer; int i; for (i = 1; i <= One.Length(); i++) for (int j = 1; j <= Two.Length(); j++) { gMono next = One[i] * Two[j]; if (answer.Length() == 0) answer.Append(next); else { int bot = 1; int top = answer.Length(); if ( Order->Less (answer[top].ExpV(),next.ExpV()) ) answer.Append(next); else if ( Order->Greater(answer[bot].ExpV(),next.ExpV()) ) answer.Insert(next,1); else { if ( answer[bot].ExpV() == next.ExpV() ) top = bot; else if ( answer[top].ExpV() == next.ExpV() ) bot = top; while (bot < top - 1) { int test = bot + (top - bot)/2; if ( answer[test].ExpV() == next.ExpV() ) bot = top = test; else if (Order->Less (answer[test].ExpV(),next.ExpV())) bot = test; else // (Order->Greater(answer[test].ExpV(),next.ExpV())) top = test; } if (bot == top) answer[bot] += next; else answer.Insert(next,top); } } } return answer; } template gPoly gPoly::DivideByPolynomial(const gPoly &den) const { gPoly zero(Space,(T)0,Order); assert(den != zero); assert(*this == zero || den.Degree() <= Degree()); // assumes exact divisibility! gPoly result = zero; if (*this == zero) return result; else if (den.Degree() == 0) { result = *this/den.NumLeadCoeff(); return result; } else { int last = Dmnsn(); while (den.DegreeOfVar(last) == 0) last--; gPoly remainder = *this; while (remainder != zero) { gPoly quot = remainder.LeadingCoefficient(last) / den.LeadingCoefficient(last); gPoly power_of_last(Space,last,remainder.DegreeOfVar(last) - den.DegreeOfVar(last),Order); result += quot * power_of_last; remainder -= quot * power_of_last * den; } } return result; } template gPoly gPoly::EvaluateOneVar( int varnumber, T val) const { gPoly answer(Space,(T)0,Order); for (int i = 1; i <= Terms.Length(); i++) answer += gPoly(Space, Terms[i].ExpV().AfterZeroingOutExpOfVariable(varnumber), ((T) Terms[i].Coef())* ((T) pow(val,(long int)Terms[i].ExpV()[varnumber])), Order); return answer; } template exp_vect gPoly::OrderMaxMonomialDivisibleBy(const term_order& order, const exp_vect& /*expv*/) { // gout << "You have just tested OrderMaxMonomialDivisibleBy.\n"; exp_vect answer(Space); // constructs [0,..,0] for (int i = 1; i <= Terms.Length(); i++) if ( order.Less(answer,Terms[i].ExpV()) && answer < Terms[i].ExpV() ) answer = Terms[i].ExpV(); return answer; } template gPoly gPoly::PartialDerivative(int varnumber) const { gPoly newPoly(*this); for (int i = 1; i <= newPoly.Terms.Length(); i++) newPoly.Terms[i] = gMono(newPoly.Terms[i].Coef() * (T)newPoly.Terms[i].ExpV()[varnumber], newPoly.Terms[i].ExpV().AfterDecrementingExpOfVariable(varnumber)); int j = 1; while (j <= newPoly.Terms.Length()) { if (newPoly.Terms[j].Coef() == (T)0) newPoly.Terms.Remove(j); else j++; } return (newPoly); } template gPoly gPoly::LeadingCoefficient(int varnumber) const { gPoly newPoly(*this); int degree = DegreeOfVar(varnumber); newPoly.Terms = Gambit::List >(); for (int j = 1; j <= Terms.Length(); j++) { if (Terms[j].ExpV()[varnumber] == degree) newPoly.Terms.Append(gMono(Terms[j].Coef(), Terms[j].ExpV().AfterZeroingOutExpOfVariable(varnumber))); } return (newPoly); } //-------------------- // Term Order Concepts //-------------------- template exp_vect gPoly::LeadingPowerProduct(const term_order & order) const { assert (Terms.Length() > 0); if (*Order == order) // worth a try ... return Terms[Terms.Length()].ExpV(); else { int max = 1; for (int j = 2; j <= Terms.Length(); j++) { if ( order.Less(Terms[max].ExpV(),Terms[j].ExpV()) ) max = j; } return Terms[max].ExpV(); } } template T gPoly::LeadingCoefficient(const term_order & order) const { if (*Order == order) // worth a try ... return Terms[Terms.Length()].Coef(); else { int max = 1; for (int j = 2; j <= Terms.Length(); j++) if ( order.Less(Terms[max].ExpV(),Terms[j].ExpV()) ) max = j; return Terms[max].Coef(); } } template gPoly gPoly::LeadingTerm(const term_order & order) const { if (*Order == order) // worth a try ... return gPoly(Space,Terms[Terms.Length()],Order); else { int max = 1; for (int j = 2; j <= Terms.Length(); j++) if ( order.Less(Terms[max].ExpV(),Terms[j].ExpV()) ) max = j; return gPoly(Space,Terms[max],Order); } } template void gPoly::ToMonic(const term_order & order) { *this = *this/LeadingCoefficient(order); } template void gPoly::ReduceByDivisionAtExpV(const term_order & order, const gPoly & divisor, const exp_vect & expv) { assert(expv >= divisor.LeadingPowerProduct(order)); assert(divisor.LeadingCoefficient(order) != (T)0); gPoly factor(Space, expv - divisor.LeadingPowerProduct(order), (T)1, Order); *this -= (GetCoef(expv) / divisor.LeadingCoefficient(order)) * factor * divisor; } template void gPoly::ReduceByRepeatedDivision(const term_order & order, const gPoly & divisor) { exp_vect zero_exp_vec(Space); exp_vect exps = OrderMaxMonomialDivisibleBy(order, divisor.LeadingPowerProduct(order)); while (exps != zero_exp_vec) { ReduceByDivisionAtExpV(order, divisor, exps); exps = OrderMaxMonomialDivisibleBy(order, divisor.LeadingPowerProduct(order)); } } template gPoly gPoly::S_Polynomial(const term_order& order, const gPoly& arg2) const { exp_vect exp_lcm = (LeadingPowerProduct(order)).LCM(arg2.LeadingPowerProduct(order)); gPoly lcm = gPoly(Space,exp_lcm,(T)1,Order); gPoly L1 = lcm/LeadingTerm(order); gPoly L2 = lcm/arg2.LeadingTerm(order); return L1*(*this) - L2*arg2; } template gPoly gPoly::TranslateOfMono(const gMono& m, const Gambit::Vector& new_origin) const { gPoly answer(GetSpace(), (T)1, GetOrder()); for (int i = 1; i <= Dmnsn(); i++) { if (m.ExpV()[i] > 0) { gPoly lt(GetSpace(), i, 1, GetOrder()); lt += gPoly(GetSpace(), new_origin[i], GetOrder()); for (int j = 1; j <= m.ExpV()[i]; j++) answer *= lt; } } answer *= m.Coef(); return answer; } template gPoly gPoly::TranslateOfPoly(const Gambit::Vector& new_origin) const { gPoly answer(GetSpace(), GetOrder()); for (int i = 1; i <= this->MonomialList().Length(); i++) answer += TranslateOfMono(this->MonomialList()[i],new_origin); return answer; } template gPoly gPoly::MonoInNewCoordinates(const gMono& m, const Gambit::SquareMatrix& M) const { assert(M.NumRows() == Dmnsn()); gPoly answer(GetSpace(), (T)1, GetOrder()); for (int i = 1; i <= Dmnsn(); i++) { if (m.ExpV()[i] > 0) { gPoly linearform(GetSpace(), (T)0, GetOrder()); for (int j = 1; j <= Dmnsn(); j++) { exp_vect exps(GetSpace(), j, 1); linearform += gPoly(GetSpace(), exps, M(i,j), GetOrder()); } for (int k = 1; k <= m.ExpV()[i]; k++) answer *= linearform; } } answer *= m.Coef(); return answer; } template gPoly gPoly::PolyInNewCoordinates(const Gambit::SquareMatrix& M) const { gPoly answer(GetSpace(), GetOrder()); for (int i = 1; i <= MonomialList().Length(); i++) answer += MonoInNewCoordinates(MonomialList()[i],M); return answer; } template T gPoly::MaximalValueOfNonlinearPart(const T& radius) const { T maxcon = (T)0; for (int i = 1; i <= MonomialList().Length(); i++) if (MonomialList()[i].TotalDegree() > 1) maxcon += MonomialList()[i].Coef() * pow(radius,(long)MonomialList()[i].TotalDegree()); return maxcon; } //--------------------------- // Global Operators //--------------------------- template gPoly operator*(const T val, const gPoly &poly) { gPoly prod(poly); prod *= val; return prod; } template gPoly operator*(const gPoly &poly, const T val) { return val * poly; } template gPoly operator+(const T val, const gPoly &poly) { gPoly prod(poly); prod += val; return prod; } template gPoly operator+(const gPoly &poly, const T val) { return val + poly; } template void gPoly::Output(std::string &t) const { std::string s; if (Terms.Length() == 0) { s += "0"; } else { for (int j = 1; j <= Terms.Length(); j++) { if (Terms[j].Coef() < (T)0) { s += "-"; if (j > 1) s += " "; } else if (j > 1) s += "+ "; if ((Terms[j].Coef() != (T)1 && -Terms[j].Coef() != (T)1) || Terms[j].IsConstant() ) if (Terms[j].Coef() < (T)0) { s += Gambit::ToText(-Terms[j].Coef()); } else { s += Gambit::ToText( Terms[j].Coef()); } for (int k = 1; k <= Space->Dmnsn(); k++) { int exp = Terms[j].ExpV() [k]; if (exp > 0) { s += " "; s += (*Space)[k]->Name; if (exp != 1) { s += '^'; s += Gambit::ToText(exp); } } } if (j < Terms.Length()) s += " "; } } if (s == "") s = " 0"; t += s; } template std::string &operator<<(std::string &p_text, const gPoly &p_poly) { p_poly.Output(p_text); return p_text; } //---------------------------------- // Conversion //---------------------------------- template gPoly TogDouble(const gPoly& given) { gPoly answer(given.GetSpace(),given.GetOrder()); Gambit::List > list = given.MonomialList(); for (int i =1; i <= list.Length(); i++) { double nextcoef = (double)list[i].Coef(); gPoly next(given.GetSpace(), list[i].ExpV(), nextcoef, given.GetOrder()); answer += next; } return answer; } template gPoly NormalizationOfPoly(const gPoly& given) { Gambit::List > list = given.MonomialList(); double maxcoeff = 0.0; for (int i =1; i <= list.Length(); i++) { maxcoeff = Gambit::max(maxcoeff, (double) Gambit::abs((double) list[i].Coef())); } if (maxcoeff < 0.000000001) return TogDouble(given); gPoly answer(given.GetSpace(),given.GetOrder()); for (int i =1; i <= list.Length(); i++) { double nextcoef = (double)list[i].Coef()/maxcoeff; gPoly next(given.GetSpace(), list[i].ExpV(), nextcoef, given.GetOrder()); answer += next; } return answer; } gambit-0.2010.09.01/src/tools/enumpoly/gpolyctr.h0000644000076500007650000000436011435216102016251 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpolyctr.h // Declaration of specialized containers for polynomials // // 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 GPOLYCTR_H #define GPOLYCTR_H #include "gpoly.h" template class gPolyArray { protected: int mindex, maxdex; gPoly **data; public: gPolyArray(const gSpace *, const term_order *, int len = 0); gPolyArray(const gSpace *, const term_order *, int lo, int hi); gPolyArray(const gPolyArray &); virtual ~gPolyArray(); gPolyArray &operator=(const gPolyArray &); int Length(void) const; int First(void) const; int Last(void) const; const gPoly &operator[](int index) const; gPoly &operator[](int index); virtual void Dump(gOutput &) const; }; template class gPolyBlock : public gPolyArray { private: int InsertAt(const gPoly &t, int where); public: gPolyBlock(const gSpace *, const term_order *, int len = 0); gPolyBlock(const gSpace *, const term_order *, int lo, int hi); gPolyBlock(const gPolyBlock &); virtual ~gPolyBlock(); gPolyBlock &operator=(const gPolyBlock &); bool operator==(const gPolyBlock &b) const; bool operator!=(const gPolyBlock &b) const; int Append(const gPoly &); int Insert(const gPoly &, int); gPoly Remove(int); int Find(const gPoly &) const; int Contains(const gPoly &t) const; void Flush(void); }; #endif // GPOLYCTR_H gambit-0.2010.09.01/src/tools/enumpoly/gpolylst.cc0000644000076500007650000000255011435216102016420 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpolylst.cc // Instantiations of polynomial list types // // 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 "gpolylst.imp" #include "libgambit/matrix.imp" //template class gPolyList; //template gOutput &operator<<(gOutput &f, const gPolyList &y); //template class gPolyList; //template class gPolyList; //template gOutput &operator<<(gOutput &f, const gPolyList &y); template class gPolyList; template class Gambit::RectArray*>; //template class Gambit::RectArray*>; gambit-0.2010.09.01/src/tools/enumpoly/gpolylst.h0000644000076500007650000001200511435216102016256 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpolylist.h // Declaration of polynomial list type // // 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 GPOLYLST_H #define GPOLYLST_H #include "odometer.h" #include #include "gpoly.h" //! //! Simple class for compact reference to pairs of indices //! class index_pair { private: const int m_first, m_second; public: index_pair(int p_first, int p_second) : m_first(p_first), m_second(p_second) { } bool operator==(const index_pair &p_other) const { return (m_first == p_other.m_first && m_second == p_other.m_second); } bool operator!=(const index_pair &p_other) const { return (m_first != p_other.m_first || m_second != p_other.m_second); } int operator[](int p_index) const { return (p_index == 1) ? m_first : m_second; } }; // *********************** // class gPolyList // *********************** template class gPolyList // : private Counted > { private: const gSpace* Space; const term_order* Order; Gambit::List< gPoly *> List; // SubProcedures of ToSortedReducedGrobner void Sort(const term_order &); void CriterionTwo( Gambit::List&, const Gambit::List&, const int&, const term_order&) const; // See Adams and Loustaunau, p. 130 void Grobnerize(const term_order &); void GrobnerToMinimalGrobner(const term_order &); void MinimalGrobnerToReducedGrobner(const term_order &); public: gPolyList(const gSpace *, const term_order*); gPolyList(const gSpace *, const term_order*, const Gambit::List< gPoly *> &); gPolyList(const gSpace *, const term_order*, const Gambit::List< gPoly > &); gPolyList(const gPolyList &); ~gPolyList(); // Deletes all pointees // Operators gPolyList& operator= (const gPolyList &); bool operator==(const gPolyList &) const; bool operator!=(const gPolyList &) const; void operator+=(const gPoly &); void operator+=(const gPolyList &); void operator+=( gPoly *); // NB - Doesn't copy pointee // This can save a copy when one must create a // polynomial, then do something in order to // decide whether it should be added to the List gPoly operator[](const int) const; // Residue of repeated reduction by members of the list gPoly ReductionOf(const gPoly &, const term_order &) const; bool SelfReduction(const int &, const term_order &); // Transform to canonical basis for associated ideal gPolyList& ToSortedReducedGrobner(const term_order &); // New Coordinate Systems gPolyList TranslateOfSystem(const Gambit::Vector&) const; gPolyList SystemInNewCoordinates(const Gambit::SquareMatrix&) const; // Truncations gPolyList InteriorSegment(int, int) const; // Information const gSpace* AmbientSpace() const; const term_order* TermOrder() const; const int Length() const; const int Dmnsn() const; const bool IsMultiaffine() const; Gambit::List > UnderlyingList() const; const Gambit::Vector Evaluate(const Gambit::Vector&) const; const bool IsRoot(const Gambit::Vector&) const; const Gambit::RectArray*> DerivativeMatrix() const; const gPoly DetOfDerivativeMatrix() const; const Gambit::Matrix DerivativeMatrix(const Gambit::Vector&) const; const Gambit::SquareMatrix SquareDerivativeMatrix(const Gambit::Vector&) const; // inline int static Count() { return Counted >::objCount(); } // Conversion Gambit::List > ListTogDouble() const; Gambit::List > NormalizedList() const; }; #endif // GPOLYLST_H gambit-0.2010.09.01/src/tools/enumpoly/gpolylst.imp0000644000076500007650000003727711435216102016636 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gpolylst.imp // Implementation of polynomial list type // // 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 "gpolylst.h" template Gambit::List InteriorSegment(const Gambit::List &p_list, int first, int last) { Gambit::List answer; for (int i = first; i <= last; i++) answer.Append(p_list[i]); return answer; } //--------------------------------------------------------------- // gPolyList //--------------------------------------------------------------- //--------------------------- // Constructors / Destructors //--------------------------- template gPolyList::gPolyList(const gSpace* sp, const term_order* to) : Space(sp), Order(to), List() { } template gPolyList::gPolyList(const gSpace * sp, const term_order* to, const Gambit::List< gPoly *> & plist) : Space(sp), Order(to), List() { int ii; for ( ii = 1; ii <= plist.Length(); ii++) { gPoly* temp = new gPoly(*plist[ii]); List.Append(temp); } } template gPolyList::gPolyList(const gSpace * sp, const term_order* to, const Gambit::List< gPoly > & list) : Space(sp), Order(to), List() { int ii; for ( ii = 1; ii <= list.Length(); ii++) { gPoly* temp = new gPoly(list[ii]); List.Append(temp); } } template gPolyList::gPolyList(const gPolyList & lst) : Space(lst.Space), Order(lst.Order), List() { int ii; for ( ii = 1; ii <= lst.List.Length(); ii++) { gPoly* temp = new gPoly(*(lst.List[ii])); List.Append(temp); } } template gPolyList::~gPolyList() { int ii; for (ii = 1; ii <= List.Length(); ii++) delete List[ii]; } //---------------------------------- // Operators //---------------------------------- template gPolyList& gPolyList::operator=(const gPolyList & rhs) { assert (Space == rhs.Space && Order == rhs.Order); if (*this != rhs) { int ii; for (ii = List.Length(); ii >= 1; ii--) { delete List[ii]; List.Remove(ii); } for (ii = 1; ii <= rhs.List.Length(); ii++) { gPoly* temp = new gPoly(*(rhs.List[ii])); List.Append(temp); } } return *this; } template bool gPolyList::operator==(const gPolyList & rhs) const { if (Space != rhs.Space || Order != rhs.Order) return false; if (List.Length() != rhs.List.Length()) return false; for (int j = 1; j <= List.Length(); j++) if (*List[j] != *(rhs.List[j])) return false; return true; } template bool gPolyList::operator!=(const gPolyList & rhs) const { return !(*this == rhs); } template void gPolyList::operator+=(const gPoly & new_poly) { gPoly* temp = new gPoly(new_poly); List.Append(temp); } template void gPolyList::operator+=(const gPolyList & new_list) { Gambit::List*> temp; for (int i = 1; i <= new_list.Length(); i++) temp.Append(new gPoly(new_list[i])); List+=temp; } // NB - does not copy pointee - see gpolylst.h template void gPolyList::operator+=(gPoly * new_poly_ptr) { List.Append(new_poly_ptr); } template gPoly gPolyList::operator[](const int index) const { return *(List[index]); } //------------------------------------------------- // Term Order and Grobner Basis Operations //------------------------------------------------- template bool gPolyList::SelfReduction(const int& target, const term_order& order) { assert (!List[target]->IsZero()); gPoly tear_up(*List[target]); gPoly reduction(Space,(T)0,&order); bool target_was_reduced = false; while (!tear_up.IsZero()) { int index = 1; while (index <= List.Length() && !tear_up.IsZero()) { if (index == target || List[index]->IsZero()) index++; else if ( List[index]->LeadingPowerProduct(order) <= tear_up.LeadingPowerProduct(order) ) { tear_up.ReduceByDivisionAtExpV(order, *List[index], tear_up.LeadingPowerProduct(order)); target_was_reduced = true; index = 1; } if (!tear_up.IsZero()) { reduction+=tear_up.LeadingTerm(order); tear_up-=tear_up.LeadingTerm(order); } } } *List[target] = reduction; return target_was_reduced; } template gPoly gPolyList::ReductionOf(const gPoly& f, const term_order& order) const { assert (Space == f.GetSpace()); if (f.IsZero()) { gPoly zero(Space,(T)0,f.GetOrder()); return zero; } gPoly tear_up(f); gPoly reduction(Space,(T)0,f.GetOrder()); while (!tear_up.IsZero()) { int index = 1; while (index <= List.Length() && !tear_up.IsZero()) { if (List[index]->IsZero()) index++; else if ( List[index]->LeadingPowerProduct(order) <= tear_up.LeadingPowerProduct(order) ) { tear_up.ReduceByDivisionAtExpV(order, *List[index], tear_up.LeadingPowerProduct(order)); index = 1; } else index++; } if (!tear_up.IsZero()) { reduction+=tear_up.LeadingTerm(order); tear_up-=tear_up.LeadingTerm(order); } } return reduction; } template void gPolyList::Sort(const term_order& order) // bubble sort, justified since // I expect List.Length() < 10 { if (List.Length() <= 1) return; int ii; for (ii = 1; ii < List.Length(); ii++) if (!List[ii]->IsZero()) { for (int j = ii + 1; j <= List.Length(); j++) { bool swap = false; if (List[j]->IsZero()) swap = true; else if ( order.Less(List[j]->LeadingPowerProduct(order), List[ii]->LeadingPowerProduct(order)) ) swap = true; if (swap) { gPoly* temp = List[ii]; List[ii] = List[j]; List[j] = temp; } } } } template void gPolyList::CriterionTwo( Gambit::List& uncomputed, const Gambit::List& computed, const int& no_polys, const term_order & order) const { for (int ell = 1; ell < no_polys; ell++) { int spot = uncomputed.Find(index_pair(ell,no_polys)); if (spot != 0) { int ii; for (ii = 1; ii < no_polys; ii++) if (ii != ell && spot != 0) if ( uncomputed.Contains(index_pair(ii,ell)) || computed.Contains(index_pair(ii,ell)) ) if (uncomputed.Contains(index_pair(ii,no_polys))) { exp_vect lpp_i = List[ii]-> LeadingPowerProduct(order); exp_vect lpp_ell = List[ell]->LeadingPowerProduct(order); exp_vect lpp_no_polys = List[no_polys]-> LeadingPowerProduct(order); if ( lpp_ell.Divides(lpp_i.LCM(lpp_no_polys)) ) { uncomputed.Remove(spot); spot = 0; } } } } int ii; for (ii = 1; ii < no_polys; ii++) { if ( uncomputed.Contains(index_pair(ii,no_polys)) ) for (int j = ii + 1; j < no_polys; j++) { int spot = uncomputed.Find(index_pair(ii,j)); if ( uncomputed.Contains(index_pair(j,no_polys)) && (spot != 0) ) { exp_vect lpp_i = List[ii]->LeadingPowerProduct(order); exp_vect lpp_j = List[j]->LeadingPowerProduct(order); exp_vect lpp_no_polys = List[no_polys]-> LeadingPowerProduct(order); if ( lpp_no_polys.Divides(lpp_i.LCM(lpp_j)) ) uncomputed.Remove(spot); } } } } template void gPolyList::Grobnerize(const term_order & order) { int index = 1; // Remove all 0's from List while (index <= List.Length()) if (List[index]->IsZero()) { delete List[index]; List.Remove(index); } else index++; if (List.Length() <= 1) return; int ii; for (ii = 1; ii <= List.Length(); ii++) List[ii]->ToMonic(order); Gambit::List uncomputed; Gambit::List computed; for (ii = 2; ii <= List.Length(); ii++) { for (int j = 1; j < ii; j++) uncomputed.Append(index_pair(j,ii)); CriterionTwo(uncomputed, computed, ii, order); } while (uncomputed.Length() > 0) { int mindex = 1; for (ii = 2; ii <= uncomputed.Length(); ii++) if (order.Less(List[uncomputed[ii][1]]->LeadingPowerProduct(order). LCM(List[uncomputed[ii][2]]->LeadingPowerProduct(order)), List[uncomputed[mindex][1]]->LeadingPowerProduct(order). LCM(List[uncomputed[mindex][2]]->LeadingPowerProduct(order)))) mindex = ii; computed.Append(uncomputed[mindex]); int ii = uncomputed[mindex][1]; int j = uncomputed[mindex][2]; uncomputed.Remove(mindex); if ( !List[ii]->LeadingPowerProduct(order). UsesDifferentVariablesThan(List[j]->LeadingPowerProduct(order)) ) { gPoly h = ReductionOf(List[ii]->S_Polynomial(order,*(List[j])),order); if (!h.IsZero()) { h.ToMonic(order); gPoly* hptr = new gPoly(h); List.Append(hptr); for (int k = 1; k < List.Length(); k++) uncomputed.Append(index_pair(k,List.Length())); CriterionTwo(uncomputed, computed, List.Length(), order); } } } } template void gPolyList::GrobnerToMinimalGrobner(const term_order & order) { if (Length() <= 1) return; int i = 1; int j = 2; while (j <= Length()) { if ( List[i]->LeadingPowerProduct(order) <= List[j]->LeadingPowerProduct(order) ) { delete List[j]; List.Remove(j); } else if ( List[i]->LeadingPowerProduct(order) >= List[j]->LeadingPowerProduct(order) ) { delete List[i]; List.Remove(i); if (i < j-1) j--; else i = 1; } else { if (i < j-1) i++; else { i = 1; j++; } } } } template void gPolyList::MinimalGrobnerToReducedGrobner(const term_order & order) { if (Length() <= 1) return; int i = 1; while (i <= List.Length()) { gPolyList AllBut_ith(*this); delete AllBut_ith.List[i]; AllBut_ith.List.Remove(i); gPoly h = AllBut_ith.ReductionOf(*List[i],order); delete List[i]; List[i] = new gPoly(h); i++; } } template gPolyList& gPolyList::ToSortedReducedGrobner(const term_order & order) { Grobnerize(order); GrobnerToMinimalGrobner(order); MinimalGrobnerToReducedGrobner(order); Sort(order); return *this; } //------------------------------------------ // New Coordinate Systems //------------------------------------------ template gPolyList gPolyList::TranslateOfSystem(const Gambit::Vector& new_origin) const { Gambit::List > new_polys; for (int i = 1; i <= Length(); i++) { new_polys.Append((*this)[i].TranslateOfPoly(new_origin)); // assert (TranslateOfPoly((*this)[i],new_origin) == // (*this)[i].TranslateOfPoly(new_origin)); } return gPolyList(AmbientSpace(),TermOrder(),new_polys); } template gPolyList gPolyList::SystemInNewCoordinates(const Gambit::SquareMatrix& M) const { Gambit::List > new_polys; for (int i = 1; i <= Length(); i++) { // assert ( (*this)[i].PolyInNewCoordinates(M) == // gPoly( PolyInNewCoordinates((*this)[i],M) ) ); new_polys.Append((*this)[i].PolyInNewCoordinates(M)); } return gPolyList(AmbientSpace(),TermOrder(),new_polys); } //----------------------------------- // Truncations //----------------------------------- template gPolyList gPolyList::InteriorSegment(int first, int last) const { return gPolyList(AmbientSpace(), TermOrder(), ::InteriorSegment(List, first, last)); } //---------------------------------- // Information //---------------------------------- template Gambit::List > gPolyList::UnderlyingList(void) const { Gambit::List > NewList; int ii; for (ii = 1; ii <= List.Length(); ii++) NewList.Append(*List[ii]); return NewList; } template const bool gPolyList::IsMultiaffine() const { for (int i = 1; i <= List.Length(); i++) if (!(*List[i]).IsMultiaffine()) return false; return true; } template const Gambit::Vector gPolyList::Evaluate(const Gambit::Vector& v) const { Gambit::Vector answer(Length()); int ii; for (ii = 1; ii <= List.Length(); ii++) answer[ii] = List[ii]->Evaluate(v); return answer; } template const bool gPolyList::IsRoot(const Gambit::Vector& v) const { for (int ii = 1; ii <= List.Length(); ii++) if (List[ii]->Evaluate(v) != (T)0) return false; return true; } template const Gambit::RectArray*> gPolyList::DerivativeMatrix() const { gPoly zero(Space, Order); Gambit::RectArray*> answer(Length(),Dmnsn()); int ii; for (ii = 1; ii <= Length(); ii++) for (int j = 1; j <= Dmnsn(); j++) answer(ii,j) = new gPoly(UnderlyingList()[ii].PartialDerivative(j)); return answer; } template const gPoly gPolyList::DetOfDerivativeMatrix() const { assert(List.Length() == Space->Dmnsn()); int n = List.Length(); Gambit::RectArray*> deriv_matrix = DerivativeMatrix(); gPoly answer(Space, Order); gPermutationOdometer odo(n); while (odo.Turn()) { gPoly increment(Space, (T)1, Order); for (int i = 1; i <= n; i++) increment *= *(deriv_matrix(i, odo[i])); increment *= (T)odo.CurrentSign(); answer += increment; } return answer; } template const Gambit::Matrix gPolyList::DerivativeMatrix(const Gambit::Vector& p) const { Gambit::Matrix answer(Length(),Dmnsn()); Gambit::List > list = UnderlyingList(); int ii; for (ii = 1; ii <= Length(); ii++) for (int j = 1; j <= Dmnsn(); j++) answer(ii,j) = list[ii].PartialDerivative(j).Evaluate(p); return answer; } template const Gambit::SquareMatrix gPolyList::SquareDerivativeMatrix(const Gambit::Vector& p) const { assert (Length() == Dmnsn()); Gambit::SquareMatrix answer(Length()); Gambit::List > list = UnderlyingList(); int ii; for (ii = 1; ii <= Length(); ii++) for (int j = 1; j <= Dmnsn(); j++) answer(ii,j) = list[ii].PartialDerivative(j).Evaluate(p); return answer; } //---------------------------------- // Conversion //---------------------------------- template Gambit::List > gPolyList::ListTogDouble() const { Gambit::List > newlist; int ii; for (ii = 1; ii <= List.Length(); ii++) { newlist.Append(gPoly(TogDouble(*List[ii]))); } return newlist; } template Gambit::List > gPolyList::NormalizedList() const { Gambit::List > newlist; int ii; for (ii = 1; ii <= List.Length(); ii++) { newlist.Append(gPoly(NormalizationOfPoly(*List[ii]))); } return newlist; } template const gSpace* gPolyList::AmbientSpace() const { return Space; } template const term_order* gPolyList::TermOrder() const { return Order; } template const int gPolyList::Length() const { return List.Length(); } template const int gPolyList::Dmnsn() const { return Space->Dmnsn(); } gambit-0.2010.09.01/src/tools/enumpoly/gsolver.cc0000644000076500007650000000176411435216102016232 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gsolver.cc // Instantiation of gSolver classes // // 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 "gsolver.imp" template class gSolver; //template class gSolver; gambit-0.2010.09.01/src/tools/enumpoly/gsolver.h0000644000076500007650000000322211435216102016063 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gsolver.h // Declaration of gSolver // // 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 GSOLVER_H #define GSOLVER_H #include "ideal.h" #include "linrcomb.h" #include "gpolylst.h" template class gSolver { private: const gPolyList& InputList; const gIdeal TheIdeal; // Conversion Gambit::List > BasisTogDouble() const; // Recursive Call in Solver Gambit::List > ContinuationSolutions(const Gambit::List >& list, const int dmnsn, const int curvar, const Gambit::Vector& knownvals); public: // Constructor and Destructor gSolver(const term_order* Order,const gPolyList& Inputs); gSolver(const gSolver&); ~gSolver(); bool IsZeroDimensional(); Gambit::List > Roots(); }; #endif // GSOLVER_H gambit-0.2010.09.01/src/tools/enumpoly/gsolver.imp0000644000076500007650000001511511435216102016425 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gsolver.imp // Implementation of class gSolver // // 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 "gsolver.h" //--------------------------------------------------------------- // gSolver //--------------------------------------------------------------- //--------------------------- // Constructor / Destructor //--------------------------- template gSolver::gSolver(const term_order* Order, const gPolyList& Inputs) : InputList(Inputs), TheIdeal(Order, Inputs) { } template gSolver::gSolver(const gSolver& given) : InputList(given.InputList), TheIdeal(given.TheIdeal) { } template gSolver::~gSolver() { } //--------------------------- // Utilities //--------------------------- template Gambit::List > gSolver::BasisTogDouble() const { Gambit::List > newlist; gPolyList oldlist = TheIdeal.CanonicalBasis(); for (int i = 1; i <= oldlist.Length(); i++) { newlist.Append(TogDouble(oldlist[i])); } return newlist; } template Gambit::List > gSolver::ContinuationSolutions(const Gambit::List >& list, const int dmnsn, const int curvar, const Gambit::Vector& knownvals) { Gambit::List > answer; if (!list[1].IsZero()) { polynomial rootpoly = list[1].UnivariateEquivalent(curvar); gInterval root_interval((double)-10,(double)10); // Ouch!! double error = (double) 0.0001; // Ditto!! //DEBUG //gout << "About to enter PreciseRoots ... \n"; Gambit::List rootlist = rootpoly.PreciseRoots(root_interval,error); //DEBUG //gout << "Just left PreciseRoots ... \n"; for (int i = 1; i <= rootlist.Length(); i++) { Gambit::Vector newvec(knownvals); newvec[curvar] = rootlist[i]; if (curvar == dmnsn) answer.Append(newvec); else { Gambit::List > newlist; for (int j = 2; j <= list.Length(); j++) newlist.Append(list[j].EvaluateOneVar(curvar,rootlist[i])); answer += ContinuationSolutions(newlist,dmnsn,curvar+1,newvec); } } } else { // (list[1].IsZero()) Gambit::List > newlist; for (int j = 2; j <= list.Length(); j++) newlist.Append(list[j]); answer += ContinuationSolutions(newlist,dmnsn,curvar,knownvals); } return answer; } //--------------------------- // Information //--------------------------- template bool gSolver::IsZeroDimensional() { return TheIdeal.ZeroDimensional(); } /* - Old Implementation of Roots template Gambit::List > gSolver::Roots() { Gambit::List > dlist = BasisTogDouble(); int dmnsn = InputList.AmbientSpace()->Dmnsn(); Gambit::Vector origin(dmnsn); for (int i = 1; i <= dmnsn; i++) origin[i] = (double)0; // Needless! Gambit::List > rootlist = ContinuationSolutions(dlist, dmnsn, 1, origin); return rootlist; } */ template Gambit::List > gSolver::Roots() { Gambit::List mon_bss = TheIdeal.MonomialBasis(); Gambit::List > UnivariateRootEquations; int i; for (i = 1; i <= TheIdeal.Dmnsn(); i++) { Gambit::Matrix CoefficientMatrix(mon_bss.Length()+1, mon_bss.Length()); int j = 0; bool done = false; while (!done) { exp_vect x_i_to_j(InputList.AmbientSpace(),i,j); gPoly power(InputList.AmbientSpace(),x_i_to_j,(T)1,TheIdeal.Order()); gPoly reduced_power = TheIdeal.CanonicalBasis(). ReductionOf(power,*(TheIdeal.Order())); for (int k = 1; k <= mon_bss.Length(); k++) CoefficientMatrix(j+1,k) = reduced_power.GetCoef(mon_bss[k]); //DEBUG //gout << "After updating, j = " << j // << "and CoefficientMatrix is\n" << CoefficientMatrix << "\n"; Gambit::Matrix SubMatrix(j+1,mon_bss.Length()); for (int m = 1; m <= j+1; m++) for (int n = 1; n <= mon_bss.Length(); n++) SubMatrix(m,n) = CoefficientMatrix(m,n); //DEBUG //gout << "Before entering Linear Combination, SubMatrix is\n" // << SubMatrix << "\n"; LinearCombination Attempt(SubMatrix); if (Attempt.LastRowIsSpanned()) { polynomial root_eqn_i(Attempt.LinearDependence()); UnivariateRootEquations.Append(root_eqn_i); done = true; } j++; } } Gambit::List > ConvertedUnivariateRootEquations; for (i = 1; i <= UnivariateRootEquations.Length(); i++) ConvertedUnivariateRootEquations.Append(UnivariateRootEquations[i].TogDouble()); Gambit::List > original; Gambit::List > revised; Gambit::Vector zero(TheIdeal.Dmnsn()); original.Append(zero); gInterval root_interval((double)-10,(double)10); // Ouch!! double error = (double) 0.0001; // Ditto!! for (i = 1; i <= TheIdeal.Dmnsn(); i++) { Gambit::List roots_of_eqn_i = ConvertedUnivariateRootEquations[i].PreciseRoots(root_interval,error); for (int j = 1; j <= original.Length(); j++) for (int k = 1; k <= roots_of_eqn_i.Length(); k++) { Gambit::Vector new_vec = original[j]; new_vec[i] = roots_of_eqn_i[k]; revised.Append(new_vec); } original = revised; revised = Gambit::List >(); } Gambit::List > finished; Gambit::List > gDoublePolys = InputList.ListTogDouble(); gPolyList InputListTogDouble(TheIdeal.TheSpace(), TheIdeal.Order(), gDoublePolys); for (i = 1; i <= original.Length(); i++) if (InputListTogDouble.IsRoot(original[i])) finished.Append(original[i]); return finished; } gambit-0.2010.09.01/src/tools/enumpoly/gtree.h0000644000076500007650000000627711435216102015525 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gtree.h // A generic tree container class // // 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 GTREE_H #define GTREE_H #include "libgambit/libgambit.h" template class gTree; template class gTreeNode { friend class gTree; private: T data; gTreeNode *parent, *prev, *next, *eldest, *youngest; public: // Constructor gTreeNode(const T& _data, gTreeNode* _parent, gTreeNode* _prev, gTreeNode* _next, gTreeNode* _eldest, gTreeNode* _youngest); ~gTreeNode(); inline void SetData (const T& newdata) {data = newdata;} inline void SetParent (gTreeNode* newparent) {parent = newparent;} inline void SetPrev (gTreeNode* newprev) {prev = newprev;} inline void SetNext (gTreeNode* newnext) {next = newnext;} inline void SetEldest (gTreeNode* neweldest) {eldest = neweldest;} inline void SetYoungest(gTreeNode* newyoungest) {youngest = newyoungest;} inline T GetData() const {return data;} inline gTreeNode* GetParent() const {return parent;} inline gTreeNode* GetPrev() const {return prev;} inline gTreeNode* GetNext() const {return next;} inline gTreeNode* GetEldest() const {return eldest;} inline gTreeNode* GetYoungest() const {return youngest;} }; template class gTree { protected: gTreeNode* root; gTreeNode* RecursiveFind(const T&, gTreeNode*) const; void RecursiveCopy(gTreeNode*, const gTreeNode*); void RecursiveFlush(const gTreeNode*); void Flush(void); public: gTree(void); gTree(const T&); gTree(const gTree&); virtual ~gTree(); gTree& operator=(const gTree&); bool operator==(const gTree& b) const; bool operator!=(const gTree& b) const; // Constructive Manipulation void InsertAt(const T&, gTreeNode*); // Information Gambit::List*> Children(const gTreeNode*) const; gTreeNode* RootNode() const; gTreeNode* Find(const T&) const; bool Contains(const T& t) const; bool SubtreesAreIsomorphic(const gTreeNode*, const gTreeNode*) const; }; #endif // GTREE_H gambit-0.2010.09.01/src/tools/enumpoly/gtree.imp0000644000076500007650000001251211435216102016050 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/gtree.imp // Implementation of a generic tree container class // // 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 #include "gtree.h" //-------------------------------------------------------------------------- // gTreeNode: Member function implementations //-------------------------------------------------------------------------- template gTreeNode::gTreeNode(const T& _data, gTreeNode* _parent, gTreeNode* _prev, gTreeNode* _next, gTreeNode* _eldest, gTreeNode* _youngest) : data(_data), parent(_parent), prev(_prev), next(_next), eldest(_eldest), youngest(_youngest) { } template gTreeNode::~gTreeNode() { } //-------------------------------------------------------------------------- // gTree: Member function implementations //-------------------------------------------------------------------------- template gTree::gTree(void) : root(NULL) { } template gTree::gTree(const T& rootdatum) : root(NULL) { root = new gTreeNode(rootdatum,NULL,NULL,NULL,NULL,NULL); } template gTree::gTree(const gTree& b) : root(NULL) { if (b.root != NULL) { root = new gTreeNode(b.root->data, NULL, NULL, NULL, NULL, NULL); RecursiveCopy(root, b.root); } } template gTree::~gTree() { Flush(); } template void gTree::InsertAt(const T& t, gTreeNode* n) { assert (n != NULL); if (n->eldest == NULL) { gTreeNode* newn = new gTreeNode(t,n,NULL,NULL,NULL,NULL); n->SetEldest(newn); n->SetYoungest(newn); } else { gTreeNode* newn = new gTreeNode(t,n,n->youngest,NULL,NULL,NULL); n->youngest->SetNext(newn); n->SetYoungest(newn); } } template void gTree::RecursiveCopy( gTreeNode* copyn, const gTreeNode* orign) { Gambit::List*> oldchildren = Children(orign); int i; for (i = 1; i <= oldchildren.Length(); i++) InsertAt(oldchildren[i]->data,copyn); Gambit::List*> newchildren = Children(copyn); for (i = 1; i <= newchildren.Length(); i++) RecursiveCopy(newchildren[i],oldchildren[i]); } //--------------------- operators ------------------------ template gTree& gTree::operator=(const gTree& b) { if (this != &b) { Flush(); if (root != NULL) { root = new gTreeNode(b.root->data, NULL, NULL, NULL, NULL, NULL); RecursiveCopy(root, b.root); } else root = NULL; } return *this; } template bool gTree::operator==(const gTree& b) const { if (root == NULL && b.root == NULL) return true; if (root == NULL || b.root == NULL) return false; return SubtreesAreIsomorphic(root,b.root); } template bool gTree::operator!=(const gTree& b) const { return !(*this == b); } template Gambit::List*> gTree::Children(const gTreeNode* n) const { assert(n != NULL); Gambit::List*> answer; for (gTreeNode* child = n->eldest; child != NULL; child = child->next) answer.Append(child); return answer; } template gTreeNode* gTree::RootNode() const { return root; } template gTreeNode* gTree::RecursiveFind(const T& t, gTreeNode* n) const { gTreeNode* answer = NULL; if (n->data == t) answer = n; else { gTreeNode* probe = n->eldest; while (answer == NULL && probe != NULL) { answer = RecursiveFind(t,probe); probe = probe->next; } } return answer; } template gTreeNode* gTree::Find(const T& t) const { return RecursiveFind(t,root); } template bool gTree::Contains(const T& t) const { return (Find(t) != NULL); } template bool gTree::SubtreesAreIsomorphic(const gTreeNode* lhs, const gTreeNode* rhs) const { if (lhs->data != rhs->data) return false; Gambit::List*> lchildren = Children(lhs); Gambit::List*> rchildren = Children(rhs); if (lchildren.Length() != rchildren.Length()) return false; for (int i = 1; i <= lchildren.Length(); i++) if ( !SubtreesAreIsomorphic(lchildren[i],rchildren[i]) ) return false; return true; } template void gTree::RecursiveFlush(const gTreeNode* n) { Gambit::List*> children = Children(n); for (int i = 1; i <= children.Length(); i++) RecursiveFlush(children[i]); delete n; } template void gTree::Flush(void) { RecursiveFlush(root); root = NULL; } gambit-0.2010.09.01/src/tools/enumpoly/ideal.cc0000644000076500007650000000254611435216102015626 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/ideal.cc // Instantiations of gBasis types // // 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 "ideal.imp" //template class gIdeal; //template class gBasis; //template gOutput &operator<<(gOutput &f, const gBasis &y); //template class gIdeal; //template class gBasis; //template gOutput &operator<<(gOutput &f, const gBasis &y); //template class gIdeal; //template class gBasis; //template gOutput &operator<<(gOutput &f, const gBasis &y); template class gIdeal; gambit-0.2010.09.01/src/tools/enumpoly/ideal.h0000644000076500007650000000625111435216102015465 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/ideal.h // Declaration of gIdeal // // 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 IDEAL_H #define IDEAL_H #include "odometer.h" #include "gpolylst.h" /* By the Hilbert basis theorem, every ideal is generated by some finite basis, and for computational purposes we essentially think of ideals as bases. There are some important operations, however, that differ across the various bases generating a single ideal, and for this reason we will have a separate basis class. Operator == is defined setwise -- computationally we sort the two bases and then compare termwise. In class ideal operator == is defined in terms of the ideal generated. Computationally two ideals agree if their ordered reduced Grobner bases are the same. */ // *********************** // class gIdeal // *********************** template class gIdeal { private: const gSpace* Space; const term_order* order; gPolyList basis; public: gIdeal(const gSpace *, const term_order *); // Null gIdeal constructor gIdeal(const gSpace *, const term_order *, const Gambit::List< gPoly *> &); gIdeal(const term_order *, const gPolyList &); gIdeal(const gIdeal &); ~gIdeal(); // Operators gIdeal& operator=(const gIdeal &); bool operator==(const gIdeal &) const; bool operator!=(const gIdeal &) const; gIdeal operator+ (const gIdeal &) const; gIdeal operator* (const gIdeal &) const; // Information inline int Dmnsn() const { return Space->Dmnsn(); } inline const gSpace* TheSpace() const { return Space ; } inline int NoBasisElements() const { return basis.Length(); } inline const term_order* Order() const { return order; } inline gPolyList CanonicalBasis() const { return basis; } gIdeal MonomialIdeal() const; Gambit::List MonomialBasis() const; // This returns a monomial basis of the ring of polynomial // functions on the variety V(I), where I is the given ideal. // It fails if the variety is not zero dimensional. bool IsRoot(const Gambit::Vector&) const; bool ZeroDimensional() const; bool IsEntireRing() const; bool Contains(gPoly &) const; }; #endif //# IDEAL_H gambit-0.2010.09.01/src/tools/enumpoly/ideal.imp0000644000076500007650000001354511435216102016027 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/ideal.imp // Implementation of gIdeal // // 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 "ideal.h" //--------------------------------------------------------------- // gIdeal //--------------------------------------------------------------- //--------------------------- // Constructors / Destructors //--------------------------- template gIdeal::gIdeal(const gSpace * ls, const term_order * ordr) : Space(ls), order(ordr), basis(ls,ordr) { } template gIdeal::gIdeal(const gSpace * ls, const term_order * ordr, const Gambit::List< gPoly *> & polys) : Space(ls), order(ordr), basis(ls,ordr,polys) { } template gIdeal::gIdeal(const term_order * ordr, const gPolyList & bss) : Space(bss.AmbientSpace()), order(ordr), basis(bss) { basis.ToSortedReducedGrobner(*ordr); } template gIdeal::gIdeal(const gIdeal & ideal) : Space(ideal.Space), order(ideal.order), basis(ideal.basis) { } template gIdeal::~gIdeal() { } //---------------------------------- // Operators //---------------------------------- template gIdeal& gIdeal::operator=(const gIdeal & rhs) { assert (Space == rhs.Space); if (*this != rhs) { this->order = rhs.order; this->basis = rhs.basis; } return *this; } template bool gIdeal::operator==(const gIdeal & rhs) const { if (Space != rhs.Space) { return false; } else { if (*order == *(rhs.order)) { if (basis == rhs.basis) return true; else return false; } if (basis.Length() != rhs.basis.Length()) return false; else { // gPolyList reordered_rhs(rhs.basis,*order); // gPolyList reordered_rhs(rhs.basis); const gIdeal reordered_rhs(order,rhs.basis); if (basis == reordered_rhs.basis) return true; else return false; } } } template bool gIdeal::operator!=(const gIdeal & rhs) const { return !(*this == rhs); } template gIdeal gIdeal::operator+ (const gIdeal & rhs) const { Gambit::List *> combined; for (int i = 1; i <= basis.Length(); i++) { gPoly* temp = new gPoly(basis[i]); combined.Append(temp); } for (int j = 1; j <= rhs.basis.Length(); j++) { gPoly* temp = new gPoly(rhs.basis[j]); combined.Append(temp); } return gIdeal(Space,order,combined); } template gIdeal gIdeal::operator* (const gIdeal & rhs) const { Gambit::List *> basis_products; for (int i = 1; i <= basis.Length(); i++) for (int j = 1; j <= rhs.basis.Length(); j++) { gPoly* temp = new gPoly(basis[i] * rhs.basis[j]); basis_products.Append(temp); } return gIdeal(Space,order,basis_products); } //---------------------------------- // Information //---------------------------------- template gIdeal gIdeal::MonomialIdeal() const { gPolyList mon_bss(Space,order); for (int i = 1; i <= basis.Length(); i++) mon_bss += basis[i].LeadingTerm(*order); return gIdeal(order,mon_bss); } template Gambit::List gIdeal::MonomialBasis() const { Gambit::List answer; Gambit::Array MinIndices(Dmnsn()), MaxIndices(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) MinIndices[i] = 0; for (int j = 1; j <= basis.Length(); j++) { if (basis[j].LeadingPowerProduct(*order).IsUnivariate()) MaxIndices[basis[j].LeadingPowerProduct(*order).SoleActiveVariable()] = basis[j].LeadingPowerProduct(*order).TotalDegree() - 1; } gIndexOdometer odometer(MinIndices,MaxIndices); while (odometer.Turn()) { exp_vect candidate(Space,odometer.CurrentIndices()); bool add = true; for (int j = 1; j <= basis.Length(); j++) if (basis[j].LeadingPowerProduct(*order) <= candidate) add = false; if (add) answer.Append(candidate); } return answer; } template bool gIdeal::IsRoot(const Gambit::Vector& v) const { for (int i = 1; i <= basis.Length(); i++) if (basis[i].Evaluate(v) != (T)0) return false; return true; } template bool gIdeal::ZeroDimensional() const { if (Dmnsn() == 0) return true; Gambit::Array HasLeadingTermThatIsPowerOfVariable(Dmnsn()); int i; for (i = 1; i <= Dmnsn(); i++) HasLeadingTermThatIsPowerOfVariable[i] = false; for (int j = 1; j <= basis.Length(); j++) { if (basis[j].LeadingPowerProduct(*order).IsConstant()) return false; if (basis[j].LeadingPowerProduct(*order).IsUnivariate()) HasLeadingTermThatIsPowerOfVariable[ basis[j].LeadingPowerProduct(*order).SoleActiveVariable() ] = true; } for (i = 1; i <= Dmnsn(); i++) if (!HasLeadingTermThatIsPowerOfVariable[i]) return false; return true; } template bool gIdeal::Contains(gPoly & f) const { gPoly zero(Space,(T)0,order); return (basis.ReductionOf(f,*order) == zero); } template bool gIdeal::IsEntireRing() const { gPoly one(Space,(T)1,order); return Contains(one); } gambit-0.2010.09.01/src/tools/enumpoly/ineqsolv.cc0000644000076500007650000000177211435216102016410 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/ineqsolv.cc // Instantiation of IneqSolv classes // // 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 "ineqsolv.imp" //template class IneqSolv; template class IneqSolv; gambit-0.2010.09.01/src/tools/enumpoly/ineqsolv.h0000644000076500007650000000656611435216102016260 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/ineqsolv.h // Declaration of IneqSolv // // 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 INEQSOLV_H #define INEQSOLV_H #include "libgambit/libgambit.h" #include "gsolver.h" #include "odometer.h" #include "rectangl.h" #include "gpoly.h" #include "gpolylst.h" #include "gpartltr.h" /* The class described in this file is a method of determining whether a system of weak inequalities has a solution (a point where all are satisfied) in a given rectangle. Ir is modeled on QuikSolv, but simpler. There is no Newton search, only repeated subdivision, queries at the center, and tests against whether one of the inequalities is provably everywhere negative in the rectangle. */ /* The main constructor for this takes a gPolyList, interpreted as inequalities in the sense that, at a solution, all the polynomials are required to be nonnegative. */ // *********************** // class IneqSolv // *********************** template class IneqSolv { private: const gPolyList System; const ListOfPartialTrees TreesOfPartials; T Epsilon; // bool HasBeenSolved; // gTriState HasASolution; // Gambit::Vector Sample; // Routines Doing the Actual Work bool IsASolution(const Gambit::Vector&) const; bool SystemHasNoSolutionIn(const gRectangle& r, Gambit::Array&) const; const bool ASolutionExistsRecursion(const gRectangle&, Gambit::Vector&, Gambit::Array&) const; public: IneqSolv(const gPolyList &); IneqSolv(const IneqSolv &); ~IneqSolv(); // Operators IneqSolv& operator= (const IneqSolv &); bool operator==(const IneqSolv &) const; bool operator!=(const IneqSolv &) const; // Information inline const gSpace* AmbientSpace() const { return System.AmbientSpace(); } inline const term_order* TermOrder() const { return System.TermOrder(); } inline const int Dmnsn() const { return System.Dmnsn(); } inline const gPolyList UnderlyingEquations() const { return System; } inline const T ErrorTolerance() const { return Epsilon; } // The function that does everything const bool ASolutionExists(const gRectangle&, Gambit::Vector& sample); }; #endif // INEQSOLV_H gambit-0.2010.09.01/src/tools/enumpoly/ineqsolv.imp0000644000076500007650000001100011435216102016571 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/ineqsolv.imp // Implementation of IneqSolv // // 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 "ineqsolv.h" //--------------------------------------------------------------- // class: IneqSolv //--------------------------------------------------------------- //--------------------------- // Constructors / Destructors //--------------------------- template IneqSolv::IneqSolv(const gPolyList& given) : System(given), TreesOfPartials(given), Epsilon((T)1/(T)1000000) // Epsilon((T)0), // HasBeenSolved(false), // HasASolution(triUNKNOWN), // Sample(given.Dmnsn()), { } template IneqSolv::IneqSolv(const IneqSolv& qs) : System(qs.System), TreesOfPartials(qs.TreesOfPartials), Epsilon(qs.Epsilon) // HasBeenSolved(qs.HasBeenSolved), // HasASolution(qs.HasASolution), // Sample(qs.Sample), { } template IneqSolv::~IneqSolv() { } //---------------------------------- // Operators //---------------------------------- template IneqSolv& IneqSolv::operator=(const IneqSolv & rhs) { assert (System == rhs.System); if (*this != rhs) { Epsilon = rhs.Epsilon; } return *this; } template bool IneqSolv::operator==(const IneqSolv & rhs) const { if (System != rhs.System || Epsilon != rhs.Epsilon) return false; else return true; } template bool IneqSolv::operator!=(const IneqSolv & rhs) const { return !(*this == rhs); } //--------------------------- // Calculations //--------------------------- template bool IneqSolv::IsASolution(const Gambit::Vector& v) const { bool answer(true); for (int i = 1; i <= System.Length() && answer; i++) if ( System[i].Evaluate(v) < -Epsilon ) answer = false; return answer; } template bool IneqSolv::SystemHasNoSolutionIn(const gRectangle& r, Gambit::Array& precedence) const { for (int i = 1; i <= System.Length(); i++) { if ( TreesOfPartials[precedence[i]].PolyEverywhereNegativeIn(r) ) { /* //DEBUG gout << "The polynomial " << System[precedence[i]] << " has no roots in "; gRectangle newrect(r); gout << newrect; gout << ".\n"; */ if (i != 1) { // We have found a new "most likely to never be positive" int tmp = precedence[i]; for (int j = 1; j <= i-1; j++) precedence[i - j + 1] = precedence[i - j]; precedence[1] = tmp; } return true; } } return false; } template const bool IneqSolv::ASolutionExistsRecursion(const gRectangle& r, Gambit::Vector& sample, Gambit::Array& precedence) const { /* //DEBUG gout << "The rectangle is\n"; for (int i = 1; i <= r.Dmnsn() - 1; i++) gout << r.CartesianFactor(i) << "x"; if (r.Dmnsn() > 0) gout << r.CartesianFactor(r.Dmnsn()) << "\n"; */ // Check for user interrupt if ( IsASolution(r.Center()) ) return true; if ( SystemHasNoSolutionIn(r, precedence) ) return false; int N = r.NumberOfCellsInSubdivision(); for (int i = 1; i <= N; i++) if (ASolutionExistsRecursion(r.SubdivisionCell(i), sample, precedence)) return true; return false; } template const bool IneqSolv::ASolutionExists (const gRectangle& r, Gambit::Vector& sample) { // precedence orders search for everywhere negative poly Gambit::Array precedence(System.Length()); for (int i = 1; i <= System.Length(); i++) precedence[i] = i; /* //DEBUG gout << "The system is\n" << System << "\n"; */ bool answer = ASolutionExistsRecursion(r, sample, precedence); return answer; } gambit-0.2010.09.01/src/tools/enumpoly/interval.cc0000644000076500007650000000205411435216102016366 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/interval.cc // Instantiation of interval type // // 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 #include "interval.imp" //template class gInterval; template class gInterval; template class gInterval; gambit-0.2010.09.01/src/tools/enumpoly/interval.h0000644000076500007650000000503711435216102016234 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/interval.h // Interface to interval type // // 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 INTERVAL_H #define INTERVAL_H #include "libgambit/libgambit.h" #include "libgambit/rational.h" /* This file provides the template class gInterval which models the concept of a nonempty compact interval. Since boundary points can be identified, open and half open (bounded) intervals can be effected, but less directly. */ template class gInterval { private: const T lower_bd; const T upper_bd; public: // constructors gInterval(const gInterval&); gInterval(const T, const T); ~gInterval(); // operators gInterval& operator = (const gInterval& y); bool operator == (const gInterval& y) const; bool operator != (const gInterval& y) const; // information const T LowerBound() const; const T UpperBound() const; const bool Contains(const T&) const; const bool Contains(const gInterval&) const; const bool LiesBelow(const T&) const; const bool LiesAbove(const T&) const; const T Length() const; const T Midpoint() const; const gInterval LeftHalf() const; const gInterval RightHalf() const; const gInterval SameCenterTwiceLength() const; const gInterval SameCenterWithNewLength(const T&) const; }; #endif // INTERVAL_H gambit-0.2010.09.01/src/tools/enumpoly/interval.imp0000644000076500007650000000754011435216102016573 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/interval.imp // Implementation of interval type // // 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 "interval.h" //-------------------------------------------------------------------------- // interval -- constructors and destructor //-------------------------------------------------------------------------- template gInterval::gInterval(const gInterval& given) : lower_bd(given.lower_bd), upper_bd(given.upper_bd) { } template gInterval::gInterval(const T low, const T high) : lower_bd(low), upper_bd(high) { assert (low <= high); } template gInterval::~gInterval() { } //-------------------------------------------------------------------------- // interval -- operators //-------------------------------------------------------------------------- template gInterval &gInterval::operator=(const gInterval &) { // gout << "For const'ness, operator = not allowed for gIntervals\n"; assert(0); return *this; /* if (*this == rhs) return *this; lower_bd = rhs.lower_bd; upper_bd = rhs.upper_bd; return *this; */ } template bool gInterval::operator == (const gInterval& rhs) const { return (lower_bd == rhs.lower_bd && upper_bd == rhs.upper_bd); } template bool gInterval::operator != (const gInterval& rhs) const { return !(*this == rhs); } //-------------------------------------------------------------------------- // interval -- information //-------------------------------------------------------------------------- template const T gInterval::LowerBound() const { return lower_bd; } template const T gInterval::UpperBound() const { return upper_bd; } template const bool gInterval::Contains(const T& number) const { return (lower_bd <= number && number <= upper_bd); } template const bool gInterval::Contains(const gInterval& I) const { return (lower_bd <= I.lower_bd && I.upper_bd <= upper_bd); } template const bool gInterval::LiesBelow(const T& number) const { return (upper_bd <= number); } template const bool gInterval::LiesAbove(const T& number) const { return (number <= lower_bd); } template const T gInterval::Length() const { return (upper_bd - lower_bd); } template const T gInterval::Midpoint() const { return (upper_bd + lower_bd)/(T)2; } template const gInterval gInterval::LeftHalf() const { return gInterval(LowerBound(),Midpoint()); } template const gInterval gInterval::RightHalf() const { return gInterval(Midpoint(),UpperBound()); } template const gInterval gInterval::SameCenterTwiceLength() const { return gInterval((T)2 * LowerBound() - Midpoint(), (T)2 * UpperBound() - Midpoint()); } template const gInterval gInterval::SameCenterWithNewLength(const T& L) const { return gInterval(Midpoint() - L/(T)2,Midpoint() + L/(T)2); } gambit-0.2010.09.01/src/tools/enumpoly/linrcomb.cc0000644000076500007650000000212311435216102016344 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/linrcomb.cc // Instantiation of linear combination types // // 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 "linrcomb.imp" #include #include template class LinearCombination; //template class LinearCombination; gambit-0.2010.09.01/src/tools/enumpoly/linrcomb.h0000644000076500007650000000471211435216102016214 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/linrcomb.h // Find linear weights for dependencies between rows of a matrix // // 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. // /* This file contains the file for a class that performs a very specific computation, namely asking whether the last row of a matrix is a linear combination of the other rows, and if so computing the coefficients of a linear dependence. All computation is done in the constructor. The constructor should only be called when there is a guarantee (which this class may be used to compute!) that the rows other than the last are linearly independent. */ #ifndef LINRCOMB_H #define LINRCOMB_H #include "libgambit/rational.h" #include "libgambit/matrix.h" template class LinearCombination { private: Gambit::Matrix scrambled; Gambit::Vector weights; bool last_row_is_spanned; void AddMultipleOfRowiToRowj(const int& i, const int& j, const T& scalar); void AddMultipleOfRowiToRowj(const int& i, const int& j, const T& scalar, Gambit::Matrix& B); // This function is left unimplemented to avoid copying LinearCombination& operator=(const LinearCombination &); public: // Constructors, Destructor, Constructive Operators LinearCombination(const Gambit::Matrix &); LinearCombination(const LinearCombination &); virtual ~LinearCombination(); // Comparison Operators bool operator==(const LinearCombination &) const; bool operator!=(const LinearCombination &) const; // Information bool LastRowIsSpanned() const; Gambit::Vector LinearDependence() const; }; #endif // LinearCombination_H gambit-0.2010.09.01/src/tools/enumpoly/linrcomb.imp0000644000076500007650000001403011435216102016544 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/linrcomb.imp // Implementation of linear combination class // // 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 #include "libgambit/libgambit.h" #include "linrcomb.h" //------------------------------------------------------------------------- // LinearCombination: Constructors, destructors, constructive operators //------------------------------------------------------------------------- template LinearCombination::LinearCombination(const Gambit::Matrix &M) : scrambled(M), weights(M.NumRows()), last_row_is_spanned(true) { int K = scrambled.NumRows() - 1; int i,j; Gambit::Matrix B(K,K); // Initialize the matrix recording the for (i = 1; i <= K; i++) // effect of all row operations. for (j = 1; j <= K; j++) if (i == j) B(i,j) = 1; else B(i,j) = 0; Gambit::Vector PivotRow(K); for (i = 1; i <= K; i++) PivotRow[i] = i; Gambit::Vector PivotColumn(K); int c = 1; for (i = 1; i <= K-1; i++) { // Each iteration is a // Gaussian column clearing int i1 = i; // Find pivot row and column while (scrambled(PivotRow[i1],c) == (T)0 && c <= M.NumColumns()) if (i1 < K) i1++; else { c++; i1 = i; } if (c > M.NumColumns()) { // gout << "First NumRows() rows not linearly independent in " // << "LinearCombination(Gambit::Matrix M).\n"; exit(1); } int tmp = PivotRow[i]; // Swap PivotRow[i] = PivotRow[i1]; PivotRow[i1] = tmp; PivotColumn[i] = c; for (int i2 = 1; i2 <= K; i2++) { // Each i2 is a pair of row operations. if (i2 != i) { T factor = scrambled(PivotRow[i2],PivotColumn[i]) / scrambled(PivotRow[i],PivotColumn[i]); AddMultipleOfRowiToRowj(PivotRow[i],PivotRow[i2],-factor,scrambled); AddMultipleOfRowiToRowj(PivotRow[i],PivotRow[i2],-factor,B); } } c++; } if (K > 0) { if (K == 1) PivotColumn[K] = 1; else PivotColumn[K] = PivotColumn[K-1]+1; while ( PivotColumn[K] <= M.NumColumns() && scrambled(PivotRow[K],PivotColumn[K]) == (T)0 ) PivotColumn[K]++; if (PivotColumn[K] > M.NumColumns()) { // gout << "First NumRows()-1 rows not linearly independent in " // << "LinearCombination(Gambit::Matrix M).\n"; // gout << "At the time of failure, scrambled is \n" // << scrambled << "\n"; exit(1); } for (int i2 = 1; i2 < K; i2++) { // Each i2 is a pair of row operations. T factor = scrambled(PivotRow[i2],PivotColumn[K]) / scrambled(PivotRow[K],PivotColumn[K]); AddMultipleOfRowiToRowj(PivotRow[K],PivotRow[i2],-factor); AddMultipleOfRowiToRowj(PivotRow[K],PivotRow[i2],-factor,B); } } Gambit::Vector xBinverse(K); for (int i3 = 1; i3 <= K; i3++) { // Each i3 is a row operation on last row. T factor = scrambled(K+1,PivotColumn[i3]) / scrambled(PivotRow[i3],PivotColumn[i3]); xBinverse[PivotRow[i3]] = factor; AddMultipleOfRowiToRowj(PivotRow[i3],K+1,-factor); } Gambit::Vector x(xBinverse * B); for (j = 1; j <= M.NumColumns(); j++) if (scrambled(K+1,j) != (T)0) last_row_is_spanned = false; if (last_row_is_spanned) { for (int i4 = 1; i4 <= K; i4++) weights[i4] = -x[i4]; weights[K+1] = 1; } } template LinearCombination::LinearCombination(const LinearCombination &L) : scrambled(L.scrambled), weights(L.weights), last_row_is_spanned(L.last_row_is_spanned) { } template LinearCombination::~LinearCombination() { } //------------------------------------------------------------------------- // LinearCombination: Comparison operators //------------------------------------------------------------------------- template bool LinearCombination::operator==(const LinearCombination &L) const { if (scrambled == L.scrambled && last_row_is_spanned == L.last_row_is_spanned && weights == L.weights) return true; else return false; } template bool LinearCombination::operator!=(const LinearCombination &L) const { return !(*this == L); } //------------------------------------------------------------------------- // LinearCombination: Information //------------------------------------------------------------------------- template bool LinearCombination::LastRowIsSpanned() const { return last_row_is_spanned; } template Gambit::Vector LinearCombination::LinearDependence() const { return weights; } //------------------------------------------------------------------------- // LinearCombination: Private Members //------------------------------------------------------------------------- template void LinearCombination::AddMultipleOfRowiToRowj(const int& i, const int& j, const T& scalar, Gambit::Matrix& B) { for (int k = 1; k <= B.NumColumns(); k++) B(j,k) += scalar * B(i,k); } template void LinearCombination::AddMultipleOfRowiToRowj(const int& i, const int& j, const T& scalar) { AddMultipleOfRowiToRowj(i,j,scalar,scrambled); } gambit-0.2010.09.01/src/tools/enumpoly/monomial.cc0000644000076500007650000000201711435216102016354 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/monomial.cc // Instantiation of monomial classes // // 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 "monomial.imp" template class gMono; template class gMono; //template class gMono; gambit-0.2010.09.01/src/tools/enumpoly/monomial.h0000644000076500007650000000462411435216102016224 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/monomial.h // Declaration of monomial class // // 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 "prepoly.h" // This file provides the template class // // gMono // // whose objects are monomials in several variables // with coefficients of class T and nonnegative exponents. // This role of this class is to support the class gPoly. template class gMono { private: T coef; exp_vect exps; public: // constructors gMono(const gSpace*, const T&); gMono(const T&, const exp_vect&); gMono(const gMono&); ~gMono(); // operators gMono& operator = (const gMono&); bool operator == (const gMono&) const; bool operator != (const gMono&) const; gMono operator * (const gMono&) const; gMono operator / (const gMono&) const; gMono operator + (const gMono&) const; // assert exps == gMono& operator += (const gMono&); // assert exps == gMono& operator *= (const T&); gMono operator - () const; // information const T & Coef() const; int Dmnsn() const; int TotalDegree() const; bool IsConstant() const; bool IsMultiaffine() const; const exp_vect& ExpV() const; T Evaluate(const Gambit::Array&) const; T Evaluate(const Gambit::Vector&) const; }; gambit-0.2010.09.01/src/tools/enumpoly/monomial.imp0000644000076500007650000000762111435216102016562 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/monomial.imp // Implementation of monomial classes // // 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 "monomial.h" //-------------------------------------------------------------------------- // gMono -- constructors and destructor //-------------------------------------------------------------------------- template gMono::gMono(const gSpace* p, const T& x) : coef(x), exps(p) { } template gMono::gMono(const T& x, const exp_vect& e) : coef(x), exps(e) { if (x == (T)0) exps.ToZero(); } template gMono::gMono(const gMono& y) : coef(y.coef), exps(y.exps) { } template gMono::~gMono() { } //-------------------------------------------------------------------------- // gMono -- operators //-------------------------------------------------------------------------- template gMono& gMono::operator = (const gMono& y) { if (this != &y) { coef = y.coef; exps = y.exps; } return *this; } template bool gMono::operator == (const gMono& y) const { return (coef == y.coef && exps == y.exps); } template bool gMono::operator != (const gMono& y) const { return !(*this == y); } template gMono gMono::operator * (const gMono & y) const { return gMono(coef * y.coef,exps + y.exps); } template gMono gMono::operator / (const gMono& y) const { //assert ( y.coef != (T)0); return gMono(coef / y.coef,exps - y.exps); } template gMono gMono::operator + (const gMono & y) const { //assert (exps == y.exps); return gMono(coef + y.coef,exps); } template gMono& gMono::operator += (const gMono & y) { //assert (exps == y.exps); coef += y.coef; return *this; } template gMono& gMono::operator *= (const T& val) { coef *= val; return *this; } template gMono gMono::operator - () const { return gMono(-coef,exps); } //-------------------------------------------------------------------------- // gMono -- information //-------------------------------------------------------------------------- template const T &gMono::Coef() const { return coef; } template int gMono::Dmnsn() const { return exps.Dmnsn(); } template int gMono::TotalDegree() const { return exps.TotalDegree(); } template const exp_vect &gMono::ExpV() const { return exps; } template bool gMono::IsConstant() const { return exps.IsConstant(); } template bool gMono::IsMultiaffine() const { return exps.IsMultiaffine(); } template T gMono::Evaluate(const Gambit::Array& vals) const { T answer = Coef(); for (int i = 1; i <= Dmnsn(); i++) for (int j = 1; j <= exps[i]; j++) answer *= vals[i]; return answer; } template T gMono::Evaluate(const Gambit::Vector& vals) const { T answer = Coef(); for (int i = 1; i <= Dmnsn(); i++) for (int j = 1; j <= exps[i]; j++) answer *= vals[i]; return answer; } gambit-0.2010.09.01/src/tools/enumpoly/nfgcpoly.cc0000644000076500007650000002331511435216102016366 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, Litao Wei and The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/nfgcpoly.cc // Compute Nash equilibria via heuristic search on game supports // (Porter, Nudelman & Shoham, 2004) // Implemented by Litao Wei // // 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 "nfgcpoly.h" //------------------------------------------------------------------------- // HeuristicPolEnumModule: Member functions //------------------------------------------------------------------------- HeuristicPolEnumModule::HeuristicPolEnumModule(const StrategySupport &S, int p_stopAfter) : m_stopAfter(p_stopAfter), NF(S.GetGame()), support(S), Space(support.MixedProfileLength()-NF->NumPlayers()), Lex(&Space, lex), num_vars(support.MixedProfileLength()-NF->NumPlayers()), count(0), nevals(0), is_singular(false) { // gEpsilon(eps,12); } int HeuristicPolEnumModule::PolEnum(void) { gPolyList equations = NashOnSupportEquationsAndInequalities(); /* // equations for equality of strat j to strat j+1 for( i=1;i<=NF.NumPlayers();i++) for(j=1;j2) equations+=Prob(i,support.NumStrats(i)); */ // set up the rectangle of search Vector bottoms(num_vars), tops(num_vars); bottoms = (double)0; tops = (double)1; gRectangle Cube(bottoms, tops); // start QuikSolv Gambit::List > solutionlist = NashOnSupportSolnVectors(equations, Cube); int index = SaveSolutions(solutionlist); return index; } int HeuristicPolEnumModule::SaveSolutions(const Gambit::List > &list) { MixedStrategyProfile profile(support); int i,j,k,kk,index=0; double sum; for(k=1;k<=list.Length();k++) { kk=0; for(i=1;i<=NF->NumPlayers();i++) { sum=0; for(j=1;j= -eps) return 1; return 0; } long HeuristicPolEnumModule::NumEvals(void) const { return nevals; } double HeuristicPolEnumModule::Time(void) const { return time; } const Gambit::List > &HeuristicPolEnumModule::GetSolutions(void) const { return solutions; } gPoly HeuristicPolEnumModule::Prob(int p, int strat) const { gPoly equation(&Space,&Lex); Vector exps(num_vars); int i,j,kk = 0; for(i=1;i const_term((double)1,const_exp); gPoly new_term(&Space,const_term,&Lex); equation+=new_term; } else { for(j=1;j term((double)(-1),exponent); gPoly new_term(&Space,term,&Lex); equation+=new_term; } exps=0; exp_vect const_exp(&Space,exps); gMono const_term((double)1,const_exp); gPoly new_term(&Space,const_term,&Lex); equation+=new_term; } return equation; } gPoly HeuristicPolEnumModule::IndifferenceEquation(int i, int strat1, int strat2) const { gPoly equation(&Space,&Lex); for (StrategyIterator A(support, i, strat1), B(support, i, strat2); !A.AtEnd(); A++, B++) { gPoly term(&Space,(double)1,&Lex); int k; for(k=1;k<=NF->NumPlayers();k++) if(i!=k) term*=Prob(k,support.GetIndex(A->GetStrategy(k))); double coeff,ap,bp; ap = A->GetPayoff(i); bp = B->GetPayoff(i); coeff = ap - bp; term*=coeff; equation+=term; } return equation; } gPolyList HeuristicPolEnumModule::IndifferenceEquations() const { gPolyList equations(&Space,&Lex); for(int pl=1;pl<=NF->NumPlayers();pl++) for(int j=1;j HeuristicPolEnumModule::LastActionProbPositiveInequalities() const { gPolyList equations(&Space,&Lex); for(int pl=1;pl<=NF->NumPlayers();pl++) if(support.NumStrategies(pl)>2) equations+=Prob(pl,support.NumStrategies(pl)); return equations; } gPolyList HeuristicPolEnumModule::NashOnSupportEquationsAndInequalities() const { gPolyList equations(&Space,&Lex); equations += IndifferenceEquations(); equations += LastActionProbPositiveInequalities(); return equations; } Gambit::List > HeuristicPolEnumModule::NashOnSupportSolnVectors(const gPolyList &equations, const gRectangle &Cube) { QuikSolv quickie(equations); // p_status.SetProgress(0); try { quickie.FindCertainNumberOfRoots(Cube,2147483647, m_stopAfter); } catch (SingularMatrixException) { is_singular = true; } return quickie.RootList(); } bool HeuristicPolEnumModule::IsSingular() const { return is_singular; } //--------------------------------------------------------------------------- // PolEnumParams: member functions //--------------------------------------------------------------------------- int PolEnum(const StrategySupport &support, int p_stopAfter, Gambit::List > &solutions, long &nevals, double &time, bool &is_singular) { HeuristicPolEnumModule module(support, p_stopAfter); module.PolEnum(); nevals = module.NumEvals(); time = module.Time(); solutions = module.GetSolutions(); if (module.IsSingular()) is_singular = true; else is_singular = false; return 1; } //--------------------------------------------------------------------------- // Polish Equilibrum for Nfg //--------------------------------------------------------------------------- #ifdef UNUSED static MixedStrategyProfile PolishEquilibrium(const StrategySupport &support, const MixedStrategyProfile &sol, bool &is_singular) { HeuristicPolEnumModule module(support, 0); Vector vec = module.SolVarsFromMixedStrategyProfile(sol); /* //DEBUG gbtPVector xx = module.SeqFormProbsFromSolVars(vec); MixedStrategyProfile newsol = module.SequenceForm().ToMixed(xx); gout << "sol.Profile = " << *(sol.Profile()) << "\n"; gout << "vec = " << vec << "\n"; gout << "xx = " << xx << "\n"; gout << "newsol = " << newsol << "\n"; exit(0); if ( newsol != *(sol.Profile()) ) { gout << "Failure of reversibility in PolishEquilibrium.\n"; exit(0); } */ //DEBUG // gout << "Prior to Polishing vec is " << vec << ".\n"; module.PolishKnownRoot(vec); //DEBUG // gout << "After Polishing vec is " << vec << ".\n"; return module.ReturnPolishedSolution(vec); } #endif // UNUSED Vector HeuristicPolEnumModule::SolVarsFromMixedStrategyProfile(const MixedStrategyProfile &sol) const { int numvars(0); for (int pl = 1; pl <= NF->NumPlayers(); pl++) numvars += support.NumStrategies(pl) - 1; Vector answer(numvars); int count(0); for (int pl = 1; pl <= NF->NumPlayers(); pl++) for (int j = 1; j < support.NumStrategies(pl); j++) { count ++; answer[count] = (double)sol[support.GetStrategy(pl,j)]; } return answer; } const int HeuristicPolEnumModule::PolishKnownRoot(Vector &point) const { //DEBUG // gout << "Prior to Polishing point is " << point << ".\n"; if (point.Length() > 0) { // equations for equality of strat j to strat j+1 gPolyList equations(&Space,&Lex); equations += IndifferenceEquations(); //DEBUG // gout << "We are about to construct quickie with Dmnsn() = " // << Space->Dmnsn() << " and equations = \n" // << equations << "\n"; // start QuikSolv QuikSolv quickie(equations); //DEBUG // gout << "We constructed quickie.\n"; try { point = quickie.NewtonPolishedRoot(point); } catch (SingularMatrixException &) { return 0; } //DEBUG // gout << "After Polishing point = " << point << ".\n"; } return 1; } MixedStrategyProfile HeuristicPolEnumModule::ReturnPolishedSolution(const Vector &root) const { MixedStrategyProfile profile(support); int j; int kk=0; for(int pl=1;pl<=NF->NumPlayers();pl++) { double sum=0; for(j=1;j > solutions; bool is_singular; bool EqZero(double x) const; // p_i_j as a gPoly, with last prob in terms of previous probs gPoly Prob(int i,int j) const; // equation for when player i sets strat1 = strat2 // with last probs for each player substituted out. gPoly IndifferenceEquation(int i, int strat1, int strat2) const; gPolyList IndifferenceEquations() const; gPolyList LastActionProbPositiveInequalities() const; gPolyList NashOnSupportEquationsAndInequalities() const; Gambit::List > NashOnSupportSolnVectors(const gPolyList &equations, const gRectangle &Cube); int SaveSolutions(const Gambit::List > &list); public: HeuristicPolEnumModule(const StrategySupport &, int p_stopAfter); int PolEnum(void); long NumEvals(void) const; double Time(void) const; const Gambit::List > &GetSolutions(void) const; Vector SolVarsFromMixedStrategyProfile(const MixedStrategyProfile &) const; const int PolishKnownRoot(Vector &) const; MixedStrategyProfile ReturnPolishedSolution(const Vector &) const; bool IsSingular() const; }; #endif // NFGCPOLY_H gambit-0.2010.09.01/src/tools/enumpoly/nfgensup.cc0000644000076500007650000002702711435216102016376 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/nfgensup.cc // Enumerate undominated subsupports of a support // // 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 "nfgensup.h" // We build a series of functions of increasing complexity. The // final one, which is our goal, is the undominated support function. // We begin by simply enumerating all subsupports. void AllSubsupportsRECURSIVE(const Gambit::StrategySupport &s, Gambit::StrategySupport *sact, StrategyCursorForSupport *c, Gambit::List &p_list) { p_list.Append(*sact); StrategyCursorForSupport c_copy(*c); do { Gambit::GameStrategy str_ptr = c_copy.GetStrategy(); if (sact->Contains(str_ptr)) { sact->RemoveStrategy(str_ptr); AllSubsupportsRECURSIVE(s,sact,&c_copy,p_list); sact->AddStrategy(str_ptr); } } while (c_copy.GoToNext()) ; } Gambit::List AllSubsupports(const Gambit::StrategySupport &S) { Gambit::List answer; Gambit::StrategySupport SAct(S); StrategyCursorForSupport cursor(S); AllSubsupportsRECURSIVE(S, &SAct, &cursor, answer); return answer; } // In the next two routines we only output subsupports that // have at least one active strategy for each agent. void AllValidSubsupportsRECURSIVE(const Gambit::StrategySupport &s, Gambit::StrategySupport *sact, StrategyCursorForSupport *c, Gambit::List &p_list) { p_list.Append(*sact); StrategyCursorForSupport c_copy(*c); do { if (sact->NumStrategies(c_copy.PlayerIndex()) > 1) { Gambit::GameStrategy str_ptr = c_copy.GetStrategy(); sact->RemoveStrategy(str_ptr); AllValidSubsupportsRECURSIVE(s,sact,&c_copy,p_list); sact->AddStrategy(str_ptr); } } while (c_copy.GoToNext()) ; } Gambit::List AllValidSubsupports(const Gambit::StrategySupport &S) { Gambit::List answer; Gambit::StrategySupport SAct(S); StrategyCursorForSupport cursor(S); AllValidSubsupportsRECURSIVE(S, &SAct, &cursor, answer); return answer; } void AllUndominatedSubsupportsRECURSIVE(const Gambit::StrategySupport &s, Gambit::StrategySupport *sact, StrategyCursorForSupport *c, const bool strong, const bool conditional, Gambit::List &p_list) { bool abort = false; bool no_deletions = true; Gambit::List deletion_list; StrategyCursorForSupport scanner(s); // First we collect all the strategies that can be deleted. do { Gambit::GameStrategy this_strategy = scanner.GetStrategy(); bool delete_this_strategy = false; if (sact->Contains(this_strategy)) if (sact->IsDominated(this_strategy,strong) ) delete_this_strategy = true; if (delete_this_strategy) { no_deletions = false; if (c->IsSubsequentTo(this_strategy)) abort = true; else deletion_list.Append(this_strategy); } } while (!abort && scanner.GoToNext()); // Now we delete them, recurse, then restore if (!abort && !no_deletions) { Gambit::List actual_deletions; for (int i = 1; !abort && i <= deletion_list.Length(); i++) { actual_deletions.Append(deletion_list[i]); sact->RemoveStrategy(deletion_list[i]); } if (!abort) AllUndominatedSubsupportsRECURSIVE(s, sact, c, strong, conditional, p_list); for (int i = 1; i <= actual_deletions.Length(); i++) sact->AddStrategy(actual_deletions[i]); } // If there are no deletions, we ask if it is consistent, then recurse. if (!abort && no_deletions) { p_list.Append(*sact); StrategyCursorForSupport c_copy(*c); do { if (sact->Contains(c_copy.GetStrategy()) && sact->NumStrategies(c_copy.PlayerIndex()) > 1 ) { Gambit::GameStrategy str_ptr = c_copy.GetStrategy(); sact->RemoveStrategy(str_ptr); AllUndominatedSubsupportsRECURSIVE(s, sact, &c_copy, strong, conditional, p_list); sact->AddStrategy(str_ptr); } } while (c_copy.GoToNext()) ; } } Gambit::List AllUndominatedSubsupports(const Gambit::StrategySupport &S, bool strong, bool conditional) { Gambit::List answer; Gambit::StrategySupport sact(S); StrategyCursorForSupport cursor(S); AllUndominatedSubsupportsRECURSIVE(S, &sact, &cursor, strong, conditional, answer); return answer; } void PossibleNashSubsupportsRECURSIVE(const Gambit::StrategySupport &s, Gambit::StrategySupport *sact, StrategyCursorForSupport *c, Gambit::List &p_list) { bool abort = false; bool no_deletions = true; Gambit::List deletion_list; StrategyCursorForSupport scanner(s); do { Gambit::GameStrategy this_strategy = scanner.GetStrategy(); bool delete_this_strategy = false; if (sact->Contains(this_strategy)) if (sact->IsDominated(this_strategy,true) ) { delete_this_strategy = true; } if (delete_this_strategy) { no_deletions = false; if (c->IsSubsequentTo(this_strategy)) abort = true; else deletion_list.Append(this_strategy); } } while (!abort && scanner.GoToNext()); if (!abort) { Gambit::List actual_deletions; for (int i = 1; !abort && i <= deletion_list.Length(); i++) { actual_deletions.Append(deletion_list[i]); sact->RemoveStrategy(deletion_list[i]); } if (!abort && deletion_list.Length() > 0) PossibleNashSubsupportsRECURSIVE(s,sact,c,p_list); for (int i = 1; i <= actual_deletions.Length(); i++) sact->AddStrategy(actual_deletions[i]); } if (!abort && no_deletions) { p_list.Append(*sact); StrategyCursorForSupport c_copy(*c); do { Gambit::GameStrategy str_ptr = c_copy.GetStrategy(); if (sact->Contains(str_ptr) && sact->NumStrategies(str_ptr->GetPlayer()->GetNumber()) > 1 ) { sact->RemoveStrategy(str_ptr); PossibleNashSubsupportsRECURSIVE(s,sact,&c_copy,p_list); sact->AddStrategy(str_ptr); } } while (c_copy.GoToNext()) ; } } Gambit::List SortSupportsBySize(Gambit::List &p_list) { Gambit::Array sizes(p_list.Length()); for (int i = 1; i <= p_list.Length(); i++) sizes[i] = p_list[i].MixedProfileLength(); Gambit::Array listproxy(p_list.Length()); for (int i = 1; i <= p_list.Length(); i++) listproxy[i] = i; int maxsize(0); for (int i = 1; i <= p_list.Length(); i++) if (sizes[i] > maxsize) maxsize = sizes[i]; int cursor(1); for (int j = 0; j < maxsize; j++) { int scanner(p_list.Length()); while (cursor < scanner) if (sizes[scanner] != j) scanner--; else { while (sizes[cursor] == j) cursor++; if (cursor < scanner) { int tempindex = listproxy[cursor]; listproxy[cursor] = listproxy[scanner]; listproxy[scanner] = tempindex; int tempsize = sizes[cursor]; sizes[cursor] = sizes[scanner]; sizes[scanner] = tempsize; cursor++; } } } Gambit::List answer; for (int i = 1; i <= p_list.Length(); i++) answer.Append(p_list[listproxy[i]]); return answer; } Gambit::List PossibleNashSubsupports(const Gambit::StrategySupport &S) { Gambit::List answer; Gambit::StrategySupport sact(S); StrategyCursorForSupport cursor(S); PossibleNashSubsupportsRECURSIVE(S, &sact, &cursor, answer); // At this point answer has all consistent subsupports without // any strong dominations. We now edit the list, removing all // subsupports that exhibit weak dominations, and we also eliminate // subsupports exhibiting domination by currently inactive strategies. for (int i = answer.Length(); i >= 1; i--) { Gambit::StrategySupport current(answer[i]); StrategyCursorForSupport crsr(S); bool remove = false; do { Gambit::GameStrategy strat = crsr.GetStrategy(); if (current.Contains(strat)) for (int j = 1; j <= strat->GetPlayer()->NumStrategies(); j++) { Gambit::GameStrategy other_strat = strat->GetPlayer()->GetStrategy(j); if (other_strat != strat) if (current.Contains(other_strat)) { if (current.Dominates(other_strat,strat,false)) remove = true; } else { current.AddStrategy(other_strat); if (current.Dominates(other_strat,strat,false)) { remove = true; } current.RemoveStrategy(other_strat); } } } while (crsr.GoToNext() && !remove); if (remove) answer.Remove(i); } return SortSupportsBySize(answer); return answer; } //---------------------------------------------------- // StrategyCursorForSupport // --------------------------------------------------- StrategyCursorForSupport::StrategyCursorForSupport(const Gambit::StrategySupport &S) : support(&S), pl(1), strat(1) {} StrategyCursorForSupport::StrategyCursorForSupport( const StrategyCursorForSupport &sc) : support(sc.support), pl(sc.pl), strat(sc.strat) {} StrategyCursorForSupport::~StrategyCursorForSupport() {} StrategyCursorForSupport& StrategyCursorForSupport::operator=(const StrategyCursorForSupport &rhs) { if (this != &rhs) { support = rhs.support; pl = rhs.pl; strat = rhs.strat; } return *this; } bool StrategyCursorForSupport::operator==(const StrategyCursorForSupport &rhs) const { if (support != rhs.support || pl != rhs.pl || strat != rhs.strat) return false; return true; } bool StrategyCursorForSupport::operator!=(const StrategyCursorForSupport &rhs) const { return (!(*this==rhs)); } bool StrategyCursorForSupport::GoToNext() { if (strat != support->NumStrategies(pl)) { strat++; return true; } else if (pl != support->GetGame()->NumPlayers()) { pl++; strat = 1; return true; } else return false; } Gambit::GameStrategy StrategyCursorForSupport::GetStrategy() const { return support->GetStrategy(pl, strat); } int StrategyCursorForSupport::StrategyIndex() const { return strat; } Gambit::GamePlayer StrategyCursorForSupport::GetPlayer() const { return support->GetGame()->GetPlayer(pl); } int StrategyCursorForSupport::PlayerIndex() const { return pl; } bool StrategyCursorForSupport::IsLast() const { if (pl == support->GetGame()->NumPlayers()) if (strat == support->NumStrategies(pl)) return true; return false; } bool StrategyCursorForSupport::IsSubsequentTo(const Gambit::GameStrategy &s) const { if (pl > s->GetPlayer()->GetNumber()) return true; else if (pl < s->GetPlayer()->GetNumber()) return false; else if (strat > s->GetNumber()) return true; else return false; } gambit-0.2010.09.01/src/tools/enumpoly/nfgensup.h0000644000076500007650000001113111435216102016225 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/nfgensup.h // Enumerate undominated subsupports of a support // // 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 "libgambit/libgambit.h" class StrategyCursorForSupport; // We build a series of functions of increasing complexity. The // final one, which is our goal, is the undominated support function. // We begin by simply enumerating all subsupports. void AllSubsupportsRECURSIVE(const Gambit::StrategySupport &s, Gambit::StrategySupport *sact, StrategyCursorForSupport *c, Gambit::List &list); Gambit::List AllSubsupports(const Gambit::StrategySupport &S); // Subsupports of a given support are _valid_ if each agent has an action. void AllValidSubsupportsRECURSIVE(const Gambit::StrategySupport &s, Gambit::StrategySupport *sact, StrategyCursorForSupport *c, Gambit::List &list); Gambit::List AllValidSubsupports(const Gambit::StrategySupport &S); // The following routines combine to return all supports that do not // exhibit particular type of domination. This was a prototype for // PossibleNashSubsupports, and displays the methods used there, // but it does NOT do exactly what is advertised with respect to // weak domination. This is because the recursion may eliminate // a strategy that is weakly dominated at some stage of the truncation // process, when, after more truncations, it might be no longer weakly // dominated, and thus part of an allowed subsupport. void AllUndominatedSubsupportsRECURSIVE(const Gambit::StrategySupport &s, Gambit::StrategySupport *sact, StrategyCursorForSupport *c, bool strong, Gambit::List &list); Gambit::List AllUndominatedSubsupports(const Gambit::StrategySupport &S, bool strong, bool conditional); // The following two routines combine to produce all subsupports that could // host the path of a behavioral Nash equilibrium. These are subsupports // that have no strategy, at an active infoset, that is weakly dominated by // another active strategy, either in the conditional sense (for any active // node in the infoset) or the unconditional sense. In addition we // check for domination by strategys that are inactive, but whose activation // would not activate any currently inactive infosets, so that the // subsupport resulting from activation is consistent, in the sense // of having active strategys at all active infosets, and not at other // infosets. void PossibleNashSubsupportsRECURSIVE(const Gambit::StrategySupport &s, Gambit::StrategySupport *sact, StrategyCursorForSupport *c, Gambit::List &list); Gambit::List SortSupportsBySize(Gambit::List &); Gambit::List PossibleNashSubsupports(const Gambit::StrategySupport &S); ///////////////// Utility Cursor Class ///////////////////// class StrategyCursorForSupport { protected: const Gambit::StrategySupport *support; int pl; int strat; public: //Constructors and dtor StrategyCursorForSupport(const Gambit::StrategySupport &S); StrategyCursorForSupport(const StrategyCursorForSupport &s); ~StrategyCursorForSupport(); // Operators StrategyCursorForSupport &operator =(const StrategyCursorForSupport &); bool operator==(const StrategyCursorForSupport &) const; bool operator!=(const StrategyCursorForSupport &) const; // Manipulation bool GoToNext(); // Information Gambit::GameStrategy GetStrategy() const; int StrategyIndex() const; Gambit::GamePlayer GetPlayer() const; int PlayerIndex() const; bool IsLast() const; bool IsSubsequentTo(const Gambit::GameStrategy &) const; }; gambit-0.2010.09.01/src/tools/enumpoly/nfghs.cc0000644000076500007650000005057611435216102015663 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, Litao Wei The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/nfghs.cc // Compute Nash equilibria via heuristic search on game supports // (Porter, Nudelman & Shoham, 2004) // Implemented by Litao Wei // // 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 #include #include #include "libgambit/libgambit.h" #include "nfgcpoly.h" #include "nfghs.h" extern MixedStrategyProfile ToFullSupport(const MixedStrategyProfile &p_profile); extern void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedStrategyProfile &p_profile); //--------------------------------------------------------------------------- // gbtNfgHs: member functions //--------------------------------------------------------------------------- void gbtNfgHs::Solve(Game game) { int i; int size, diff, maxsize, maxdiff; bool preferBalance; Initialize(game); //first, setup default, for "automatic", or for malformed ordering argument preferBalance = false; if (numPlayers == 2) { preferBalance = true; } //then, change if specified otherwise if (Ordering() == "balance") { preferBalance = true; } if (Ordering() == "size") { preferBalance = false; } Gambit::List < MixedStrategyProfile < double > > solutions; //Iterate over possible sizes and differences of the support size profile. //The order of iteration is determined by preferBalance. //Diff is defined to be difference between the maximum and minimum size support maxsize = 0; for (i = 1; i <= numPlayers; i++) { maxsize += numActions[i]; } maxdiff = maxActions - 1; size = numPlayers; diff = 0; while ((size <= maxsize) && (diff <= maxdiff)) { SolveSizeDiff(game, solutions, size, diff); if ((m_stopAfter > 0) && (solutions.Length() >= m_stopAfter)) { size = maxsize + 1; diff = maxdiff + 1; } if (preferBalance) { size++; if (size > maxsize) { size = numPlayers; diff++; } } else { diff++; if (diff > maxdiff) { diff = 0; size++; } } } Cleanup(game); } void gbtNfgHs::Initialize(Game p_game) { // remove strict dominated strategies Gambit::Array strategies_list; numPlayers = p_game->NumPlayers(); numActions = p_game->NumStrategies(); int i; minActions = numActions[1]; maxActions = numActions[1]; for (i = 2; i <= numPlayers; i++) { if (minActions > numActions[i]) { minActions = numActions[i]; } if (maxActions < numActions[i]) { maxActions = numActions[i]; } } } void gbtNfgHs::Cleanup(Game game) { } gbtNfgHs::gbtNfgHs(int p_stopAfter) : m_iteratedRemoval(true), m_removalWhenUninstantiated(1), m_ordering("automatic") #ifdef DEBUG , m_logfile(std::cerr) #endif // DEBUG { m_stopAfter = p_stopAfter; } void gbtNfgHs::SolveSizeDiff(Game game, Gambit::List < MixedStrategyProfile < double > > & solutions, int size, int diff) { //------------------------------------ // Logging #ifdef DEBUG m_logfile << "Entering SolveSizeDiff with size = " << size << ", diff = " << diff << "\n"; #endif //------------------------------------ int i, j; Gambit::Array < int > supportSizeProfile(numPlayers); for (i = 1; i <= numPlayers; i++) { supportSizeProfile[i] = 1; } supportSizeProfile[1] = 0; int currdiff, currsize, currminNumActions, currmaxNumActions; currsize = numPlayers; while ((currsize <= size) && (supportSizeProfile[numPlayers] <= numActions[numPlayers])) { j = 1; supportSizeProfile[j] += 1; currminNumActions = supportSizeProfile[1]; currmaxNumActions = supportSizeProfile[1]; for (i = 2; i <= numPlayers; i++) { if (currminNumActions > supportSizeProfile[i]) { currminNumActions = supportSizeProfile[i]; } if (currmaxNumActions < supportSizeProfile[i]) { currmaxNumActions = supportSizeProfile[i]; } } currdiff = currmaxNumActions - currminNumActions; currsize = 0; for (i = 1; i <= numPlayers; i++) { currsize += supportSizeProfile[i]; } while ((j != numPlayers) && ((supportSizeProfile[j] == numActions[j] + 1) || (currsize > size))) { supportSizeProfile[j] = 1; j++; supportSizeProfile[j] = supportSizeProfile[j] + 1; currminNumActions = supportSizeProfile[1]; currmaxNumActions = supportSizeProfile[1]; for (i = 2; i <= numPlayers; i++) { if (currminNumActions > supportSizeProfile[i]) { currminNumActions = supportSizeProfile[i]; } if (currmaxNumActions < supportSizeProfile[i]) { currmaxNumActions = supportSizeProfile[i]; } } currdiff = currmaxNumActions - currminNumActions; currsize = 0; for (i = 1; i <= numPlayers; i++) { currsize += supportSizeProfile[i]; } } if ((currdiff != diff) || (currsize != size)) { continue; } if (supportSizeProfile[numPlayers] <= numActions[numPlayers]) { SolveSupportSizeProfile(game, solutions, supportSizeProfile); } if (m_stopAfter > 0 && solutions.Length() >= m_stopAfter) { //------------------------------------ // Logging #ifdef DEBUG m_logfile << "Exiting SolveSizeDiff1\n"; #endif //------------------------------------ return; } } //------------------------------------ // Logging #ifdef DEBUG m_logfile << "Exiting SolveSizeDiff2\n"; #endif //------------------------------------ return; } bool gbtNfgHs::SolveSupportSizeProfile(Game game, Gambit::List < MixedStrategyProfile < double > > & solutions, const Gambit::Array < int > & supportSizeProfile) { //------------------------------------ // Logging #ifdef DEBUG m_logfile << "\n************\n"; m_logfile << "* Solving support size profile: "; for ( int i = 1; i <= numPlayers; i++ ) { m_logfile << supportSizeProfile[i] << ' '; } m_logfile << "\n************\n"; #endif //------------------------------------ Gambit::Array < Gambit::Array < GameStrategy > > uninstantiatedSupports(numPlayers); Gambit::Array < Gambit::Array < Gambit::Array < GameStrategy > > > domains(numPlayers); Gambit::PVector < int > playerSupport(supportSizeProfile); for (int i = 1; i <= numPlayers; i++) { uninstantiatedSupports[i] = 0; int m = 1; for (int j = 1; j <= supportSizeProfile[i]; j++) { playerSupport(i, j) = m; //m_logfile << "playerSupport: " << i << j << m << std::endl; m++; } } for (int i = 1; i <= numPlayers; i++) { bool success = false; do { Gambit::Array < GameStrategy > supportBlock; GetSupport(game, i, playerSupport.GetRow(i), supportBlock); domains[i].Append(supportBlock); success = UpdatePlayerSupport(game, i, playerSupport); } while (success); } return RecursiveBacktracking(game, solutions, uninstantiatedSupports, domains, 1); } void gbtNfgHs::GetSupport(Game game, int playerIdx, const Vector < int > & support, Gambit::Array < GameStrategy > & supportBlock) { //------------------------------------ // Logging #ifdef DEBUG m_logfile << "* Enter GetSupport for player " << playerIdx << ", choose strategies: "; for ( int i = 1; i <= support.Length(); i++ ) { m_logfile << support[i] << ' '; } m_logfile << "\n"; #endif //------------------------------------ GamePlayer player = game->GetPlayer(playerIdx); for (int i = 1; i <= support.Length(); i++) { int strategyIdx = support[i]; supportBlock.Append(player->GetStrategy(strategyIdx)); } return; } bool gbtNfgHs::UpdatePlayerSupport(Game game, int playerIdx, Gambit::PVector < int > & playerSupport) { Vector < int > support = playerSupport.GetRow(playerIdx); //------------------------------------ // Logging //m_logfile << "\n****\n"; //m_logfile << "* Enter UpdatePlayerSupport for player " << playerIdx << ", current strategiess: "; //for ( int i = 1; i <= support.Length(); i++ ) { // m_logfile << support[i] << ' '; //} //m_logfile << "\n****\n"; //------------------------------------ int lastBit = support.Length(); while (1) { playerSupport(playerIdx, lastBit) += 1; int idx = lastBit; while (idx > 1) { if (playerSupport(playerIdx, idx) == (numActions[playerIdx] + 1)) { playerSupport(playerIdx, idx - 1) += 1; if (playerSupport(playerIdx, idx - 1) < numActions[playerIdx]) { playerSupport(playerIdx, idx) = playerSupport(playerIdx, idx - 1) + 1; } else { playerSupport(playerIdx, idx) = numActions[playerIdx]; } } idx--; } if (playerSupport(playerIdx, 1) == (numActions[playerIdx] + 1)) { #ifdef DEBUG m_logfile << "Update finished, return false.\n"; #endif return false; } int maxIdx = support.Length(); for (int i = maxIdx - 1; i >= 1; i--) { if (playerSupport(playerIdx, i) >= playerSupport(playerIdx, maxIdx)) { maxIdx = i; } } if (maxIdx != lastBit) { continue; } else { break; } } return true; } bool gbtNfgHs::RecursiveBacktracking(Game game, Gambit::List < MixedStrategyProfile < double > > & solutions, Gambit::Array < Gambit::Array < GameStrategy > > & uninstantiatedSupports, Gambit::Array < Gambit::Array < Gambit::Array < GameStrategy > > > & domains, int idxNextSupport2Instantiate) { //------------------------------------ // Logging #ifdef DEBUG m_logfile << "\n********\n"; m_logfile << "* Begin RecursiveBacktracking to instantiate player " << idxNextSupport2Instantiate; m_logfile << "\n********\n"; #endif //------------------------------------ int idx = idxNextSupport2Instantiate; if (idx == numPlayers + 1) { //------------------------------------ // Logging #ifdef DEBUG m_logfile << "\n****************\n"; m_logfile << "* No more player. Instantiate finished. Now try to solve the restricted game:\n"; for (int i = 1; i <= uninstantiatedSupports.Length(); i++) { m_logfile << " Player " << i << ": "; for (int j = 1; j <= uninstantiatedSupports[i].Length(); j++) { m_logfile << uninstantiatedSupports[i] [j]->GetNumber() << ' '; } m_logfile << "\n"; } #endif //------------------------------------ bool success = FeasibilityProgram(game, solutions, uninstantiatedSupports); //------------------------------------ // Logging #ifdef DEBUG m_logfile << "* Whether solved : " << success << "\n"; m_logfile << "****************\n"; #endif //------------------------------------ if (success) { return true; } else { return false; } } else { //m_logfile << "Player " << idx << " domains length: " << domains[idx].Length() << " @@\n"; int domainLength = domains[idx].Length(); for (int k = 1; k <= domainLength; k++) { uninstantiatedSupports[idx] = domains[idx] [k]; //------------------------------------ // Logging #ifdef DEBUG m_logfile << "\nNow instantiate strategy for player " << idx << " :"; for (int i = 1; i <= uninstantiatedSupports[idx].Length(); i++) { m_logfile << uninstantiatedSupports[idx] [i]->GetNumber() << ' '; } m_logfile << "\n"; #endif //------------------------------------ Gambit::Array < Gambit::Array < Gambit::Array < GameStrategy > > > newDomains(numPlayers); for (int ii = 1; ii <= idx; ii++) { newDomains[ii].Append(uninstantiatedSupports[ii]); } for (int ii = idx + 1; ii <= numPlayers; ii++) { newDomains[ii] = domains[ii]; } bool success = true; if (IteratedRemoval()) { success = IteratedRemovalStrictlyDominatedStrategies(game, newDomains); } if (success) { // update domain //for (int ii = idx + 1; ii <= numPlayers; ii++) { // domains[ii] = newDomains[ii]; // } if (RecursiveBacktracking(game, solutions, uninstantiatedSupports, newDomains, idx + 1)) { if ((m_stopAfter > 0) && (solutions.Length() >= m_stopAfter)) { return true; } } } } return false; } } bool gbtNfgHs::IteratedRemovalStrictlyDominatedStrategies(Game game, Gambit::Array < Gambit::Array < Gambit::Array < GameStrategy > > > & domains) { //------------------------------------ // Logging #ifdef DEBUG m_logfile << "\n********\n"; m_logfile << "* Begin IteratedRemovalStrictlyDominatedStrategies:\n"; m_logfile << " Current domains:\n"; for (int i = 1; i <= numPlayers; i++) { m_logfile << " Player " << i << " [" << domains[i].Length() << "]: "; for (int j = 1; j <= domains[i].Length(); j++) { for (int k = 1; k <= domains[i] [j].Length(); k++) { m_logfile << domains[i] [j] [k]->GetNumber(); if (k != domains[i] [j].Length()) { m_logfile << ' '; } } if (j != domains[i].Length()) { m_logfile << " | "; } } m_logfile << "\n"; } m_logfile << "********\n"; #endif //------------------------------------ //Gambit::Array< Gambit::Array< Gambit::Array< gbtNfgStrategy > > > domains(numPlayers); bool changed = false; Gambit::Array < Gambit::Array < GameStrategy > > domainStrategies(numPlayers); GetDomainStrategies(domains, domainStrategies); do { changed = false; for (int i = 1; i <= numPlayers; i++) { GamePlayer player = game->GetPlayer(i); // construct restrict game StrategySupport dominatedGame(game); for (int pl = 1; pl <= numPlayers; pl++) { if (pl != i) { for (int st = 1; st <= game->GetPlayer(pl)->NumStrategies(); st++) { if (!domainStrategies[pl].Contains(game->GetPlayer(pl)->GetStrategy(st))) { dominatedGame.RemoveStrategy(game->GetPlayer(pl)->GetStrategy(st)); } } } } // construct end for (int ai = 1; ai <= numActions[i]; ai++) { GameStrategy stra = player->GetStrategy(ai); int straIdx = domainStrategies[i].Find(stra); if (straIdx == 0) { continue; } //bool dominated = IsConditionalDominated(dominatedGame, domainStrategies, stra, true); bool dominated = false; for (int aj = 1; aj <= numActions[i]; aj++ ) { if (aj != ai) { if (IsConditionalDominatedBy(dominatedGame, domainStrategies, stra, player->GetStrategy(aj), true)) { dominated = true; #ifdef DEBUG m_logfile << "Strategy " << ai << " is dominated by strategy " << aj << " in player " << i << "\n"; #endif break; } } } if (dominated) { bool success = RemoveFromDomain(domains, domainStrategies, i, straIdx); #ifdef DEBUG m_logfile << "* Now remove strategy " << ai << " in player " << i << " : "; m_logfile << success << "\n"; #endif changed = true; if (! success) { //------------------------------------ // Logging #ifdef DEBUG m_logfile << "\n********\n"; m_logfile << "* End IteratedRemovalStrictlyDominatedStrategies:\n"; m_logfile << " After IRSDS, domains exhausted!\n"; m_logfile << "********\n"; #endif //------------------------------------ return false; } } } } } while (changed == true); //------------------------------------ // Logging #ifdef DEBUG m_logfile << "\n********\n"; m_logfile << "* End IteratedRemovalStrictlyDominatedStrategies:\n"; m_logfile << " After IRSDS, domains:\n"; for (int i = 1; i <= numPlayers; i++) { m_logfile << " Player " << i << " [" << domains[i].Length() << "]: "; for (int j = 1; j <= domains[i].Length(); j++) { for (int k = 1; k <= domains[i] [j].Length(); k++) { m_logfile << domains[i] [j] [k]->GetNumber(); if (k != domains[i] [j].Length()) { m_logfile << ' '; } } if (j != domains[i].Length()) { m_logfile << " | "; } } m_logfile << "\n"; } m_logfile << "********\n"; #endif //------------------------------------ return true; } void gbtNfgHs::GetDomainStrategies(Gambit::Array < Gambit::Array < Gambit::Array < GameStrategy > > > & domains, Gambit::Array < Gambit::Array < GameStrategy > > & domainStrategies) { for (int i = 1; i <= numPlayers; i++) { domainStrategies[i] = 0; for (int j = 1; j <= domains[i].Length(); j++) { for (int k = 1; k <= domains[i] [j].Length(); k++) { if (domainStrategies[i].Find(domains[i] [j] [k]) == 0) { // no found domainStrategies[i].Append(domains[i] [j] [k]); } } } } } bool gbtNfgHs::IsConditionalDominatedBy(StrategySupport & dominatedGame, Gambit::Array < Gambit::Array < GameStrategy > > & domainStrategies, const GameStrategy &strategy, const GameStrategy &checkStrategy, bool strict) { //------------------------------------ // Logging //m_logfile << "\n********\n"; //m_logfile << "* Enter IsConditionalDominates:\n "; //m_logfile << "\n********\n"; //------------------------------------ GamePlayer player = strategy->GetPlayer(); int playerIdx = player->GetNumber(); int strategyIdx = strategy->GetNumber(); int checkStrategyIdx = checkStrategy->GetNumber(); GamePlayer dominatedPlayer = dominatedGame.GetGame()->GetPlayer(playerIdx); GameStrategy newStrategy = dominatedPlayer->GetStrategy(strategyIdx); GameStrategy newCheckStrategy = dominatedPlayer->GetStrategy(checkStrategyIdx); //return newCheckStrategy->Dominates(newStrategy, strict); return dominatedGame.Dominates(newCheckStrategy, newStrategy, strict); } bool gbtNfgHs::IsConditionalDominated(StrategySupport & dominatedGame, Gambit::Array < Gambit::Array < GameStrategy > > & domainStrategies, const GameStrategy &strategy, bool strict) { //------------------------------------ // Logging //m_logfile << "\n********\n"; //m_logfile << "* Enter IsConditionalDominated:\n "; //m_logfile << "\n********\n"; //------------------------------------ GamePlayer player = strategy->GetPlayer(); int playerIdx = player->GetNumber(); int strategyIdx = strategy->GetNumber(); GamePlayer dominatedPlayer = dominatedGame.GetGame()->GetPlayer(playerIdx); GameStrategy newStrategy = dominatedPlayer->GetStrategy(strategyIdx); //return newStrategy->IsDominated(strict); return dominatedGame.IsDominated(newStrategy, strict); } bool gbtNfgHs::RemoveFromDomain(Gambit::Array < Gambit::Array < Gambit::Array < GameStrategy > > > & domains, Gambit::Array < Gambit::Array < GameStrategy > > & domainStrategies, int player, int removeStrategyIdx) { GameStrategy removeStrategy = domainStrategies[player] [removeStrategyIdx]; for (int j = 1; j <= domains[player].Length(); j++) { int idx = domains[player] [j].Find(removeStrategy); if (idx > 0) { domains[player].Remove(j); j--; } } GetDomainStrategies(domains, domainStrategies); if (domains[player].Length() != 0) { return true; } else { return false; } } bool gbtNfgHs::FeasibilityProgram(Game game, Gambit::List < MixedStrategyProfile < double > > & solutions, Gambit::Array < Gambit::Array < GameStrategy > > & uninstantiatedSupports) { StrategySupport restrictedGame(game); for (int pl = 1; pl <= numPlayers; pl++) { for (int st = 1; st <= game->GetPlayer(pl)->NumStrategies(); st++) { if (!uninstantiatedSupports[pl].Contains(game->GetPlayer(pl)->GetStrategy(st))) { restrictedGame.RemoveStrategy(game->GetPlayer(pl)->GetStrategy(st)); } } } Gambit::List < MixedStrategyProfile < double > > newSolutions; HeuristicPolEnumModule module(restrictedGame, (m_stopAfter == 1) ? 1 : 0); module.PolEnum(); newSolutions = module.GetSolutions(); bool gotSolutions = false; for (int k = 1; k <= newSolutions.Length(); k++) { MixedStrategyProfile < double > solutionToTest = ToFullSupport(newSolutions[k]); if (solutionToTest.GetLiapValue() <.01) { gotSolutions = true; PrintProfile(std::cout, "NE", solutionToTest); solutions.Append(solutionToTest); if ((m_stopAfter > 0) && (solutions.Length() >= m_stopAfter)) { return true; } } } if (gotSolutions) { return true; } else { return false; } } gambit-0.2010.09.01/src/tools/enumpoly/nfghs.h0000644000076500007650000001010611435216102015506 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, Litao Wei and The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/nfghs.h // Compute Nash equilibria via heuristic search on game supports // (Porter, Nudelman & Shoham, 2004) // Implemented by Litao Wei // // 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 NFGHS_H #define NFGHS_H #include "libgambit/libgambit.h" using namespace Gambit; class gbtNfgHs { private: int m_stopAfter; bool m_iteratedRemoval; int m_removalWhenUninstantiated; std::string m_ordering; #ifdef DEBUG std::ostream m_logfile; #endif // DEBUG int minActions; int maxActions; int numPlayers; Gambit::Array < int > numActions; void Initialize(Game game); void Cleanup(Game game); void SolveSizeDiff(Game game, Gambit::List < MixedStrategyProfile < double > > & solutions, int size, int diff); bool SolveSupportSizeProfile(Game game, Gambit::List < MixedStrategyProfile < double > > & solutions, const Gambit::Array < int > & supportSizeProfile); void GetSupport(Game game, int playerIdx, const Vector < int > & support, Gambit::Array & supportBlock); bool UpdatePlayerSupport(Game game, int playerIdx, Gambit::PVector < int > & playerSupport); bool RecursiveBacktracking(Game game, Gambit::List < MixedStrategyProfile < double > > & solutions, Gambit::Array < Gambit::Array < GameStrategy > > & uninstantiatedSupports, Gambit::Array < Gambit::Array < Gambit::Array < GameStrategy > > > & domains, int idxNextSupport2Instantiate); bool IteratedRemovalStrictlyDominatedStrategies(Game game, Gambit::Array < Gambit::Array < Gambit::Array < GameStrategy > > > & domains); void GetDomainStrategies(Gambit::Array < Gambit::Array < Gambit::Array < GameStrategy > > > & domains, Gambit::Array < Gambit::Array < GameStrategy > > & domainStrategies); bool IsConditionalDominatedBy(StrategySupport & dominatedGame, Gambit::Array < Gambit::Array < GameStrategy > > & domainStrategies, const GameStrategy &strategy, const GameStrategy &checkStrategy, bool strict); bool IsConditionalDominated(StrategySupport & dominatedGame, Gambit::Array > & domainStrategies, const GameStrategy &strategy, bool strict); bool RemoveFromDomain(Gambit::Array > > & domains, Gambit::Array > & domainStrategies, int player, int removeStrategyIdx); bool FeasibilityProgram(Game game, Gambit::List > & solutions, Gambit::Array < Gambit::Array < GameStrategy > > & uninstantiatedSupports); public: gbtNfgHs(int = 1); virtual ~gbtNfgHs() { } int StopAfter(void)const { return m_stopAfter; } void SetStopAfter(int p_stopAfter) { m_stopAfter = p_stopAfter; } bool IteratedRemoval(void)const { return m_iteratedRemoval; } void SetIteratedRemoval(bool p_iteratedRemoval) { m_iteratedRemoval = p_iteratedRemoval; } int RemovalWhenUninstantiated(void)const { return m_removalWhenUninstantiated; } void SetRemovalWhenUninstantiated(int p_removalWhenUninstantiated) { m_removalWhenUninstantiated = p_removalWhenUninstantiated; } std::string Ordering(void)const { return m_ordering; } void SetOrdering(std::string p_ordering) { m_ordering = p_ordering; } void Solve(Game); }; #endif // NFGHS_H gambit-0.2010.09.01/src/tools/enumpoly/nfgpoly.cc0000644000076500007650000003322011435216102016217 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/nfgpoly.cc // Enumerates all Nash equilibria in a normal form game, via solving // systems of polynomial equations // // 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 #include #include "nfgensup.h" #include "gpoly.h" #include "gpolylst.h" #include "rectangl.h" #include "quiksolv.h" extern int g_numDecimals; extern bool g_verbose; class PolEnumModule { private: double eps; Gambit::Game NF; const Gambit::StrategySupport &support; gSpace Space; term_order Lex; int num_vars; long count,nevals; double time; Gambit::List > solutions; bool is_singular; bool EqZero(double x) const; // p_i_j as a gPoly, with last prob in terms of previous probs gPoly Prob(int i,int j) const; // equation for when player i sets strat1 = strat2 // with last probs for each player substituted out. gPoly IndifferenceEquation(int i, int strat1, int strat2) const; gPolyList IndifferenceEquations() const; gPolyList LastActionProbPositiveInequalities() const; gPolyList NashOnSupportEquationsAndInequalities() const; Gambit::List > NashOnSupportSolnVectors(const gPolyList &equations, const gRectangle &Cube); int SaveSolutions(const Gambit::List > &list); public: PolEnumModule(const Gambit::StrategySupport &); int PolEnum(void); long NumEvals(void) const; double Time(void) const; const Gambit::List > &GetSolutions(void) const; Gambit::Vector SolVarsFromMixedProfile(const Gambit::MixedStrategyProfile &) const; const int PolishKnownRoot(Gambit::Vector &) const; Gambit::MixedStrategyProfile ReturnPolishedSolution(const Gambit::Vector &) const; bool IsSingular() const; }; //------------------------------------------------------------------------- // PolEnumModule: Member functions //------------------------------------------------------------------------- PolEnumModule::PolEnumModule(const Gambit::StrategySupport &S) : NF(S.GetGame()), support(S), Space(support.MixedProfileLength()-NF->NumPlayers()), Lex(&Space, lex), num_vars(support.MixedProfileLength()-NF->NumPlayers()), count(0), nevals(0), is_singular(false) { // Gambit::Epsilon(eps,12); } int PolEnumModule::PolEnum(void) { gPolyList equations = NashOnSupportEquationsAndInequalities(); /* // equations for equality of strat j to strat j+1 for( i=1;i<=NF->NumPlayers();i++) for(j=1;jNumPlayers();i++) if(support.NumStrats(i)>2) equations+=Prob(i,support.NumStrats(i)); */ // set up the rectangle of search Gambit::Vector bottoms(num_vars), tops(num_vars); bottoms = (double)0; tops = (double)1; gRectangle Cube(bottoms, tops); // start QuikSolv Gambit::List > solutionlist = NashOnSupportSolnVectors(equations, Cube); int index = SaveSolutions(solutionlist); return index; } int PolEnumModule::SaveSolutions(const Gambit::List > &list) { Gambit::MixedStrategyProfile profile(support); int i,j,k,kk,index=0; double sum; for(k=1;k<=list.Length();k++) { kk=0; for(i=1;i<=NF->NumPlayers();i++) { sum=0; for(j=1;j= -eps) return 1; return 0; } long PolEnumModule::NumEvals(void) const { return nevals; } double PolEnumModule::Time(void) const { return time; } const Gambit::List > &PolEnumModule::GetSolutions(void) const { return solutions; } gPoly PolEnumModule::Prob(int p, int strat) const { gPoly equation(&Space,&Lex); Gambit::Vector exps(num_vars); int i,j,kk = 0; for(i=1;i const_term((double)1,const_exp); gPoly new_term(&Space,const_term,&Lex); equation+=new_term; } else { for(j=1;j term((double)(-1),exponent); gPoly new_term(&Space,term,&Lex); equation+=new_term; } exps=0; exp_vect const_exp(&Space,exps); gMono const_term((double)1,const_exp); gPoly new_term(&Space,const_term,&Lex); equation+=new_term; } return equation; } gPoly PolEnumModule::IndifferenceEquation(int i, int strat1, int strat2) const { gPoly equation(&Space,&Lex); for (Gambit::StrategyIterator A(support, i, strat1), B(support, i, strat2); !A.AtEnd(); A++, B++) { gPoly term(&Space,(double)1,&Lex); int k; for(k=1;k<=NF->NumPlayers();k++) if(i!=k) term*=Prob(k,support.GetIndex(A->GetStrategy(k))); double coeff,ap,bp; ap = A->GetPayoff(i); bp = B->GetPayoff(i); coeff = ap - bp; term*=coeff; equation+=term; } return equation; } gPolyList PolEnumModule::IndifferenceEquations() const { gPolyList equations(&Space,&Lex); for(int pl=1;pl<=NF->NumPlayers();pl++) for(int j=1;j PolEnumModule::LastActionProbPositiveInequalities() const { gPolyList equations(&Space,&Lex); for(int pl=1;pl<=NF->NumPlayers();pl++) if(support.NumStrategies(pl)>2) equations+=Prob(pl,support.NumStrategies(pl)); return equations; } gPolyList PolEnumModule::NashOnSupportEquationsAndInequalities() const { gPolyList equations(&Space,&Lex); equations += IndifferenceEquations(); equations += LastActionProbPositiveInequalities(); return equations; } Gambit::List > PolEnumModule::NashOnSupportSolnVectors(const gPolyList &equations, const gRectangle &Cube) { QuikSolv quickie(equations); // p_status.SetProgress(0); try { quickie.FindCertainNumberOfRoots(Cube,2147483647,0); } catch (Gambit::SingularMatrixException) { is_singular = true; } return quickie.RootList(); } bool PolEnumModule::IsSingular() const { return is_singular; } //--------------------------------------------------------------------------- // PolEnumParams: member functions //--------------------------------------------------------------------------- int PolEnum(const Gambit::StrategySupport &support, Gambit::List > &solutions, long &nevals, double &time, bool &is_singular) { PolEnumModule module(support); module.PolEnum(); nevals = module.NumEvals(); time = module.Time(); solutions = module.GetSolutions(); if (module.IsSingular()) is_singular = true; else is_singular = false; return 1; } //--------------------------------------------------------------------------- // Polish Equilibrum for Nfg //--------------------------------------------------------------------------- #ifdef UNUSED static Gambit::MixedStrategyProfile PolishEquilibrium(const Gambit::StrategySupport &support, const Gambit::MixedStrategyProfile &sol, bool &is_singular) { PolEnumModule module(support); Gambit::Vector vec = module.SolVarsFromMixedProfile(sol); /* //DEBUG Gambit::PVector xx = module.SeqFormProbsFromSolVars(vec); Gambit::MixedStrategyProfile newsol = module.SequenceForm().ToMixed(xx); gout << "sol.Profile = " << *(sol.Profile()) << "\n"; gout << "vec = " << vec << "\n"; gout << "xx = " << xx << "\n"; gout << "newsol = " << newsol << "\n"; exit(0); if ( newsol != *(sol.Profile()) ) { gout << "Failure of reversibility in PolishEquilibrium.\n"; exit(0); } */ //DEBUG // gout << "Prior to Polishing vec is " << vec << ".\n"; module.PolishKnownRoot(vec); //DEBUG // gout << "After Polishing vec is " << vec << ".\n"; return module.ReturnPolishedSolution(vec); } #endif // UNUSED Gambit::Vector PolEnumModule::SolVarsFromMixedProfile(const Gambit::MixedStrategyProfile &sol) const { int numvars(0); for (int pl = 1; pl <= NF->NumPlayers(); pl++) numvars += support.NumStrategies(pl) - 1; Gambit::Vector answer(numvars); int count(0); for (int pl = 1; pl <= NF->NumPlayers(); pl++) for (int j = 1; j < support.NumStrategies(pl); j++) { count ++; answer[count] = (double)sol[support.GetStrategy(pl,j)]; } return answer; } const int PolEnumModule::PolishKnownRoot(Gambit::Vector &point) const { //DEBUG // gout << "Prior to Polishing point is " << point << ".\n"; if (point.Length() > 0) { // equations for equality of strat j to strat j+1 gPolyList equations(&Space,&Lex); equations += IndifferenceEquations(); //DEBUG // gout << "We are about to construct quickie with Dmnsn() = " // << Space->Dmnsn() << " and equations = \n" // << equations << "\n"; // start QuikSolv QuikSolv quickie(equations); //DEBUG // gout << "We constructed quickie.\n"; try { point = quickie.NewtonPolishedRoot(point); } catch (Gambit::SingularMatrixException &) { return 0; } //DEBUG // gout << "After Polishing point = " << point << ".\n"; } return 1; } Gambit::MixedStrategyProfile PolEnumModule::ReturnPolishedSolution(const Gambit::Vector &root) const { Gambit::MixedStrategyProfile profile(support); int j; int kk=0; for(int pl=1;pl<=NF->NumPlayers();pl++) { double sum=0; for(j=1;j &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << ',' << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } Gambit::MixedStrategyProfile ToFullSupport(const Gambit::MixedStrategyProfile &p_profile) { Gambit::Game nfg = p_profile.GetGame(); const Gambit::StrategySupport &support = p_profile.GetSupport(); Gambit::MixedStrategyProfile fullProfile(nfg); for (int i = 1; i <= fullProfile.Length(); fullProfile[i++] = 0.0); int index = 1; for (int pl = 1; pl <= nfg->NumPlayers(); pl++) { Gambit::GamePlayer player = nfg->GetPlayer(pl); for (int st = 1; st <= player->NumStrategies(); st++) { if (support.Contains(player->GetStrategy(st))) { fullProfile[player->GetStrategy(st)] = p_profile[index++]; } } } return fullProfile; } void PrintSupport(std::ostream &p_stream, const std::string &p_label, const Gambit::StrategySupport &p_support) { p_stream << p_label; for (int pl = 1; pl <= p_support.GetGame()->NumPlayers(); pl++) { Gambit::GamePlayer player = p_support.GetGame()->GetPlayer(pl); p_stream << ","; for (int st = 1; st <= player->NumStrategies(); st++) { if (p_support.Contains(player->GetStrategy(st))) { p_stream << "1"; } else { p_stream << "0"; } } } p_stream << std::endl; } void SolveStrategic(const Gambit::Game &p_nfg) { Gambit::List supports = PossibleNashSubsupports(p_nfg); for (int i = 1; i <= supports.Length(); i++) { long newevals = 0; double newtime = 0.0; Gambit::List > newsolns; bool is_singular = false; if (g_verbose) { PrintSupport(std::cout, "candidate", supports[i]); } PolEnum(supports[i], newsolns, newevals, newtime, is_singular); for (int j = 1; j <= newsolns.Length(); j++) { Gambit::MixedStrategyProfile fullProfile = ToFullSupport(newsolns[j]); if (fullProfile.GetLiapValue() < 1.0e-6) { PrintProfile(std::cout, "NE", fullProfile); } } if (is_singular && g_verbose) { PrintSupport(std::cout, "singular", supports[i]); } } } gambit-0.2010.09.01/src/tools/enumpoly/odometer.cc0000644000076500007650000001672611435216102016373 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/odometer.cc // Implementation of class gIndexOdometer // // 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 #include "odometer.h" //--------------------------------------------------------------- // gIndexOdometer //--------------------------------------------------------------- //--------------------------- // Constructors / Destructors //--------------------------- gIndexOdometer::gIndexOdometer(const Gambit::Array IndexUpperBounds) : MinIndices(IndexUpperBounds.Length()), MaxIndices(IndexUpperBounds), CurIndices(IndexUpperBounds.Length()) { int i; for (i = 1; i <= NoIndices(); i++) MinIndices[i] = 1; CurIndices[1] = 0; for (i = 2; i <= NoIndices(); i++) CurIndices[i] = 1; } gIndexOdometer::gIndexOdometer(const Gambit::Array IndexLowerBounds, const Gambit::Array IndexUpperBounds) : MinIndices(IndexLowerBounds), MaxIndices(IndexUpperBounds), CurIndices(IndexUpperBounds.Length()) { CurIndices[1] = MinIndices[1] - 1;; for (int i = 2; i <= NoIndices(); i++) CurIndices[i] = MinIndices[i]; } gIndexOdometer::gIndexOdometer(const int* IndexUpperBounds, const int NoInd) : MinIndices(NoInd), MaxIndices(NoInd), CurIndices(NoInd) { int i; for (i = 1; i <= NoIndices(); i++) MinIndices[i] = 1; for (i = 1; i <= NoIndices(); i++) { MaxIndices[i] = IndexUpperBounds[i-1]; CurIndices[i] = 1; } CurIndices[1] = 0; } gIndexOdometer::gIndexOdometer(const gIndexOdometer & odo) : MaxIndices(odo.MaxIndices), CurIndices(odo.CurIndices) { } gIndexOdometer::~gIndexOdometer() { } //---------------------------------- // Operators //---------------------------------- gIndexOdometer& gIndexOdometer::operator=(const gIndexOdometer & rhs) { if (*this != rhs) { MinIndices = rhs.MinIndices; MaxIndices = rhs.MaxIndices; CurIndices = rhs.CurIndices; } return *this; } bool gIndexOdometer::operator==(const gIndexOdometer & rhs) const { if (MinIndices != rhs.MinIndices) return false; if (MaxIndices != rhs.MaxIndices) return false; if (CurIndices != rhs.CurIndices) return false; return true; } bool gIndexOdometer::operator!=(const gIndexOdometer & rhs) const { return !(*this == rhs); } int gIndexOdometer::operator[](const int place) const { //assert(1 <= place && place <= NoIndices()); return CurIndices[place]; } //---------------------------------- // Manipulate //---------------------------------- void gIndexOdometer::SetIndex(const int& place, const int& newind) { CurIndices[place] = newind; } bool gIndexOdometer::Turn() { if (CurIndices[1] == MinIndices[1]-1) { CurIndices[1] = MinIndices[1]; return true; } int turn_index = 1; while ( turn_index <= NoIndices() && CurIndices[turn_index] == MaxIndices[turn_index]) turn_index++; if (turn_index > NoIndices()) return false; for (int j = 1; j < turn_index; j++) CurIndices[j] = MinIndices[j]; CurIndices[turn_index]++; return true; } //---------------------------------- // Information //---------------------------------- int gIndexOdometer::NoIndices() const { return MaxIndices.Length(); } int gIndexOdometer::LinearIndex() const { int index = (*this)[1]; int factor = 1; for (int i = 2; i <= NoIndices(); i++) { factor *= MaxIndices[i-1] - MinIndices[i-1] + 1; index += factor * (CurIndices[i] - 1); } return index; } Gambit::Array gIndexOdometer::CurrentIndices() const { return CurIndices; } gIndexOdometer gIndexOdometer::AfterExcisionOf(int& to_be_zapped) const { Gambit::Array NewMins, NewMaxs; int i; for (i = 1; i < to_be_zapped; i++) { NewMins.Append(MinIndices[i]); NewMaxs.Append(MaxIndices[i]); } for (i = to_be_zapped+1; i <= NoIndices(); i++) { NewMins.Append(MinIndices[i]); NewMaxs.Append(MaxIndices[i]); } gIndexOdometer NewOdo(NewMins,NewMaxs); for (i = 1; i < to_be_zapped; i++) NewOdo.SetIndex(i ,CurIndices[i]); for (i = to_be_zapped+1; i <= NoIndices(); i++) NewOdo.SetIndex(i-1,CurIndices[i]); return NewOdo; } //--------------------------------------------------------------- // gPermutationOdometer //--------------------------------------------------------------- //--------------------------- // Constructors / Destructors //--------------------------- gPermutationOdometer::gPermutationOdometer(const int& given_n) : n(given_n), CurIndices(n), CurSign(0) { CurIndices[1] = 0; // Codes for virginity - see Turn() below for (int i = 2; i <= n; i++) CurIndices[i] = i; } gPermutationOdometer::gPermutationOdometer(const gPermutationOdometer & odo) : n(odo.n), CurIndices(odo.CurIndices), CurSign(odo.CurSign) { } gPermutationOdometer::~gPermutationOdometer() { } //---------------------------------- // Operators //---------------------------------- bool gPermutationOdometer::operator==(const gPermutationOdometer & rhs) const { if (n != rhs.n) return false; for (int i = 1; i <= n; i++) if (CurIndices[i] != rhs.CurIndices[i]) return false; if (CurSign != rhs.CurSign) { //gout << "Error in gPermutationOdometer\n"; exit(1); } return true; } bool gPermutationOdometer::operator!=(const gPermutationOdometer & rhs) const { return !(*this == rhs); } int gPermutationOdometer::operator[](const int place) const { //assert(1 <= place && place <= n); return CurIndices[place]; } //---------------------------------- // Manipulate //---------------------------------- bool gPermutationOdometer::Turn() { if (CurIndices[1] == 0) { // First turn gives identity permutation CurIndices[1] = 1; CurSign = 1; return true; } if (n ==1) return false; int cursor1 = n-1; while (cursor1 >= 1 && CurIndices[cursor1] > CurIndices[cursor1 + 1]) cursor1--; if (cursor1 == 0) return false; int cursor2 = cursor1 + 1; while (cursor2 < n && CurIndices[cursor2 + 1] > CurIndices[cursor1]) cursor2++; int tmp = CurIndices[cursor2]; CurIndices[cursor2] = CurIndices[cursor1]; CurIndices[cursor1] = tmp; CurSign *= -1; cursor1++; cursor2 = n; while (cursor1 < cursor2) { int tmp = CurIndices[cursor2]; CurIndices[cursor2] = CurIndices[cursor1]; CurIndices[cursor1] = tmp; CurSign *= -1; cursor1++; cursor2--; } return true; } //---------------------------------- // Information //---------------------------------- int gPermutationOdometer::NoIndices() const { return n; } Gambit::Array gPermutationOdometer::CurrentIndices() const { return CurIndices; } int gPermutationOdometer::CurrentSign() const { return CurSign; } gambit-0.2010.09.01/src/tools/enumpoly/odometer.h0000644000076500007650000000642411435216102016227 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/odometer.h // Declaration of gIndexOdometer class // // 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. // /* When the cartesian product of ordered sets is ordered lexicographically, there is a relation between such a relation, and the numerical indexing derived from the lexicographical ordering, that is similar to an odometer. Here the least significant index is the first ("leftmost"). The second class provides a utility for cycling through the integers 1..n. */ #ifndef ODOMETER_H #define ODOMETER_H #include "libgambit/libgambit.h" // ***************************** // class gIndexOdometer // ***************************** class gIndexOdometer { private: Gambit::Array MinIndices; Gambit::Array MaxIndices; Gambit::Array CurIndices; public: gIndexOdometer(const Gambit::Array); gIndexOdometer(const Gambit::Array, const Gambit::Array); gIndexOdometer(const int*, const int); gIndexOdometer(const gIndexOdometer &); ~gIndexOdometer(); // Deletes all pointees // Operators gIndexOdometer& operator= (const gIndexOdometer &); bool operator==(const gIndexOdometer &) const; bool operator!=(const gIndexOdometer &) const; int operator[](const int) const; // Manipulate void SetIndex(const int&, const int&); bool Turn(); // Information int NoIndices() const; int LinearIndex() const; Gambit::Array CurrentIndices() const; gIndexOdometer AfterExcisionOf(int&) const; }; // ***************************** // class gPermutationOdometer // ***************************** class gPermutationOdometer { private: const int n; Gambit::Array CurIndices; int CurSign; // Declared but not defined to prohibit assignment gPermutationOdometer &operator=(const gPermutationOdometer &); public: gPermutationOdometer(const int&); gPermutationOdometer(const gPermutationOdometer &); ~gPermutationOdometer(); // Deletes all pointees // Operators bool operator==(const gPermutationOdometer &) const; bool operator!=(const gPermutationOdometer &) const; int operator[](const int) const; // Manipulate bool Turn(); // Information int NoIndices() const; Gambit::Array CurrentIndices() const; int CurrentSign() const; }; #endif // ODOMETER_H gambit-0.2010.09.01/src/tools/enumpoly/pelclass.cc0000644000076500007650000004432711435216102016361 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/pelclass.cc // Implementation of interface to Pelican // // 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 "pelclass.h" /* #include "glist.h" #include "gvector.h" #include "complex.h" */ /*************************************************************/ /************** Implementation of class Pelview **************/ /*************************************************************/ node SaveList=0; void PelView::InitializePelicanMemory() const { // mimicking main in Shell.c LOCS(1); init_symbol_table(); node_init_store(); PUSH_LOC(SaveList); SaveList=node_new(); } Pring PelView::MakePring(const int num) const { char* q[] = {"","n1","n2" , "n3", "n4", "n5", "n6", "n7", "n8", "n9", "n10", "n11", "n12", "n13", "n14", "n15", "n16", "n17", "n18","n19", "n20", "n21", "n22", "n23", "n24", "n25", "n26", "n27", "n28","n29", "n30"}; Pring R = makePR(num); // makePR is a memory malloc routine for(int j=1; j<=R->n; j++) R->vars[j-1] = q[j]; R->def = "t"; R->n = num; return R; } void PelView::PrintPring(const Pring &ring) const { // gout << "The Pring has " << ring->n << " variables: "; for (int i = 1; i <= ring->n; i++) { // gout << ring->vars[i-1]; //if (i < ring->n) // gout << ", "; //else // gout << ".\n"; } // gout << " The homotopy variable is " << ring->def << ".\n"; } void PelView::Initialize_Idf_T_Gen_node(const Gen_node &node, const char * label) const { node->type=Idf_T; node->Genval.gval=Copy_String_NQ((char *)label); node->Genval.idval=Copy_String_NQ((char *)label); } Gen_node PelView::CreateRing(const int numvar) const { char* q[] = {" ", "","n1","n2" , "n3", "n4", "n5", "n6", "n7", "n8", "n9", "n10", "n11", "n12", "n13", "n14", "n15", "n16", "n17", "n18","n19", "n20", "n21", "n22", "n23", "n24", "n25", "n26", "n27", "n28","n29", "n30"}; Gen_node a1 = gen_node(); Initialize_Idf_T_Gen_node(a1,"n1"); Gen_node atemp; atemp = gen_node(); if (numvar == 1) a1->next= atemp; else { a1->next=NULL; atemp = a1; for(int j=2; j<=numvar; j++) { Gen_node a = gen_node(); Initialize_Idf_T_Gen_node(a,q[j]); a->next = NULL; atemp->next = a; atemp = a; } } atemp->next=NULL; Initialize_Idf_T_Gen_node(atemp,"t"); return a1; } polynomial1 PelView::GamPolyToPelPoly(const gPoly &p, const int n, const Pring ring) const { if ((p.MonomialList().Length() == 0)) { polynomial1 P; P = makeP(ring); P->coef.r=0; P->coef.i=0; for (int i=0;iR->n;i++) P->exps[i]=0; P->next= 0; return P; } else { polynomial1 P,Ptemp; P = makeP(ring); Ptemp= P; if (p.MonomialList()[1].IsConstant()) { Ptemp->coef.r= p.MonomialList()[1].Coef(); Ptemp->coef.i= 0; for (int i=0;iR->n;i++) Ptemp->exps[i]=0; Ptemp->next=0; } else { Ptemp->coef.r= p.MonomialList()[1].Coef(); Ptemp->coef.i= 0; for (int i=0;iR->n;i++) Ptemp->exps[i]= p.MonomialList()[1].ExpV() [i+1]; Ptemp->next=0; } for (int j = 2; j <=p.MonomialList().Length(); j++) { polynomial1 a; a = makeP(ring); if (p.MonomialList()[j].IsConstant()) { a->coef.r= p.MonomialList()[j].Coef(); a->coef.i= 0; for (int i=0;iR->n;i++) a->exps[i]=0; a->next = 0; Ptemp->next = a; Ptemp = a; } else { a->coef.r= p.MonomialList()[j].Coef(); a->coef.i= 0; for (int i=0;iR->n;i++) a->exps[i]= p.MonomialList()[j].ExpV() [i+1]; // printP(a); // cout; a->next = 0; Ptemp->next = a; Ptemp = a; } } return P; } } Gen_node PelView::CreatePelicanVersionOfSystem(const gPolyList &input, const Pring ring) const { Gen_node a; a = gen_node(); a->type= Mtx_T; a->next= NULL; Gmatrix V; V = Gmatrix_new(1, input.Length()); V->store = input.Length(); V->topc = input.Length(); V->ncols = input.Length(); V->topr=1; for(int j=1; j<=input.Length(); j++) { Gen_node b; b = gen_node(); b->type = Ply_T; b->next = NULL; b->Genval.pval=(GamPolyToPelPoly(input[j], input.Length(), ring)); b->Genval.gval=(char*) (GamPolyToPelPoly(input[j], input.Length(), ring)); b->Genval.idval=(char*) (GamPolyToPelPoly(input[j], input.Length(), ring)); (V->coords[j-1])= b; } a->Genval.gval=(char *)V; return G_System(a); } int PelView::GutsOfGetMixedVolume( node A, node norms, const Imatrix T) const { node ptr = 0, ptc = 0, res = 0; Imatrix M = 0, Tp = 0; int v, mv = 0, t = 0; LOCS(5); PUSH_LOC(A); PUSH_LOC(res); PUSH_LOC(ptc); PUSH_LOC(ptr); PUSH_LOC(norms); ptr = norms; while (ptr != 0) { ptc = aset_face(A, (Imatrix) Car((node) Car(ptr))); Tp = aset_type(ptc, Tp); if (T != 0 && Imatrix_equal(Tp, T) == TRUE) { t = 1; list_insert(Car(ptr),&res, &(list_Imatrix_comp),FALSE); } else t = 0; M = aset_M(ptc, M); if ( (Imatrix_rref(M, &v) == aset_dim(A) - 1) && (IMrows(M) == aset_dim(A) - 1) ) { if (t == 1) mv += abs(v); } ptr = Cdr(ptr); } Imatrix_free(Tp); Imatrix_free(M); POP_LOCS(); return mv; } int PelView::GetMixedVolume(const Gen_node g) const { aset A=0; Ivector T=0; int r = 0; int CP; int nargs; LOCS(2); PUSH_LOC(A); nargs=Gen_length(g); //Something happens right here and is necessary for the code, //but don't ask me what... if ((nargs ==0) || (nargs==1 && Can_Be_Aset(Gen_elt(g,1))!=TRUE )|| (nargs==2 && (r=Can_Be_Vector(Gen_elt(g,2),Int_T))<0)){ } A=Gen_aset(Gen_elt(g,1)); if (nargs==2 ) if (r==aset_r(A)) T=Gen_to_Imatrix(Gen_elt(g,2)); CP= GutsOfGetMixedVolume(A,aset_lower_facets(A),T); return CP; } Gen_node PelView::Make_scl_Gen_node() const { Gen_node g= gen_node(); g->type= Idf_T; g->next= NULL; g->Genval.gval= "scl"; g->Genval.idval= "scl"; return g; } Gen_node PelView::ToDmatrixGen_node(const Gen_node g) const { Gen_node a; psys PS; Dmatrix S; PS=Gen_to_psys(g); S=psys_scale(PS); a= Dmatrix_to_Gen(S); return a; } polynomial1 PelView::IdentityElementPoly(const Pring ring) const { polynomial1 P; P = makeP(ring); P->coef.r=1; P->coef.i=0; for (int i=0;iR->n;i++) P->exps[i]=0; P->def =0; P->next= 0; return P; } polynomial1 PelView::HomotopyVariableMonomialPoly(const Pring ring, const int comp) const { polynomial1 P; P = makeP(ring); P->coef.r=1; P->coef.i=0; P->remaining=0; P->homog=0; for (int i=0;iR->n;i++) P->exps[i]=0; P->def = comp; P->next= 0; return P; } Gen_node PelView::SolutionsDerivedFromContinuation(const Pring &ring, const Gen_node &Genpoly, const Gen_node &Solve, const Gen_node &pel_system, int tweak) const { pel_system->next = 0; Gen_node temp= Link(pel_system ,Make_scl_Gen_node()); Gen_node scl= ToDmatrixGen_node(temp); Gen_node fs = G_Scale(temp); // gout<< " Step 12 \n"; // polynomials used for the homothopy int unity = 1; Gen_node tee, one, tee1; tee = Ply_To_Gen(HomotopyVariableMonomialPoly(ring, unity)); one=Ply_To_Gen(IdentityElementPoly(ring)); tee1=Ply_To_Gen(HomotopyVariableMonomialPoly(ring, unity)); tee->next=0; one->next=0; // Define the homothopy // gout<< " Step 13 \n"; Gen_node h = PROC_MUL(Link(tee, fs)); Gen_node h1 = PROC_SUB(Link(one, tee1)); //A little trick Genpoly->next=0; Gen_node h2 = G_UnLift(Genpoly); // gout<< " Step 14 \n"; Gen_node h4 = PROC_MUL(Link(h1, h2)); Gen_node h5 = PROC_ADD(Link(h,h4)); Gen_node cs = G_Cont(Link(h5,G_UnLift(Solve)), tweak); // gout<< " Step 15 \n"; Gen_node sols = G_Affine(G_UnScale(Link(cs, scl))); free_Gen_list(scl); return sols; } template bool HasARedundancy(const Gambit::List &p_list) { int i = 1; int j = 2; while (i < p_list.Length()) { if (p_list[i] == p_list[j]) return true; else j++; if (j > p_list.Length()) { i++; j = i+1; } } return false; } //#define PELVIEW_DEBUG Gen_node PelView::SolveCheckMaybeTryAgain(const Pring &ring, const Gen_node &Genpoly, const Gen_node &Qtrig, const Gen_node &pel_system) { Gen_node sols, Solve; bool done(false); for (int tweak = 0; tweak <= 3 && !done; tweak ++) { Solve = G_Solve(Link(Genpoly, Qtrig), tweak); #ifdef PELVIEW_DEBUG print_Gen_list(Solve); // gout<< " \n Step 11 \n"; #endif sols = SolutionsDerivedFromContinuation(ring, Genpoly, Solve, pel_system, tweak); #ifdef PELVIEW_DEBUG // gout<<" \n The solution list produced by Pelican is:\n"; print_Gen_list(sols); #endif //The same little trick pel_system->next= 0; #ifdef PELVIEW_DEBUG // gout << "\n Step 12 \n"; #endif solutionsarecorrect = CheckSolutions(G_Verify(Link(pel_system,sols))); if (solutionsarecorrect && !HasARedundancy(GambitRootsFromPelRoots(sols))) done = true; if (!done) free_Gen_list(sols); #ifdef PELVIEW_DEBUG // gout << "The solutions are "; // if (!solutionsarecorrect) // gout << "not "; // gout << "correct.\n"; #endif } return sols; // gout<< "\n Solve \n"; print_Gen_list(Solve); // free_Gen_list(Solve); // Solve doesn't seem to exist at this point, yet this is very ambiguous. } Gambit::List > PelView::GambitRootsFromPelRoots(const Gen_node g) const { Gambit::List > alist; node ptr; ptr = Gen_to_Dvector_list(Gen_lval(copy_Gen_node(g))); Dmatrix P; int i; while(ptr!=0) { P=(Dmatrix)(Car(Car(ptr))); int numbervar; numbervar= (int)(DVlength(P)-3)/2; Gambit::Vector vector(1, numbervar); int j = 1; for(i=3; i > &complexroots) const { #ifdef UNUSED for (int k = 1; k <= complexroots.Length(); k++) for (int m = 1; m <= complexroots[k].Length(); m++) { if (m ==1) gout << "{"; for (int n = 1; n <= m; n++) gout << " "; gout << complexroots[k][m]; if (m < complexroots[k].Length()) gout << ",\n"; else gout << " }\n"; } #endif // UNUSED } int PelView::Dmnsn() const { return input.Dmnsn(); } Gambit::List > PelView::RealRoots(const Gambit::List > &clist) const { Gambit::List > answer; for (int i = 1; i <= clist.Length(); i++) { bool is_real = true; for (int j = 1; j <= Dmnsn(); j++) if (Gambit::abs(clist[i][j].ImaginaryPart()) > 0.0001) is_real = false; if (is_real) { Gambit::Vector next(Dmnsn()); for (int j = 1; j <= Dmnsn(); j++) next[j] = (double)clist[i][j].RealPart(); answer.Append(next); } } return answer; } bool PelView::CheckSolutions(const Gen_node g) const { Gen_node goo; goo = g->Genval.lval; while (goo!=0) { if (Gambit::abs(goo->Genval.dval) > 0.01) return 0; goo = goo->next; } return 1; } PelView::PelView(const gPolyList &mylist):input(mylist) { InitializePelicanMemory(); #ifdef PELVIEW_DEBUG // gout << "We begin with the polynomial list\n" << mylist << "\n"; #endif Pring ring = MakePring(input.Length()); #ifdef PELVIEW_DEBUG // gout<< " Step 1 \n"; PrintPring(ring); #endif Gen_node vic = Set_Ring((CreateRing(input.Length()+1))); #ifdef PELVIEW_DEBUG // gout<< "\n Step 2 \n"; print_Gen_node(vic); #endif // Gen_node pel_system = G_System(translate(input,ring)); Gen_node pel_system = CreatePelicanVersionOfSystem(input,ring); #ifdef PELVIEW_DEBUG // gout<< "\n\n Step 3 \n"; // gout << "The translated system is:\n"; print_Gen_node(pel_system); #endif Gen_node Atype= G_AType(pel_system); // Atype is the vector of numbers of #ifdef PELVIEW_DEBUG // gout<< " Step 4 \n"; print_Gen_list(Atype); // polys with each support type #endif Gen_node Aset = G_Aset(pel_system); #ifdef PELVIEW_DEBUG // gout<< "\n Step 5 \n"; // gout << "The list of unlifted vertex tuples is:\n"; print_Gen_node(Aset); #endif Gen_node Randlift = G_RandLift(Aset); #ifdef PELVIEW_DEBUG // gout<< "\n\n Step 6 \n"; // gout<< "After the random lift, the vertex tuples are:\n"; print_Gen_list(Randlift); // gout << "\n\n Step 7 \n"; // gout << "To see the cells in the subdivision, define ACTUALLY_PRINT in pelclqhl.cc:\n"; #endif Gen_node Qtrig = G_Qtrig(Link(Randlift, Atype)); /* - There is a commented out error in node_push_local that was triggered by this in various conditions. In particular, commented out the final print avoids the error, somehow!! // gout<< "\n Step 8 \n"; // gout<< "Before Randlift is "; // gout << Randlift << "\n"; silent_print_Gen_list(Randlift); // gout<< "After Randlift is " << Randlift << "\n"; */ mixedvolume = GetMixedVolume(Randlift); #ifdef PELVIEW_DEBUG // gout<< "\n Step 8 \n"; // gout << "The mixed volume is " << mixedvolume << ".\n"; #endif Gen_node Genpoly = G_Gen_Poly(Randlift); #ifdef PELVIEW_DEBUG // gout<< "\n Step 9 \n"; // gout << "The homotopy system is:\n"; print_Gen_list(Genpoly); // gout<< "\n Step 10 \n"; // gout << "The Gen_node Solve (solutions of start system) is: \n"; #endif Gen_node sols = SolveCheckMaybeTryAgain(ring, Genpoly, Qtrig, pel_system); complexroots = GambitRootsFromPelRoots(sols); #ifdef PELVIEW_DEBUG // gout << "\n Step 13 \n"; // gout<<" After conversion to Gambit, the complex roots are...\n"; DisplayComplexRootList(complexroots); #endif realroots = RealRoots(complexroots); #ifdef PELVIEW_DEBUG // gout << "\n Step 14 \n"; // gout<<" The real solutions are...\n"; // for (int k = 1; k <= realroots.Length(); k++) // gout << realroots[k] << "\n"; // gout<< "\n Step 15 \n"; // gout<< "\n Memory testing \n"; print_Gen_list(Genpoly); #endif free_Gen_list(Genpoly); #ifdef PELVIEW_DEBUG // gout<< "\n Qtrig \n"; print_Gen_list(Qtrig); #endif free_Gen_list(Qtrig); free_Gen_list(vic); free_Gen_list(sols); #ifdef PELVIEW_DEBUG // gout << "And the memory should be clean...\n"; #endif } PelView::PelView(const PelView & given) : input(given.input), complexroots(given.complexroots), realroots(given.realroots), mixedvolume(given.mixedvolume), solutionsarecorrect(given.solutionsarecorrect) { } PelView::~PelView() { } PelView& PelView::operator =(const PelView &rhs) { // gout << "For (eventual) const'ness, operator = not allowed for PelView\n"; exit (0); return *this; } bool PelView::operator ==(const PelView &rhs) const { return (input == rhs.input && complexroots == rhs.complexroots && realroots == rhs.realroots && mixedvolume == rhs.mixedvolume && solutionsarecorrect == rhs.solutionsarecorrect); } bool PelView::operator !=(const PelView &rhs) const { return !(*this == rhs); } Gambit::List > PelView::ComplexRoots() const { return complexroots; } Gambit::List > PelView::RealRoots() const { return realroots; } int PelView::MixedVolume() const { return mixedvolume; } int PelView::NumComplexRoots() const { return complexroots.Length(); } bool PelView::FoundAllRoots() const { return (NumComplexRoots() == MixedVolume()); } int PelView::NumRealRoots() const { return realroots.Length(); } /**********************************************************************/ // was the original main in the pelican driver int old_main() { //stuff for Gambit-text to Gambit-data for (int loop = 1; loop <= 3; loop++) { gSpace Space(4); ORD_PTR ptr = &lex; term_order Lex(&Space, ptr); ptr = &reversedeglex; term_order ReverseDegLex(&Space, ptr); ptr = &reverselex; term_order ReverseLex(&Space, ptr); //Default system std::string gx = " 2 + n2 "; std::string gy = " 1 + 78 * n1 + 2 * n2 + n4 * n1^2"; std::string gz = " 3 + n3 + n4"; std::string gu = " 4 * n1 - n2 * n3 + 6 * n1 * n4^3"; gPoly px(&Space,gx,&Lex); gPoly py(&Space,gy,&Lex); gPoly pz(&Space,gz,&Lex); gPoly pu(&Space,gu,&Lex); gPolyList mylist(&Space, &ReverseDegLex); mylist += px; mylist += py; mylist += pz; mylist += pu; PelView atlast(mylist); gSpace NewSpace(3); ptr = &lex; term_order NewLex(&NewSpace, ptr); ptr = &reversedeglex; term_order NewReverseDegLex(&NewSpace, ptr); ptr = &reverselex; term_order NewReverseLex(&NewSpace, ptr); //Default system std::string newgx = " 2 + n2 "; std::string newgy = " 1 + 78 * n1 + 2 * n2 + n3 * n1^2"; std::string newgz = " 3 + n3"; gPoly newpx(&NewSpace,newgx,&NewLex); gPoly newpy(&NewSpace,newgy,&NewLex); gPoly newpz(&NewSpace,newgz,&NewLex); gPolyList mynewlist(&NewSpace, &NewReverseDegLex); mynewlist += newpx; mynewlist += newpy; mynewlist += newpz; PelView newatlast(mynewlist); } return 0; } gambit-0.2010.09.01/src/tools/enumpoly/pelclass.h0000644000076500007650000001020211435216102016204 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/pelclass.h // Declaration of interface to Pelican // // 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 #include "gpolylst.h" /* extern "C" { */ #include "pelprgen.h" /* } */ /*************************************************************/ /*********************** The class PelView *******************/ /*************************************************************/ class PelView { private: gPolyList input; Gambit::List > complexroots; Gambit::List > realroots; int mixedvolume; bool solutionsarecorrect; // All private routines contribute to the constructor // void InitializePelicanMemory() const; Pring MakePring(const int num) const; void PrintPring(const Pring &ring) const; void Initialize_Idf_T_Gen_node(const Gen_node &node, const char * label) const; Gen_node CreateRing(const int numvar) const; polynomial1 GamPolyToPelPoly(const gPoly &p, const int n, const Pring ring) const; Gen_node CreatePelicanVersionOfSystem(const gPolyList &input, const Pring ring) const; int GutsOfGetMixedVolume( node A, node norms, const Imatrix T) const; int GetMixedVolume(const Gen_node g) const; // Routines associated with the homotopy continuation Gen_node Make_scl_Gen_node() const; Gen_node ToDmatrixGen_node(const Gen_node g) const; polynomial1 IdentityElementPoly(const Pring ring) const; polynomial1 HomotopyVariableMonomialPoly(const Pring ring, const int comp) const; Gen_node SolutionsDerivedFromContinuation(const Pring &ring, const Gen_node &Genpoly, const Gen_node &Solve, const Gen_node &pel_system, int tweak) const; Gen_node SolveCheckMaybeTryAgain(const Pring &ring, const Gen_node &Genpoly, const Gen_node &Qtrig, const Gen_node &pel_system) ; Gambit::List > GambitRootsFromPelRoots(const Gen_node g) const; void DisplayComplexRootList(const Gambit::List > &) const; Gambit::List > RealRoots(const Gambit::List > &) const; bool CheckSolutions(const Gen_node g) const; public: PelView(const gPolyList &mylist); PelView(const PelView &); ~PelView(); PelView &operator = (const PelView &); bool operator == (const PelView &) const; bool operator != (const PelView &) const; int Dmnsn() const; Gambit::List > ComplexRoots() const; Gambit::List > RealRoots() const; int MixedVolume() const; int NumComplexRoots() const; bool FoundAllRoots() const; int NumRealRoots() const; }; int old_main(); gambit-0.2010.09.01/src/tools/enumpoly/pelclhpk.cc0000644000076500007650000000676711350032206016360 00000000000000/*------------------------------------------------------------------- Call_Hompack.c created 9/15/1994 last modified 9/15/1994 Birk Huber (birk@math.cornell.edu ALL RIGHTS RESERVED This File represents the interface between Pelican and Hompacks FIXPNF path tracker. The HOMPACK routines it calls have actually been translated from fortran into c with f2c and then modified a little so as not to require the f2c library. The two routines the user needs to be aware of are init_HPK which takes a pelican Pvector, converts it to "tableau" format, and initialies all the nescessary global variables to represent the homotopy. Call_HPK_Hom wich takes a double vector and uses it as a starting point for path continuation. --------------------------------------------------------------------*/ #include "pelclhpk.h" #define X(i) (DVref(X,i)) int HPK_cont(Dvector X, int tweak) { int i, ist, dst,N,N1; static int iflag,trace,nfe,*pivot,*ipar; static double *yold,*a,arcae; static double *qr, arclen, *wp, *yp, *tz,*par,*z0,*z1; static double ansre, *ypold, *sspar,*alpha,ansae,*w,*y,arcre; /* extern int fixpnf_(); IN Homotopies.h */ if (Hom_defd!=1) return 0; /* save start of free storage space */ ist=Itop(); dst=Dtop(); /* init numbers of real eqs with and without hom param*/ N=2*Hom_num_vars; N1=N+1; /* get space for local arrays from store */ ipar=Ires(1); pivot=Ires(N1); yold=Dres(N1); a=Dres(N1); alpha=Dres(N1); w=Dres(N1); y=Dres(N1); ypold=Dres(N1); sspar=Dres(8); z0=Dres(N1); z1=Dres(N1); qr=Dres(N*(N1+1)); wp=Dres(N1); yp=Dres(N1); tz=Dres(N1); par=Dres(1); /* initialize parameters */ iflag = -2; /* should not be changed switch to tell hompack to do path tracking*/ arcre = -1.; arcae = -1.; /* errors allowed during normal flow iteration will be automatically reset to appropriat values later*/ ansre = Hom_tol; ansae = Hom_tol; trace = 1; /* 1 keep a log , 0 dont */ nfe = 10; /* I am not sure what this one is for */ for(i=0;i<8;i++) sspar[i] = -1.; /* sspar holds a number of flags used to determine optimal step size, set to -1 will cause hompack to choose them by its own heuristics */ Htransform(X); /* print Starting point to Log File*/ print_proj_trans(); for(i=1;i<=N+3;i++) #ifdef CHP_PRINT fprintf(Hom_LogFile,"S %g", X(i)); fprintf(Hom_LogFile," 0 \n") #endif ; y[0]=X(N+3);/* y0 holds the initial deformation parameter */ for(i=3;i<=N+2;i++){ /* y1 and on hold the starting coordinates */ y[i-2]=X(i); } fixpnf_(&N, y, &iflag, &arcre, &arcae, &ansre, &ansae, &trace, a, &nfe, &arclen, yp, yold, ypold, qr, alpha, tz, pivot, w, wp, z0, z1, sspar, par, ipar, tweak); /* tweak is used to refine step size */ /* #ifdef CHP_PRINT fprintf(Hom_OutFile,"Done arclen=%f, LAMBDA=%f, return flag %d\n", arclen,y[0],iflag) #endif */ ; for(i=1;i<=N;i++) X(i+2)=y[i]; X(N+3)=y[0]; Huntransform(X); /* print ending point to log file */ #ifdef CHP_PRINT fprintf(Hom_LogFile,"E") #endif ; for(i=1;i<=N+3;i++) #ifdef CHP_PRINT fprintf(Hom_LogFile," %g", X(i)) #endif ; #ifdef CHP_PRINT fprintf(Hom_LogFile," 4 1 %d %f %f",iflag,arclen,y[0]); fprintf(Hom_LogFile,"\n") #endif ; /*free space*/ Ifree(ist), Dfree(dst); return 0; } #undef X gambit-0.2010.09.01/src/tools/enumpoly/pelclhpk.h0000644000076500007650000000350611350032206016206 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /*------------------------------------------------------------------- Call_Hompack.c created 9/15/1994 last modified 9/15/1994 Birk Huber (birk@math.cornell.edu ALL RIGHTS RESERVED This File represents the interface between Pelican and Hompacks FIXPNF path tracker. The HOMPACK routines it calls have actually been translated from fortran into c with f2c and then modified a little so as not to require the f2c library. The two routines the user needs to be aware of are init_HPK which takes a pelican Pvector, converts it to "tableau" format, and initialies all the nescessary global variables to represent the homotopy. Call_HPK_Hom wich takes a double vector and uses it as a starting point for path continuation. --------------------------------------------------------------------*/ #ifndef CALL_HPK_H #define CALL_HPK_H #include "pelhomot.h" void print_proj_trans(); int HPK_cont(Dvector X, int tweak); #endif /* CALL_HPK_H */ gambit-0.2010.09.01/src/tools/enumpoly/pelclqhl.cc0000644000076500007650000001732411350032206016351 00000000000000/* ** Call_Qhull.h ** Old code calling qhull to find a mixed subdivision ** ** copyright (c) 1995 Birk Huber */ #include "pelclqhl.h" #include "pelqhull.h" /* ** node pcfg_facets(node PC, Imatrix Controll) ** Return a list of the inner-normals of the facets of a point ** configuaration PC. Uses Control as input to pcfg_good ** facets (see bellow) to screen for facets whoose normals ** obey certain conditions. */ #define FORALLfacet_(facetlist) if (facetlist) for(facet=(facetlist);facet && facet->next;facet=facet->next) node pcfg_facets(node PC, Imatrix Controll) { int curlong, totlong, exitcode, i, j, k; int D, N; coordT *points, *make_cay(node, boolT *, node **); boolT ismalloc; facetT *facet; vertexT *vertex, **vertexp; node NormList = 0, *pt_table; Imatrix M, Norm, P0, P1; LOCS(2); PUSH_LOC(PC); PUSH_LOC(NormList); N = pcfg_npts(PC); D = pcfg_dim(PC); M = Imatrix_new(N, D); Norm = Ivector_new(D); M = pcfg_M(PC, M); j = Imatrix_rref(M, &i); if (j <= D - 1) { if (j == D - 1) { /* printf("point config is D-1 dim\n"); */ Imatrix_backsolve(M, Norm); Imatrix_gcd_reduce(Norm); /* printf("Imatrix norm : "); Imatrix_print(Norm); printf("\n"); */ if (is_normal_good(Norm, Controll) != True) { for (i = 1; i <= D; i++) *IVref(Norm, i) *= -1; } if (is_normal_good(Norm, Controll) == True) NormList = Cons(atom_new((char *) Norm, IMTX), 0); else Imatrix_free(Norm); } else { bad_error("point config is low dim in pcfg_facets"); printf("point config is low dim \n"); Imatrix_free(Norm); } Imatrix_free(M); POP_LOCS(); /* printf("leaving qhull with low D:"); node_print(NormList); printf("\n"); */ return NormList; } qh_meminit(stderr); qh_initqhull_start(stdin, stdout, stderr); if (!(exitcode = setjmp(qh errexit))) { strcpy(qh qhull_command, "qhull i Qs Pg Pp"); qh_initflags(qh qhull_command); points = make_cay(PC, &ismalloc, &pt_table); qh_initqhull_globals(points, N, D, ismalloc); qh_initqhull_mem(); /* mem.c and set.c are initialized */ qh_initqhull_buffers(); /* setting up treshold to ensure that good facets will be those on the lower hull with respecto to the last coordinate */ qh_qhull(); qh_findgood_all(qh facet_list); FORALLfacet_(qh facet_list) { if (facet->good) { k = 0; FOREACHvertex_(facet->vertices) { if (k == 0) P0 = pnt_coords(pt_table[qh_pointid(vertex->point)]); else { P1 = pnt_coords(pt_table[qh_pointid(vertex->point)]); for (i = 1; i <= pcfg_dim(PC); i++) { *IMref(M, k, i) = *IVref(P1, i) - *IVref(P0, i); } } k++; } Imatrix_submat(M, k - 1, pcfg_dim(PC)); Imatrix_rref(M, &i); Imatrix_backsolve(M, Norm); for (i = 1; (*IVref(Norm, i) == 0) && i <= IVlength(Norm); i++); if ((facet->normal[i - 1] * (*IVref(Norm, i))) > 0.0) { for (i = 1; i <= IVlength(Norm); i++) { *(IVref(Norm, i)) = -1 * (*IVref(Norm, i)); } } if (is_normal_good(Norm, Controll) == True) { list_insert(atom_new((char *) Norm, IMTX), &NormList, &(list_Imatrix_comp),FALSE); Norm = Ivector_new(pcfg_dim(PC)); } } } exitcode = qh_ERRnone; } qh NOerrexit = True; /* no more setjmp */ qh_freeqhull(False); qh_memfreeshort(&curlong, &totlong); if (curlong || totlong) #ifdef LOG_PRINT fprintf(stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong) #endif ; mem_free((char *) pt_table); Imatrix_free(M); Imatrix_free(Norm); POP_LOCS(); return NormList; } coordT *make_cay(node PC, boolT * ismalloc, node ** table) { int i, j; coordT *points, *coords; node ptr = PC, *lptr; coords = points = (coordT *) malloc(pcfg_npts(PC) * pcfg_dim(PC) * sizeof(coordT)); *table = lptr = (node *) mem_malloc(pcfg_npts(PC) * sizeof(node)); if (coords == 0) { *ismalloc = False; return 0; } *ismalloc = True; for (i = 1; i <= pcfg_npts(PC); i++) { ptr = Cdr(ptr); *(lptr++) = Car(ptr); for (j = 1; j <= pcfg_dim(PC); j++) { *(coords++) = *(IVref(pnt_coords(Car(ptr)), j)); } } return points; } node aset_cayley(node A,int addlift) { node res = 0, ptr = A, ptp, ptc; int r = 0, R, D, i; char *lab; char *amm_string; Imatrix C; LOCS(2); PUSH_LOC(A); PUSH_LOC(res); D = aset_dim(A); if (addlift==1)addlift=1; else addlift=0; R = aset_r(A); ptr = aset_start_cfg(A); res = pcfg_new(); while ((ptc = aset_next_cfg(&ptr)) != 0) { r++; while ((ptp = aset_next_pnt(&ptc)) != 0) { C = Ivector_new(D + R - 1 + addlift); if(addlift==1) *IVref(C,D+R)=0; for (i = 1; i < D; i++) *IVref(C, i) = aset_pnt_get(ptp, i); for (i = 1; i <= R - 1; i++) if (r - 1 == i) *IVref(C, D + i-1) = 1; else *IVref(C, D + i-1) = 0; *IVref(C,D+R-1)=aset_pnt_get(ptp,D); lab = (char *)mem_malloc(6 * sizeof(char)); amm_string = pnt_label(ptp); /* strncpy(lab, amm_string,6); - ERROR */ /* Therefore I fake it as follows - AMM */ for (i = 0; i <= 5; i++) if (i < (int)strlen(amm_string)) lab[i] = amm_string[i]; else lab[i] = '\0'; pcfg_add(pnt_new(lab, C), res); } } POP_LOCS(); return res; } node aset_lower_facets(node A) { node res = 0, cay = 0; Imatrix Normfilter; int i; LOCS(3); PUSH_LOC(A); PUSH_LOC(res); PUSH_LOC(cay); cay = aset_cayley(A,0); Normfilter = Ivector_new(aset_dim(A) + aset_r(A)-1); for (i = 1; i < aset_dim(A) + aset_r(A)-1; i++) *IVref(Normfilter, i) = 0; *IVref(Normfilter, aset_r(A)+aset_dim(A)-1) = 2; res = pcfg_facets(cay, Normfilter); cay = res; while (cay != 0) { *IVref((Imatrix) Car(Car(cay)),aset_dim(A)) = *IVref((Imatrix) Car(Car(cay)), aset_dim(A)+aset_r(A)-1); Imatrix_resize((Imatrix) Car(Car(cay)), 1, aset_dim(A)); cay = Cdr(cay); } Imatrix_free(Normfilter); POP_LOCS(); return res; } /* #define ACTUALLY_PRINT */ node aset_print_subdiv(node A, node norms, Imatrix T) { // int i; node ptr = 0, ptc = 0, res = 0; Imatrix M = 0, Tp = 0; int v, mv = 0, t = 0; LOCS(5); PUSH_LOC(A); PUSH_LOC(res); PUSH_LOC(ptc); PUSH_LOC(ptr); PUSH_LOC(norms); ptr = norms; #ifdef ACTUALLY_PRINT printf("\n"); #endif while (ptr != 0) { /* Imatrix_gcd_reduce((Imatrix)Car((Imatrix)Car(ptr))); */ ptc = aset_face(A, (Imatrix) Car((node) Car(ptr))); #ifdef ACTUALLY_PRINT aset_print_short(ptc); printf(" "); #endif Tp = aset_type(ptc, Tp); #ifdef ACTUALLY_PRINT printf(" < %d",*IVref(Tp,1)); for(i=2;i<=IVlength(Tp);i++) printf(", %d",*IVref(Tp,i)); printf(" > "); printf(" "); #endif if (T != 0 && Imatrix_equal(Tp, T) == TRUE) { t = 1; list_insert(Car(ptr),&res, &(list_Imatrix_comp),FALSE); } else t = 0; M = aset_M(ptc, M); if ( (Imatrix_rref(M, &v) == aset_dim(A) - 1) && (IMrows(M) == aset_dim(A) - 1) ) { #ifdef ACTUALLY_PRINT printf(" vol = %d", abs(v)); #endif if (t == 1) mv += abs(v); } #ifdef ACTUALLY_PRINT printf("\n"); #endif ptr = Cdr(ptr); } if (T != 0) #ifdef ACTUALLY_PRINT printf("MV =%d\n", mv); #endif Imatrix_free(Tp); Imatrix_free(M); POP_LOCS(); return res; } gambit-0.2010.09.01/src/tools/enumpoly/pelclqhl.h0000644000076500007650000000204511350032206016205 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* ** copyright (c) 1995 Birk Huber */ #include "pelutils.h" node pcfg_facets(node PC,Imatrix Controll); aset aset_cayley(aset,int); node aset_print_subdiv(aset,node, Imatrix); node aset_lower_facets(aset); gambit-0.2010.09.01/src/tools/enumpoly/pelclyal.cc0000644000076500007650000010756611350032206016362 00000000000000/* cly_all.c */ #include "pelclyal.h" /************************************************************************/ /****************** implementation code from cly_cells.c ****************/ /************************************************************************/ /* ****************************************************************** ** Global Variables ****************************************************************** */ int cly_Npts=0; /* the number of points in the config */ int cly_N=0; /* the dimension of the cayley point config */ int cly_R=0; /* the number of point configs */ int cly_Dim=0; /* the dimension of the Aset */ int next_id=1; /*for debuging cells are labled by a unique id*/ /* ** The matrices here are used for now to avoid problems, ** they will eventually be stored with the individual cells. */ HMatrix cly_U=0; /* factor matrix */ HMatrix cly_M=0; /* an n+1xn+1 matrix */ HMatrix cly_L=0; /* an n+1 vector */ Imatrix cly_T=0; /* an R vector */ /* ** two temporary variables used by the Hint macroes */ Hint cly_temp; int cly_det; /* ** controll parameters ** */ int cly_order=TRUE; int cly_lift=TRUE; /* ** Display functions: mainly for debugging ** Ipnt_print print complete list of data fields. ** Ipnt_list_print print list print lables of all points accesable ** from a given points through nex pointers */ void Ipnt_fprint(FILE *fout,Ipnt p){ int i; #ifdef LOG_PRINT fprintf(fout,"%% %s,",Ipnt_lable(p)) #endif ; for (i=1;i<=cly_N;i++) #ifdef LOG_PRINT fprintf(fout,"%d, ",Ipnt_coord(p,i)) #endif ; #ifdef LOG_PRINT fprintf(fout,"lift = %d, idx =%d \n",Ipnt_lift(p),Ipnt_idx(p)) #endif ; } void Ipnt_list_fprint(FILE *fout,Ipnt p){ #ifdef LOG_PRINT fprintf(fout,"%%{Pl\n") #endif ; for(;p!=0;p=Ipnt_next(p)) Ipnt_fprint(fout,p); #ifdef LOG_PRINT fprintf(fout,"%%Pl}\n") #endif ; } /* ** Creator/Destructor */ Ipnt Ipnt_new(node pnt,int r){ Ipnt p; int j; p=(Ipnt)mem_malloc(sizeof(struct Ipnt_t)); if (p==0) bad_error("malloc 1 failed in new_Ipnt"); p->point=pnt; p->idx=r; p->lable=(char *)mem_strdup(pnt_lable(pnt)); p->coords=(int *)mem_malloc(cly_N*sizeof(int)); if (p==0) bad_error("malloc 2 failed in new_Ipnt"); for(j=1;j<=cly_Dim;j++) Ipnt_coord(p,j)=*IVref(pnt_coords(pnt),j); for(j=cly_Dim+1;j<=cly_N;j++) Ipnt_coord(p,j)=0; if (r>1) Ipnt_coord(p,cly_Dim+r-1)=1; p->lift=0; p->next=0; return p; } void Ipnt_free(Ipnt p){ if (p!=0){ mem_free(p->lable); mem_free((char*)(p->coords)); mem_free((char *)p); } } void points_free(Ipnt p){ Ipnt jk; while(p!=0){ jk=p; p=Ipnt_next(p); Ipnt_free(jk); } } void lift_original_points(Ipnt p){ for( ;p!=0; p=Ipnt_next(p)) *IVref(pnt_coords(Ipnt_pnt(p)),cly_Dim+1)=Ipnt_lift(p); } /************************************************************** ** functions for basic acces and manipulation of cells. ***************************************************************/ /* ** cell_new(int n,int r) ** reserve space for a new cell, for holding an n-simplex ** the points and pointers fields are initialized to null */ cell cell_new(int n,int r){ cell c; int i; if ((c=(cell)mem_malloc(sizeof(struct cell_t)))==0) bad_error("malloc failed in cell_new()"); if ((c->points=(Ipnt *)mem_malloc((n+1)*sizeof(Ipnt)))==0) bad_error("malloc failed in cell_new()"); if ((c->ptrs=(cell *)mem_malloc((n+1)*sizeof(cell)))==0) bad_error("malloc failed in cell_new()"); c->H=HMnew(n,n+1); c->U=HMnew(n,n); c->T=Ivector_new(r); c->norm=HVnew(n+1); c->n=n; c->r=r; c->id=next_id++; c->freeptrs=n+1; c->volume=0; c->Tindx=0; c->next=0; for(i=0;i<=n;i++) {c->ptrs[i]=0; c->points[i]=0;} return c; } /* ** cell_free(cell c) ** free space allocated for a cell ** (does not effect any of the objects pointed to by the ** points or pointers fields). */ void cell_free(cell c){ if (c!=0){ mem_free((char *)c->points); mem_free((char *)c->ptrs); HMfree(c->norm); Imatrix_free(c->T); HMfree(c->U); HMfree(c->H); mem_free((char *)c); } } void subdiv_free(cell c){ cell jk; while(c!=0){ jk=c; c=cell_next(c); cell_free(jk);} } /* ** cell_print(cell c)- print the contents of a single cell. */ void cell_fprint(FILE *fout, cell c){ int i,k,tog; #ifdef LOG_PRINT fprintf(fout,"%% {") #endif ; for(k=1;k<=cly_R;k++){ #ifdef LOG_PRINT fprintf(fout,"{") #endif ; tog=0; for (i=0;i<=c->n;i++){ if (Ipnt_idx(cell_pnt(c,i))==k){ if (tog==0) tog=1; else printf(","); #ifdef LOG_PRINT fprintf(fout," %s",Ipnt_lable(cell_pnt(c,i))) #endif ; } } #ifdef LOG_PRINT fprintf(fout,"}") #endif ; if (k vol=%d",cell_volume(c)); fprintf(fout,"\n") #endif ; } /* ** subdiv_print(cell c)- print contents of all cells in a ** subdivision, a list of cells linked through their next fields */ void subdiv_fprint(FILE *fout, cell c){ #ifdef LOG_PRINT fprintf(fout,"\n") #endif ; while(c!=0){ cell_fprint(fout,c); c=cell_next(c); } } /* ** point_is_in(Ipnt pt, cell c) ** Input: a point pt, ** a cell c. ** Output: TRUE if cell contains pt ** FALSE otherwise. ** (a point is determined by its memory address, points with same ** coordinates and lables but stored in diferent places are still ** distinct). */ int point_is_in(Ipnt pt, cell c){ int i; for(i=0;i<=cell_n(c);i++) if (pt==cell_pnt(c,i)) return TRUE; return FALSE; } int cell_type_cmp(cell c1,cell c2){ int i,t; if (c1==0 && c2==0) return 0; else if (c1==0) return 1; else if (c2==0) return -1; for(i=1;i<=cly_R;i++){ t=cell_type(c1,i)-cell_type(c2,i); if (t!=0) return t; } return 0; } void order_subdiv(cell *Subdiv){ cell Res=0,S=*Subdiv, ptr=0,pts=0; while(S!=0){ pts=S; S=cell_next(S); if (Res==0 || cell_type_cmp(pts,Res)>=0){ cell_next(pts)=Res; Res=pts; } else { ptr=Res; while(cell_next(ptr)!=0 && cell_type_cmp(pts,cell_next(ptr))<0){ ptr=cell_next(ptr); } cell_next(pts)=cell_next(ptr); cell_next(ptr)=pts; } } *Subdiv=Res; } int fprint_all_volumes(FILE *fout,cell S){ int vol=0, i; while(S!=0){ vol+=cell_volume(S); if (cell_next(S)==0 || cell_type_cmp(S,cell_next(S))!=0){ #ifdef LOG_PRINT fprintf(fout,"%% Vol( %d", cell_type(S,1)) #endif ; for(i=2;i<=cly_R;i++) #ifdef LOG_PRINT fprintf(fout,", %d",cell_type(S,i)) #endif ; #ifdef LOG_PRINT fprintf(fout,")= %d\n",vol) #endif ; vol=0; } S=cell_next(S); } return 1; } int cell_set_volume(cell c){ int i,j,r,row; cly_T=Imatrix_resize(cly_T,1,cly_R); cly_U=HMresize(cly_U,cly_Dim,cly_Dim); cly_M=HMresize(cly_M,cly_Dim,cly_Dim); for(i=1;i<=cly_R;i++)*IVref(cly_T,i)=-1; row=1; for(i=0;i<=cly_N;i++){ r=Ipnt_idx(cell_pnt(c,i)); if (*IVref(cly_T,r)==-1){ *IVref(cly_T,r)=i; } else{ for(j=1;j<=cly_Dim;j++){ HLMset(cly_M,row,j,cell_point(c,i,j)-cell_point(c,*IVref(cly_T,r),j)); } row++; } } HMdet(cly_M,cly_U,r); return (cell_volume(c)=r); } /* ** subdiv_union ** Input: subdivisions SD1 and SD2 ** Output: SD2 appended to SD1. ** Side Effects: if SD1 is not null SD1 also points to union. */ cell cly_subdiv_union(cell SD1, cell SD2){ cell ptr=SD1; if (SD1==0) return SD2; while(cell_next(ptr)!=0) ptr=cell_next(ptr); cell_next(ptr)=SD2; return SD1; } /* end cly_cells.c */ /************************************************************************/ /***************** implementation code from cly_initial.c ***************/ /************************************************************************/ /******************************************************************* ** Initial Simplex Program *******************************************************************/ /* ** cell Initial_simplex(node *S1, node *S2){ ** ** input: ** A list of points S1. ** ** output: ** NULL if "PC" lies in a hyperplane. ** A full dimensional simplex (S) from "PC" otherwise. ** ** effects: ** "B" points to a list containing all points of "PC" ** wich are not in (S). ** ** method: ** a) initialize (S) with upper and lower hulls of PC with ** respect to the first standard basis vector ei. ** b) repeatedly calculate a normal (N) to the span of (S), ** and add one of the extreme points of PC (with respect ** to (N)) which does not already lie in the span of (S). */ static int check_normal(Ipnt,HMatrix,Ipnt *,Ipnt *); #define CU cell_U(initial) #define CM cell_H(initial) #define CL cell_norm(initial) cell cly_initial_splx(Ipnt *S1, Ipnt *S2){ cell initial; int i,r,j; Ipnt ptr=*S1,refpt=0,newpt,tmp; initial=cell_new(cly_N,cly_R); /* ** Initialize global matrices ** M will represent the linear space spanned by points ** allready chosen. (this will be an invarient of the loop). ** L will hold the next search direction, originally (0,...,0,1) */ HMresize(CU,1,1); HMresize(CL,1,cly_N); HMresize(CM,1,cly_N); HLVset(CL,1,1); for(i=2;i<=cly_N;i++) HLVset(CL,i,0); /* ** find two points not normal to CL=(0,....,0,1); and update M */ if (check_normal(ptr,CL,&refpt,&newpt)==FALSE) return FALSE; cell_pnt(initial,0)=refpt; cell_pnt(initial,1)=newpt; for(i=1;i<=cly_N;i++) HLMset(CM,1,i,cell_point(initial,1,i)-cell_point(initial,0,i)); r=1; while (++r<=cly_N){ /* ** Calculate new search direction L ** (normal to affine span of points allready chosen) */ HMfactor(CM,CU); HMbacksolve(CM,CL); HMgcd_reduce(CL); /* ** if possible pick a new point not in the same hyperplane, ** normal to L, as points allready chosen. */ if (check_normal(ptr,CL,&refpt,&newpt)==FALSE){ #ifdef LOG_PRINT fprintf(stderr /* was cly_err */,"Failure in initial_simplex():"); fprintf(stderr /* was cly_err */,"Point Config is not full dimensional\n") #endif ; return 0; } cell_pnt(initial,r)=newpt; CM=HMsubmat(CM,r,cly_N); CU=HMresize(CU,r,r); for(i=1;i<=cly_N;i++) HLMset(CM,r,i,cell_point(initial,r,i)-cell_point(initial,0,i)); } /* ** reset sizes for matrices in cell */ HMresize(cell_norm(initial),1,cly_N+1); HMresize(cell_U(initial),cly_N,cly_N); HMresize(cell_H(initial),cly_N,cly_N+1); /* ** set normal to initial simplex ** (it is unlifted so norm = (0,...,0,1) */ for(i=1;i<=cly_N;i++) HLVset(cell_norm(initial),i,0); HLVset(cell_norm(initial),cly_N+1,1); /* set up type vector */ for(i=1;i<=cly_R;i++) cell_type(initial,i)=-1; for(i=0;i<=cly_N;i++) cell_type(initial,Ipnt_idx(cell_pnt(initial,i)))++; /* ** setup factorization matrix CU[v1-v0,....,vn-v0,0]=H */ for(i=1;i<=cly_N;i++){ for(j=1;j<=cly_N;j++){ HLMset(cell_H(initial),j,i, cell_point(initial,i,j)-cell_point(initial,0,j)); } HLMset(cell_H(initial),i,cly_N+1,0); } HMfactor(cell_H(initial),cell_U(initial)); if (HLeq(HMget(cell_H(initial),cly_N,cly_N),0)){ bad_error("initial simplex not full d"); } cell_set_volume(initial); /* ** Set S2=points in initial simplex. ** S1=S1/S2. */ ptr=*S1; *S1=0; *S2=0; while(ptr!=0){ int In=FALSE; for(i=0;i<=cly_N;i++){ if(ptr==cell_pnt(initial,i)) In=TRUE; } tmp=ptr; ptr=Ipnt_next(ptr); if (In==FALSE) { Ipnt_next(tmp)=*S1; *S1=tmp; } else{ Ipnt_next(tmp)=*S2; *S2=tmp; } } return initial; } /* ** int check_normal(node PC,Imatrix norm, node *refpt, node *newpt){ ** ** (auxilary function for initial_simplex) ** ** input: ** A point configuration "PC" ** A normal direction "N" and a reference point "refpt" ** (if "refpt" is null, "refpt" gets initalized to point ** to a point on the lower hull) ** ("norm" and "refpt" together determin a hyperplane H) ** ** output: ** FALSE if the point configuration lies hyperplane normal to N ** TRUE otherwise. ** ** side effects: ** "newpt" holds a point which has maximal distance from (H). ** if refpt was null it gets initialized (see "input"). ** ** method: just computes dot products and save a point acheiving ** maximum and minimum values. ** then compair these against value for refpt. */ static int check_normal(Ipnt PC, HMatrix norm, Ipnt *refpt, Ipnt *newpt){ Hint dot,dmin,dmax; int i,first=TRUE; Ipnt pmin = NULL; Ipnt pmax = NULL; Hinit(dot,0); Hinit(dmin,0); Hinit(dmax,0); while(PC!=0){ Hnorm_dot(dot,norm,PC); if (first==TRUE) { HHset(dmin,dot); HHset(dmax,dot); pmin=pmax=PC; first=FALSE; } else { if (HHlt(dot,dmin)){ HHset(dmin,dot); pmin=PC; } else if (HHlt(dmax,dot)){ HHset(dmax,dot); pmax=PC; } } PC=Ipnt_next(PC); } if (HHeq(dmin,dmax)) return FALSE; if (*refpt==0) { *refpt=pmin; *newpt=pmax; } else{ Hnorm_dot(dot,norm,*refpt); if (HHeq(dot,dmin)) *newpt=pmax; else *newpt=pmin; } Hfree(dot); Hfree(dmin); Hfree(dmax); return TRUE; } /* end cly_initial.c */ /************************************************************************/ /***************** implementation code from cly_update.c ****************/ /************************************************************************/ static int is_flipped(cell c1, cell c2, int *i1, int *i2); static cell cell_pivot(cell C, Ipnt x, int idx); static cell subdiv_add_cell(cell c, cell SDx); int cell_find_lift(cell c, Ipnt pt); /* ** is_flipped ** Input: cells c1, and c2. ** Output: TRUE if c1 and c2 are related by pivoting ** FALSE otherwise. ** Side Effects: i1 and i2 contain the indices of the pivoting ** vertices for c1 and c2 respectivly. */ static int is_flipped(cell c1, cell c2, int *i1, int *i2){ int i, found1=FALSE, found2=FALSE; for(i=0;i<=cly_N;i++){ if (point_is_in(cell_pnt(c1,i),c2)==FALSE){ if (found1==FALSE){ *i1=i; found1=TRUE; } else return FALSE; } if (point_is_in(cell_pnt(c2,i),c1)==FALSE){ if (found2==FALSE){ *i2=i; found2=TRUE; } else return FALSE; } } if (found1==FALSE||found2==FALSE) bad_error("is_flipped: cell differences not detected"); return TRUE; } /* ** cell_pivot ** Input. A cell C. ** A point x. ** An index idx. ** Output. A copy of C, with point x substituted for vertex idx. ** (the pointer field is set to indicate that cell C ** and the new cell are related by a flip). ** */ static cell cell_pivot(cell C, Ipnt x, int idx){ int i,j; cell ncell; if (C==0) bad_error("null cell in cell_pivot\n"); /* copy old cell */ ncell=cell_new(cly_N,cly_R); for(i=1;i<=cly_R;i++) cell_type(ncell,i)=cell_type(C,i); for(i=0;i<=cly_N;i++) cell_pnt(ncell,i)=cell_pnt(C,i); cell_type(ncell,Ipnt_idx(cell_pnt(C,idx)))--; cell_type(ncell,Ipnt_idx(x))++; cell_pnt(ncell,idx)=x; /* substitute point x for vertex idx*/ cell_ptr(ncell,idx)=C; /* pivoting ncell at idx gives c*/ cell_ptr(C,idx)=ncell; /* pivoting c at idx gives ncell*/ cell_fptr(ncell)--; cell_fptr(C)--; /* set up to calculate normal */ /* load coordinate matrix */ for(i=1;i<=cly_N;i++){ for(j=1;j<=cly_N;j++){ HLMset(cell_H(ncell),i,j, cell_point(ncell,i,j)-cell_point(ncell,0,j)); } HLMset(cell_H(ncell),i,cly_N+1,cell_lift(ncell,i)-cell_lift(ncell,0)); } /* calculate normal and remove common factors from coordinates*/ HMfactor(cell_H(ncell),cell_U(ncell)); HMbacksolve(cell_H(ncell),cell_norm(ncell)); HMgcd_reduce(cell_norm(ncell)); /* switch direction if necessary to ensure inner normal */ if (HLlt(HVget(cell_norm(ncell),cly_N+1),0)) { for(j=1;j<=cly_N+1;j++) Hneg(HVget(cell_norm(ncell),j)); } else if (HLeq(HVget(cell_norm(ncell),cly_N+1),0)) bad_error("Cell perpendicular in Cell_norm"); /* load and factor point matrix */ for(i=1;i<=cly_N;i++){ for(j=1;j<=cly_N;j++){ HLMset(cell_H(ncell),j,i, cell_point(ncell,i,j)-cell_point(ncell,0,j)); } HLMset(cell_H(ncell),i,cly_N+1,0); } HMfactor(cell_H(ncell),cell_U(ncell)); cell_set_volume(ncell); return ncell; } /* ** subdiv_add_cell ** Input: A cell c ** A list of cells SDx ** (with the invariant condition that all cells ** of SDx related by a flip point to each other ** through the relevent pointer fields.) ** Output: c appended to SDx ** (with the invariant condition maintained). ** ** */ static cell subdiv_add_cell(cell c, cell SDx){ int i,j; cell ptr; if (c==0) bad_error("null cell in subdiv_add_cell\n"); if (SDx==0) return c; ptr=SDx; while(ptr!=0){ if (is_flipped(c,ptr,&i,&j)==TRUE){ if (cell_ptr(c,i)!=0) bad_error("new cell already flipped in sudiv_add_cell"); if (cell_ptr(ptr,j)!=0) bad_error("old cell already flipped in sudiv_add_cell"); cell_ptr(c,i)=ptr; cell_fptr(c)--; cell_ptr(ptr,j)=c; cell_fptr(ptr)--; } if (cell_next(ptr)==0){ cell_next(ptr)=c; cell_next(c)=0; ptr=0; } else ptr=cell_next(ptr); } return SDx; } /* ** New_Facets ** Input a subdivision SD ** a point x ** Output The new cells resulting by "placeing" ** x (implicitly using a conservitive lifting) ** ** Method: (let n1=n+1). ** Given a cell C and an affine relation ** x=g0*v_0+...gn1*v_n1, g1+...+gn1=1; ** ** Lemma 2.20 of Verschelde et. al shows that ** should be added by pivoting x into C in position ** i iff gi<0. ** ** For each Cell C. ** The matrix M=(v_1-v_0,...,v_{n-1}-v_0,x-v_0) is formed ** and the system M*L=0 is solved, ** (giving g_i=-L_i/L_n and g_0=(L_0+...+L_n1)/L_n1 ** ** if (g_i < 0 and C has not allready been pivoted at v_i) ** (i.e. facet oposite v_i is an outer facet) ** then ** C is pivoted at v_i and vi is added to teh list of new ** cells ** ** */ cell cly_new_cells(cell D,cell Dl, Ipnt x){ cell SDx=0,B; int i,j,n,tog; Hint l0,tmp; n=cly_N; Hinit(l0,0); Hinit(tmp,0); HHset(tmp,l0); HMresize(cly_L,1,cly_N+1); if (D==0){ tog=1; B=Dl; } else { tog=0; B=D; } while(B!=0){ if (cell_is_outer(B)==TRUE){ /* load matrix L=(x-c0) */ for(j=1;j<=n;j++) HLMset(cly_L,1,j,Ipnt_coord(x,j)-cell_point(B,0,j)); /* put U*L in last collumb of H */ for(i=1;i<=n;i++){ HLMset(cell_H(B),i,cly_N+1,0); for(j=1;j<=n;j++){ HHmul(tmp,HMget(cell_U(B),i,j),HMget(cly_L,1,j)); HHadd(HMget(cell_H(B),i,cly_N+1),HMget(cell_H(B),i,cly_N+1),tmp); } } /* solve H*L=0 */ HMbacksolve(cell_H(B),cly_L); if (HLeq(HVget(cly_L,n+1),0)){ cell_print(B); bad_error("simplex not full dim in new_facets()"); } /* ** we have L1*(c1-c0)+...Ln*(cn-c0)+Ln1*(x-c0) ** that is we have l1c0+...+lncn=x for ** l0=(L1+...+Ln+Ln1)/Ln1; ** li=-Li/Ln1 ** we are supposed to flip if li<0 so for i in 1...n ** we test sign(Li)*sign(Ln1)>0 ** and for i=0 we test sign(Ln1)*sign(L1+...+Ln)<0 */ HHset(l0,HVget(cly_L,n+1)); for(i=1;i<=n;i++){ HHmul(tmp,HVget(cly_L,cly_N+1),HVget(cly_L,i)); if ((HLgt(tmp,0)) && (cell_ptr(B,i)==0)){ SDx=subdiv_add_cell(cell_pivot(B,x,i),SDx); } HHadd(l0,l0,HVget(cly_L,i)); } HHmul(tmp,HVget(cly_L,cly_N+1),l0); if ((HLlt(tmp,0)) && (cell_ptr(B,0)==0)){ SDx=subdiv_add_cell(cell_pivot(B,x,0),SDx); } } B=cell_next(B); if (B==0 && tog ==0){ B=Dl; tog=1; } } Hfree(tmp); Hfree(l0); return SDx; } /* ** cell_find_lift ** Input: a cell c ** a point pt ** Output: lowest lifting value wich can be given s while ** keeping it in upper half space defined by lifted cell ** c. ** ** Note: cell_find_lift requires normals to be stored with cell. */ int cell_find_lift(cell c, Ipnt pt){ Hint dotp,dotc,res; int i; HMatrix norm; Hinit(dotp,0); Hinit(dotc,0); Hinit(res,0); norm=cell_norm(c); Hnorm_dot(dotp,norm,pt); Hnorm_dot(dotc,norm,cell_pnt(c,0)); HLmul(res,HVget(norm,cly_N+1),cell_lift(c,0)); HHadd(dotc,dotc,res); HHsub(res,dotc,dotp); HHdiv(dotp,res,HVget(norm,cly_N+1)); HLadd(res,dotp,1); Hfree(dotp); Hfree(dotc); if (HLlt(res,1)) return 1; return HtoL(res); } /* ** subdiv_find_lift ** Input: a subdivision s ** a point pt ** Output: maximum lifting values pt can be given while keeping ** it simultaniously in upper (open) half spaces defined ** by cells of s. */ int cly_find_lift(cell s, Ipnt pt){ int res, temp; if (s==0) return 1; res=cell_find_lift(s,pt); while((s=cell_next(s))!=0) if (res<(temp=cell_find_lift(s,pt))) res=temp; return res; } /* end cly_update.c */ /************************************************************************/ /************** implementation code from cly_triangulate.c **************/ /************************************************************************/ Ipnt Internalize_Aset(aset A); void free_globals(void); static cell new_cayley_triangulate(Ipnt *PC); static node subdiv_get_norms(cell S, Imatrix T, int *mv); node cly_triangulate(aset A, Imatrix T, int order, int lift){ int mv; Ipnt Pts; cell D; node Res=0; LOCS(2); PUSH_LOC(A); PUSH_LOC(Res); Pts=Internalize_Aset(A); cly_order = order; cly_lift = lift; D=new_cayley_triangulate(&Pts); /* Ipnt_list_print(Pts);*/ if (order==TRUE) order_subdiv(&D); subdiv_print(D); if (order==TRUE) print_all_volumes(D); if (lift==TRUE){ lift_original_points(Pts); if (T!=0) Res=subdiv_get_norms(D,T,&mv); else Res=0; } else { warning("finding facets not supported\n"); /* Res=subdiv_to_facets(D);*/ } subdiv_free(D); points_free(Pts); free_globals(); POP_LOCS(); return Res; } Ipnt Internalize_Aset(aset A){ Ipnt point=0,points=0; node ptr,ptc,ptp; int r; cly_Dim=aset_dim(A)-1; cly_R=aset_r(A); cly_N=cly_Dim+cly_R-1; cly_U=HMnew(cly_N,cly_N); cly_M=HMnew(cly_N+1,cly_N+1); cly_L=HVnew(cly_N+1); Hinit(cly_temp,0); /* internalize points of Aset */ ptr = aset_start_cfg(A); r=0; cly_Npts=0; while ((ptc = aset_next_cfg(&ptr)) != 0) { r++; while ((ptp = aset_next_pnt(&ptc)) != 0) { point=Ipnt_new(ptp,r); Ipnt_next(point)=points; cly_Npts++; points=point; } } return points; } void free_globals(void){ /* should also reset all global params*/ HMfree(cly_L); HMfree(cly_M); HMfree(cly_U); Hfree(cly_temp); next_id=1; } /* ** Alg 2.10 of Vershelde ** ** Input: A point configuration (with an extra coordinate to hold ** lifting values (weights) should be initialized to zeros ** ** Output: A triangulation of the subdivision (represented by ** A list of point configurations) */ static cell new_cayley_triangulate(Ipnt *PC) { Ipnt x=0,S1=0,S2=0; cell Dl=0; S1=*PC; if ((Dl=cly_initial_splx(&S1,&S2))==0) bad_error("failure in initial simplex"); while(S1!=0){ x=S1; S1=Ipnt_next(x); if (cly_lift==TRUE) Ipnt_lift(x)=cly_find_lift(Dl,x); Dl=cly_subdiv_union(Dl,cly_new_cells(0,Dl,x)); Ipnt_next(x)=S2; S2=x; } *PC=S2; return Dl; } /* ** subdiv_get_norms(cell S, Imatrix T, *int mv); ** ** Input: a subdivision S (not sorted), and a type matrix T. ** Output: a list of lifted inner normals to cells of S with ** type T. ** side effects: All space reserved for S is freed. ** mv holds the type T mixed volume. */ #define Norm(i) (*IVref(Norm,i)) static node subdiv_get_norms(cell S, Imatrix T, int *mv){ node Nlist=0; Imatrix Norm; int i; LOCS(1); PUSH_LOC(Nlist); *mv=0; while (S!=0){ if (Imatrix_order(T,cell_T(S))==0){ Norm=Ivector_new(cly_Dim+1); for(i=1;i<=cly_Dim;i++) Norm(i)=HLVget(cell_norm(S),i); Norm(cly_Dim+1)=HLVget(cell_norm(S),cly_N+1); Nlist=Cons(atom_new((char *)Norm,IMTX),Nlist); *mv+=cell_volume(S); } S=cell_next(S); } POP_LOCS(); return Nlist; } /* end cly_triangulate.c */ /************************************************************************/ /**************** implementation code from cly_continue.c ***************/ /************************************************************************/ static cell cayley_continue(Ipnt *PC, int threshold, int tweak); static Ipnt Internalize_Aset_Cont(aset,Imatrix,int); Ipnt Internalize_Aset(); static void free_continuation_globals(); void free_globals(); static void Update_Poly(Ipnt x); static void Update_Solutions(cell Dl, int tweak); static node relift(node *, int tweak); static void norm_reset(cell ncell); int cell_find_lift(cell,Ipnt); static psys Poly_Sys=0; static node Poly_Sols=0; static Imatrix Poly_Type=0; static Imatrix Poly_Norm=0; static Imatrix Poly_TNorm=0; static Ipnt *Poly_Pnts=0; #define PPnts(i) (Poly_Pnts[(i)-1]) static HMatrix Poly_H=0; static HMatrix Poly_U=0; #define Poly_Type(i) (*IVref(Poly_Type,i)) #define Poly_Norm(i) (*IVref(Poly_Norm,i)) #define Poly_TNorm(i) (*IVref(Poly_TNorm,i)) /****************************************************************** ** Cayley Triangulation and Continuation ******************************************************************/ psys Cayley_continue(aset A,Imatrix T,node *Sols,int seed,int tweak){ Ipnt S; cell D; psys res; S=Internalize_Aset_Cont(A,T,seed); D=cayley_continue(&S,10,tweak); subdiv_free(D); points_free(S); *Sols=Poly_Sols; res=Poly_Sys; free_continuation_globals(); return res; } #define T(i) (*IVref(T,i)) Ipnt Internalize_Aset_Cont(aset A, Imatrix T,int seed){ Ipnt Pts, res; int i,tmp,max_monomials=0; /* ** seed random number generator */ rand_seed(seed); /* ** initialize regular triangulation globals */ res=(Pts=Internalize_Aset(A)); Poly_Pnts=(Ipnt *)mem_malloc(cly_Npts*sizeof(Ipnt)); /* ** Store type vector in globally accessable location */ Poly_Type=T; Poly_Norm=Ivector_new(cly_Dim+1); Poly_TNorm=Ivector_new(cly_Dim+1); Poly_H=HMnew(cly_N,cly_N+1); Poly_U=HMnew(cly_N,cly_N); /* ** Count total number of monomials needed */ i=1; while(Pts!=0){ PPnts(i++)=Pts; max_monomials+= T(Ipnt_idx(Pts)); Pts=Ipnt_next(Pts); } /* ** initialize new psys- create it set up the block structure ** implied by the type vector T. */ Poly_Sys=psys_new(cly_Dim,max_monomials,cly_R); tmp=1; for(i=1;i<=IVlength(Poly_Type)+1;i++){ *psys_block_start(Poly_Sys,i)=tmp; tmp+=Poly_Type(i); } return res; } #undef T void free_continuation_globals(){ Poly_Sys=0; Poly_Type=0; Imatrix_free(Poly_Norm); Imatrix_free(Poly_TNorm); HMfree(Poly_U); HMfree(Poly_H); free_globals(); } /* ** Alg 2.10 of Vershelde ** ** Input: A point configuration (with an extra coordinate to hold ** lifting values (weights) should be initialized to zeros ** ** Output: A triangulation of the subdivision (represented by ** A list of point configurations) */ static cell cayley_continue(Ipnt *PC, int threshold, int tweak) { Ipnt pt, x=0,S1=0,S2=0; cell D=0,Dl=0; int l; LOCS(1); PUSH_LOC(Poly_Sols); S1=*PC; D=cly_initial_splx(&S1,&S2); for(l=0;l<=cell_n(D);l++) Update_Poly(cell_pnt(D,l)); while(S1!=0){ x=S1; S1=Ipnt_next(x); Ipnt_lift(x)=(l=cly_find_lift(Dl,x)); Update_Poly(x); if (l>threshold){ Update_Solutions(Dl,tweak); #ifdef LOG_PRINT fprintf(stdout /* was cly_out */,"flattening\n") #endif ; for(pt=S2;pt!=0;pt=Ipnt_next(pt)) Ipnt_lift(pt)=0; psys_lift(Poly_Sys,0); D=cly_subdiv_union(D,Dl); Dl=0; Ipnt_lift(x)=1; } Dl=cly_subdiv_union(Dl,cly_new_cells(D,Dl,x)); Ipnt_next(x)=S2; S2=x; } Update_Solutions(Dl,tweak); D=cly_subdiv_union(D,Dl); *PC=S2; POP_LOCS(); return D; } /* ** Update_Poly(Ipnt x) a monomail representing x is chosen with ** a random coefficient and added to the poly. */ static void Update_Poly(Ipnt x){ int j,n; double t; n=psys_d(Poly_Sys); psys_Bstart_poly(Poly_Sys,Ipnt_idx(x)); do{ psys_init_mon(Poly_Sys); *psys_aux(Poly_Sys)=x; t=rand_double((int)0.0,(int)(2*PI)); *psys_coef_real(Poly_Sys)=cos(t); *psys_coef_imag(Poly_Sys)=sin(t); *psys_def(Poly_Sys)=Ipnt_lift(x); for(j=1;j<=n;j++){ *psys_exp(Poly_Sys,j)=Ipnt_coord(x,j); } psys_save_mon(Poly_Sys,psys_eqno(Poly_Sys)); } while(psys_Bnext_poly(Poly_Sys,Ipnt_idx(x))==TRUE); } int comp(node g1,node g2){ return Imatrix_order(cell_norm((cell)Car(g1)), cell_norm((cell)Car(g2))); } void update_list_insert(node g, node * L) { node ptr = *L; LOCS(2); PUSH_LOC(*L); PUSH_LOC(g); if (g==0) bad_error("null node passed to update list"); if (*L == 0 || comp(g, Car(*L)) > 0) *L = Cons(g, *L); else { while ((Cdr(ptr) != 0) && comp(g, Car(Cdr(ptr))) <= 0) ptr = (node) Cdr(ptr); node_set_ptr(ptr,Cons(g, Cdr(ptr)), NODE, RIGHT); } POP_LOCS(); } /* ** Udate_Solutions(cell D) ** use continuation on all solutions already ** found. ** then for each cell in D do a lifting homotopy ** to add more solutions. ** at end flatten all monomials, and solutions. */ static void Update_Solutions(cell Dl, int tweak){ node tmp=0,lhead=0; LOCS(1); PUSH_LOC(lhead); tmp=Poly_Sols; /* update old solutions */ while(tmp!=0){ xpnt_t_set((Dmatrix)Car(Car(tmp)),0.0); tmp=Cdr(tmp); } if (Poly_Sols!=0){ #ifdef LOG_PRINT fprintf(stdout /* was cly_out */,"updating old cells\n") #endif ; Poly_Sols=psys_hom(Poly_Sys,Poly_Sols,tweak); } /* find new solutions */ /* order list of good cells by normal */ /* (with low numbered cells first) */ while(Dl!=0){ if (Imatrix_equal(Poly_Type,cell_T(Dl))==TRUE){ update_list_insert(atom_new((char *)Dl,CELL),&lhead); } Dl=cell_next(Dl); } /* cut out blocks, of cells */ while(lhead!=0){ Poly_Sols=list_cat(relift(&lhead,tweak),Poly_Sols); } psys_lift(Poly_Sys,0); POP_LOCS(); } /* ** */ #define Tmp_Norm(i) (*IVref(Tmp_Norm,i)) static node relift(node *lhead, int tweak){ Imatrix Tmp_Norm; int i,ht,tmp_ht; cell Tmp_Cell; psys Lead_Sys=0, Norm_Sys=0; node Lead_Sols=0,list2=0,lptr=0; Ipnt Mpt; LOCS(3); PUSH_LOC(*lhead); PUSH_LOC(Lead_Sols); PUSH_LOC(list2); /* ** check if cell list is empty */ if (*lhead==0) bad_error("null list in relift"); /* ** make copy of truncated original norm */ Tmp_Norm=cell_norm((cell)Car(Car(*lhead))); for(i=1;i<=cly_Dim;i++){ Poly_Norm(i)=Tmp_Norm(i); } Poly_Norm(cly_Dim+1)=Tmp_Norm(cly_N+1); /* ** set up transformed and leading equations */ Norm_Sys=psys_norm_sub(psys_copy(Poly_Sys),Poly_Norm); Lead_Sys=psys_lead(Norm_Sys); /* ** initialize all points to unseen. */ for(i=1;i<=cly_Npts;i++){ Ipnt_seen(PPnts(i))=FALSE; } /* ** relift points, and cells */ Tmp_Cell=(cell)Car(Car(*lhead)); for(i=0;i<=cly_N;i++){ Ipnt_seen(cell_pnt(Tmp_Cell,i))=TRUE; Ipnt_lift(cell_pnt(Tmp_Cell,i))=0; } while (Cdr(*lhead)!=0 && comp(Car(*lhead),Car(Cdr(*lhead)))==0){ norm_reset(Tmp_Cell); list_push(list_pop(lhead),&list2); Tmp_Cell=(cell)Car(Car(*lhead)); for(i=0;i<=cly_N;i++){ if (Ipnt_seen(cell_pnt(Tmp_Cell,i))!=TRUE){ lptr=list2; ht=cell_find_lift((cell)Car(Car(lptr)) ,cell_pnt(Tmp_Cell,i)); while ((lptr=Cdr(lptr))!=0){ tmp_ht=cell_find_lift((cell)Car(Car(lptr)) ,cell_pnt(Tmp_Cell,i)); if (hty)) #define Hneg(x) ((x*=-1)) #define HHlt(x,y) ((xy)) #define HHeq(x,y) ((x==y)) #define Hinit(x,y) (x=y) #define Hfree(x) {;} #define HHset(x,y) (x=y) #define HLadd(x,y,z) (x=y+z) #define HLmul(x,y,z) (x=y*z) #define HHadd(x,y,z) (x=y+z) #define HHdiv(x,y,z) (x=y/z) #define HHsub(x,y,z) (x=y-z) #define HHmul(x,y,z) (x=y*z) #define Hnorm_dot(dot,norm,PC) {\ dot=0;\ for(i=1;i<=cly_N;i++) dot+=*IVref(norm,i)*Ipnt_coord(PC,i);\ } #define HtoL(x) (x) /* end cly_int.h */ /************************************************************************/ /***************** header information from cly_globals.h ****************/ /************************************************************************/ /* ** Global Variables */ extern int cly_Npts; /* The number of points in the pt config*/ extern int cly_N; /* the dimension of the cayley point config */ extern int cly_R; /* the number of point configs */ extern int cly_Dim; /* the dimension of the Aset */ extern int next_id; /* unique id#s for cells (for debugging)*/ extern FILE *cly_out; /* ** The matrices here are used for now to avoid problems, ** they will eventually be stored with the individual cells. */ extern HMatrix cly_U; /* factor matrix */ extern HMatrix cly_M; /* an n+1xn+1 matrix */ extern HMatrix cly_L; /* an n+1 vector */ extern Imatrix cly_T; /* an R vector */ extern Hint cly_temp; extern int cly_det; /* ** controll parameters ** */ extern int cly_order; extern int cly_lift; /* end cly_globals.h */ /************************************************************************/ /****************** header information from cly_cells.h *****************/ /************************************************************************/ /* ** Ipnt class: Internal representation of points ** Ipnt is defined as a pointer to structure Ipnt_t */ struct Ipnt_t{ struct node_t *point; char *lable; int idx; int *coords; int lift; int seen; struct Ipnt_t *next; }; typedef struct Ipnt_t *Ipnt; /* accses macros */ #define Ipnt_coord(p,i) (((p)->coords[(i)-1])) #define Ipnt_lift(p) (((p)->lift)) #define Ipnt_lable(p) (((p)->lable)) #define Ipnt_next(p) (((p)->next)) #define Ipnt_idx(p) (((p)->idx)) #define Ipnt_pnt(p) (((p)->point)) #define Ipnt_seen(p) (((p)->seen)) void Ipnt_fprint(FILE *fout, Ipnt p); #define Ipnt_print(P) (Ipnt_fprint(stdout,P)) void Ipnt_list_fprint(FILE *fout,Ipnt p); #define Ipnt_list_print(P) (Ipnt_list_fprint(stdout,P)) Ipnt Ipnt_new(struct node_t *pnt,int r); void Ipnt_free(Ipnt p); void points_free(Ipnt p); void lift_original_points(Ipnt p); /* ** Cells of a triangulation are simplices, represented by a ** vector of n+1 points, and a vector of n+1 pointers, ** the ith pointer pointing to a cell of the triangulation ** which shares the facet oposite the ith vertex, (if no such ** cell exists the pointer is null). */ struct cell_t { int n; /* dimension of cell */ int r; /* number of supports in Aset*/ int id; /* identification number for cell */ Ipnt *points; /* points 0 through n */ struct cell_t **ptrs; /* the corresponding pointers */ int freeptrs; /* count of the number of outer facets*/ int volume; /* the normalized volume of the cell */ Imatrix T; /* mixture type for cell */ int Tindx; /* decimal value of t1+t2D+...+TrD^(R-1) used for quick test of type order */ HMatrix norm; /* normal for cell */ HMatrix U; HMatrix H; struct cell_t *next; /* next point in subdivision */ }; typedef struct cell_t *cell; #define cell_H(c) (((c)->H)) #define cell_U(c) (((c)->U)) #define cell_T(c) (((c)->T)) #define cell_norm(c) (((c)->norm)) #define cell_n(c) (((c)->n)) #define cell_r(c) (((c)->r)) #define cell_id(c) (((c)->id)) #define cell_next(c) (((c)->next)) #define cell_ptr(c,i) (((c)->ptrs)[i]) #define cell_fptr(c) (((c)->freeptrs)) #define cell_pnt(c,i) (((c)->points)[i]) #define cell_point(c,i,j) (Ipnt_coord(cell_pnt(c,i),j)) #define cell_lift(c,i) (Ipnt_lift(cell_pnt(c,i))) #define cell_type(c,i) ((*IVref(c->T,i))) #define cell_is_outer(c) ((cell_fptr(c)!=0) ? TRUE : FALSE) #define cell_volume(c) ((c->volume)) #define cell_tindex(c) ((c->Tindx)) cell cell_new(int n,int r); void cell_free(cell c); void subdiv_free(cell c); void cell_fprint(FILE *fout,cell c); void subdiv_fprint(FILE *fout,cell c); int fprint_all_volumes(FILE *fout,cell S); #define cell_print(C) (cell_fprint(stdout,C)) #define subdiv_print(C) (subdiv_fprint(stdout,C)) #define print_all_volumes(C) (fprint_all_volumes(stdout,C)) int point_is_in(Ipnt pt, cell c); int cell_set_volume(cell c); int cell_type_cmp(cell c1,cell c2); void order_subdiv(cell *Subdiv); cell cly_subdiv_union(cell SD1, cell SD2); /* end cly_cells.h */ /************************************************************************/ /***************** header information from cly_initial.h ****************/ /************************************************************************/ cell cly_initial_splx(Ipnt *S1, Ipnt *S2); /* end cly_initial.h */ /************************************************************************/ /***************** header information from cly_update.h *****************/ /************************************************************************/ cell cly_new_cells(cell D,cell Dl, Ipnt x); int cly_find_lift(cell s, Ipnt pt); /* end cly_update.h */ /************************************************************************/ /*************** header information from cly_triangulate.h **************/ /************************************************************************/ node cly_triangulate(aset A, Imatrix T, int order, int lift); /* end cly_triangulate.h */ /************************************************************************/ /***************** header information from cly_continue.h ****************/ /************************************************************************/ psys Cayley_continue(aset A,Imatrix T,node *Sols,int seed,int tweak); /* end cly_initial.h */ #endif /* CLY_ALL_H */ gambit-0.2010.09.01/src/tools/enumpoly/pelconv.cc0000644000076500007650000001727611350032206016221 00000000000000/* ** copyright (c) 1995 Birk Huber */ #include "pelconv.h" /* Coorcions from Gen to procedure Data structures: these do not make a serious attempt to check validity, it is assumed that a predicate from Pred.c will have been used first to check the suitability of g for conversion */ /* Scalors first: */ polynomial1 Gen_To_Ply(Gen_node g) { polynomial1 p=0; if (g==0) bad_error("NULL arg to Gen_To_Ply"); switch (g->type){ case Int_T: p=ItoP(g->Genval.ival,Def_Ring); break; case Dbl_T: p=DtoP(g->Genval.dval,Def_Ring); break; case Cpx_T: p=CtoP(g->Genval.cval,Def_Ring); break; case Ply_T: p=copyP(g->Genval.pval); break; default: bad_error("not coorceable to ply in Gen_To_Ply"); break; } return p; } fcomplex Gen_To_Cpx(Gen_node g){ fcomplex c; if (g==0) bad_error("NULL arg to Gen_To_Cpx\n"); switch (g->type){ case Int_T: c=ItoC(g->Genval.ival); break; case Dbl_T: c=DtoC(g->Genval.dval); break; case Cpx_T: c=g->Genval.cval; break; default: bad_error("Don't know how to coerce in Gen_To_Cpx\n"); break; } return c; } double Gen_To_Dbl(Gen_node g) { double d = 0.0; if (g==0) bad_error("NULL arg to Gen_To_Dbl"); switch (g->type){ case Int_T: d=g->Genval.ival; break; case Dbl_T: d=g->Genval.dval; break; default: bad_error("Don't Know how to coerce in Gen_To_Dbl"); break; } return d; } int Gen_To_Int(Gen_node g){ int d = 0; if (g==0) bad_error("NULL arg to Gen_To_Int"); switch (g->type){ case Int_T: d=g->Genval.ival; break; default: bad_error("Don't Know how to coerce in Gen_To_Int"); break; } return d; } Dmatrix Gen_to_Dmatrix(Gen_node g){ Dmatrix Res; Gmatrix M; int i,j; M=Gen_Mtx(g); Res=Dmatrix_new(GMrows(M),GMcols(M)); for(i=1;i<=GMrows(M);i++) for(j=1;j<=GMcols(M);j++) DMref(Res,i,j)=Gen_To_Dbl(*GMref(M,i,j)); return Res; } Gen_node Dmatrix_to_Gen(Dmatrix M){ Gmatrix Res; int i,j; Res=Gmatrix_new(DMrows(M),DMcols(M)); for(i=1;i<=DMrows(M);i++) for(j=1;j<=DMcols(M);j++) *GMref(Res,i,j)=Dbl_To_Gen(DMref(M,i,j)); return GMND(Res); } Imatrix Gen_to_Imatrix(Gen_node g){ Imatrix Res; Gmatrix M; int i,j; M=Gen_Mtx(g); Res=Imatrix_new(GMrows(M),GMcols(M)); for(i=1;i<=GMrows(M);i++) for(j=1;j<=GMcols(M);j++) *IMref(Res,i,j)=Gen_To_Int(*GMref(M,i,j)); return Res; } Gen_node Imatrix_to_Gen(Imatrix M){ Gmatrix Res; int i,j; Res=Gmatrix_new(IMrows(M),IMcols(M)); for(i=1;i<=IMrows(M);i++) for(j=1;j<=IMcols(M);j++) *GMref(Res,i,j)=Int_To_Gen(*IMref(M,i,j)); return GMND(Res); } /*----------------------------------------------------------- Conversions to Gen ------------------------------------------------------------*/ Gen_node Int_To_Gen(int i) { Gen_node g; g=gen_node(); g->type=Int_T; g->Genval.ival=i; return g; } Gen_node Dbl_To_Gen(double d) { Gen_node g; g=gen_node(); g->type=Dbl_T; g->Genval.dval=d; return g; } Gen_node Cpx_To_Gen(fcomplex c) { Gen_node g; g=gen_node(); g->type=Cpx_T; g->Genval.cval=c; return g; } Gen_node Ply_To_Gen(polynomial1 p) { Gen_node g; g=gen_node(); g->type=Ply_T; g->Genval.pval=copyP(p); return g; } node Gen_to_Dvector_list(Gen_node ptr){ node res=0; LOCS(1); PUSH_LOC(res); while(ptr!=0){ if (Can_Be_Vector(ptr,Dbl_T)!=2*N+3){ warning("bad list in Gen_to_Dvector"); POP_LOCS(); return 0; } res=Cons(atom_new((char *)Gen_to_Dmatrix(ptr),DMTX),res); ptr=Gen_next(ptr); } POP_LOCS(); return res; } Gen_node Dvector_list_to_Gen(node DL){ Gen_node ptc,res; ptc=(res=gen_node()); while(DL!=0){ if (node_get_type(Car(DL),LEFT)!=DMTX){ warning("bad list in Dvector_list_to_Gen\n"); return 0; } Gen_set_next(ptc,Dmatrix_to_Gen((Dmatrix)Car(Car(DL)))); ptc=Gen_next(ptc); DL=Cdr(DL); } ptc=Gen_node_to_List(Gen_next(res)); free_Gen_node(res); return ptc; } Gen_node Xpl_to_Gen(node DL){ Gen_node ptc,res; ptc=(res=gen_node()); while(DL!=0){ if (node_get_type(Car(DL),LEFT)!=DMTX){ warning("bad list in Dvector_list_to_Gen\n"); return 0; } Gen_set_next(ptc,Dmatrix_to_Gen((Dmatrix)Car(Car(DL)))); ptc=Gen_next(ptc); DL=Cdr(DL); } ptc=XPLND(Gen_next(res)); free_Gen_node(res); return ptc; } Gen_node Ivector_list_to_Gen(node DL){ Gen_node ptc,res; ptc=(res=gen_node()); while(DL!=0){ if (node_get_type(Car(DL),LEFT)!=IMTX){ warning("bad list in Ivector_list_to_Gen"); return 0; } Gen_set_next(ptc,Imatrix_to_Gen((Imatrix)Car(Car(DL)))); ptc=Gen_next(ptc); DL=Cdr(DL); } ptc=Gen_node_to_List(Gen_next(res)); free_Gen_node(res); return ptc; } node Gen_to_Ivector_list(Gen_node ptr){ node res=0; LOCS(1); PUSH_LOC(res); while(ptr!=0){ if (Can_Be_Vector(ptr,Int_T)<=0){ warning("bad list in Gen_to_Ivector"); POP_LOCS(); return 0; } res=Cons(atom_new((char *)Gen_to_Imatrix(ptr),IMTX),res); ptr=Gen_next(ptr); } POP_LOCS(); return res; } Gen_node List_To_Aset(Gen_node g){ Gen_node ptr; Gmatrix M,P; point pnt=0; aset A=0; int R,D,r=0,j,i; char *s,c='a'-1; LOCS(2); PUSH_LOC(pnt); PUSH_LOC(A); if (Gen_Can_Be_Aset(g,&R,&D)!=TRUE){ POP_LOCS(); return Rerror("",g); } A=aset_new(R,D); for(ptr=g;ptr!=0;ptr=Gen_next(ptr)){ M=Gen_Mtx(ptr); r++; c++; for(i=1;i<=GMcols(M);i++){ s=(char *)mem_malloc(6*sizeof(char)); s[0]=c; sprintf(s+1,"%d",i); pnt=aset_new_pt(D,s); P=Gen_Mtx(*GMref(M,1,i)); for(j=1;j<=GMcols(P);j++){ aset_pnt_set(pnt,j,Gen_int(*GMref(P,1,j))); } aset_add(A,r,pnt); } } POP_LOCS(); free_Gen_list(g); return ASTND(A); } #define PV(i) Gen_poly(*GMref(PV,1,i)) psys Gen_to_psys(Gen_node g){ Gmatrix PV; int n,m,r,i,j,deg,td; psys sys; polynomial1 ptr; PV=Gen_Mtx(g); /* pass1 collect stats on polynomial1 */ n=poly_dim(PV(1)); m=0; r=1; for(i=1;i<=GMcols(PV);i++){ if (i>1&&orderPP(PV(i),PV(i-1))!=0) r++; ptr=PV(i); m++; while((ptr=poly_next(ptr))!=0) m++; } sys=psys_new(n,m,r); *psys_block_start(sys,1)=1; r=1; /* pass2: fill psys */ for(i=1;i<=GMcols(PV);i++){ if (i>1&&orderPP(PV(i),PV(i-1))!=0) { *psys_block_start(sys,++r)=i; } ptr=PV(i); deg=poly_deg(ptr); while(ptr!=0){ while(ptr!=0){ psys_init_mon(sys); *psys_coef_real(sys)=(*poly_coef(ptr)).r; *psys_coef_imag(sys)=(*poly_coef(ptr)).i; *psys_def(sys)=*poly_def(ptr); td=0; for(j=1;j<=n;j++){ *psys_exp(sys,j)=*poly_exp(ptr,j); td+=*psys_exp(sys,j); } *psys_homog(sys)=deg-td; psys_save_mon(sys,i); ptr=poly_next(ptr); } } } return sys; } Gen_node Gen_from_psys(psys sys){ polynomial1 tmpm,tmpp; int j; Gmatrix PV; PV=Gmatrix_new(1,psys_d(sys)); FORALL_POLY(sys, tmpp=0; FORALL_MONO(sys, tmpm=makeP(Def_Ring); *poly_coef(tmpm)=Complex(*psys_coef_real(sys), *psys_coef_imag(sys)); *poly_def(tmpm)=*psys_def(sys); *poly_homog(tmpm)=*psys_homog(sys); for(j=1;j<=psys_d(sys);j++) *poly_exp(tmpm,j)=*psys_exp(sys,j); tmpp=addPPP(tmpp,tmpm,tmpp); freeP(tmpm); ) *GMref(PV,1,psys_eqno(sys))=PLYND(tmpp); ) return SYSND(PV); } gambit-0.2010.09.01/src/tools/enumpoly/pelconv.h0000644000076500007650000000323411350032206016050 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* ** copyright (c) 1995 Birk Huber */ #ifndef CONV_H #define CONV_H #include #include #include "pelpred.h" polynomial1 Gen_To_Ply(Gen_node g); fcomplex Gen_To_Cpx(Gen_node g); double Gen_To_Dbl(Gen_node g); int Gen_To_Int(Gen_node g); Imatrix Gen_to_Imatrix(Gen_node g); Dmatrix Gen_to_Dmatrix(Gen_node g); Gen_node Int_To_Gen(int i); Gen_node Dbl_To_Gen(double d); Gen_node Cpx_To_Gen(fcomplex c); Gen_node Ply_To_Gen(polynomial1 p); Gen_node Imatrix_to_Gen(Imatrix M); Gen_node Dmatrix_to_Gen(Dmatrix M); node Gen_to_Ivector_list(Gen_node ptr); Gen_node Ivector_list_to_Gen(node DL); psys Gen_to_psys(Gen_node g); Gen_node Gen_from_psys(psys sys); Gen_node Dvector_list_to_Gen(node DL); Gen_node Xpl_to_Gen(node DL); node Gen_to_Dvector_list(Gen_node ptr); Gen_node List_To_Aset(Gen_node g); #endif /* CONV_H */ gambit-0.2010.09.01/src/tools/enumpoly/peleval.cc0000644000076500007650000000163611350032206016174 00000000000000/* ** copyright (c) 1995 Birk Huber */ #include "peleval.h" int EvLev=0; Gen_node Eval(Gen_node g) { Gen_node (*proc)(Gen_node),arg,ptr,ans; if (g==0) bad_error("Eval passed empty list"); if (g->type == Lst_T) { ptr=g->Genval.lval; if (ptr!=0) { arg=Eval(ptr); if (arg->type==Err_T){free_Gen_list(g); return arg;} g->Genval.lval=arg; while(arg->next!=0){ ans=Eval(arg->next); if (arg->type==Err_T){ free_Gen_list(g); return ans;} arg->next=ans; arg=arg->next; } if (g->Genval.lval->type == Prc_T){ proc=g->Genval.lval->Genval.proc; arg=g->Genval.lval->next; g->Genval.lval->next=0; ans=proc(arg); ans->next=g->next; g->next=0; free_Gen_list(g); return ans; } } } return g; } gambit-0.2010.09.01/src/tools/enumpoly/peleval.h0000644000076500007650000000164611350032206016037 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* ** copyright (c) 1995 Birk Huber */ #include "pelproc.h" Gen_node Eval(Gen_node g); gambit-0.2010.09.01/src/tools/enumpoly/pelgennd.cc0000644000076500007650000002330711351773322016353 00000000000000/* ** copyright (c) 1995 Birk Huber */ #include "pelgennd.h" extern node SaveList; node Dlist_add(node,node); node Dlist_del(node,node); node Dlist_data(node); Pring Def_Ring; int N; Gen_node gen_node() { Gen_node a; a=(Gen_node)mem_malloc(sizeof(struct Gen_node_tag)); if (a == 0) bad_error(" malloc failure in gen_node()"); a->next=0; a->type=0; return a;} Gen_node free_Gen_node(Gen_node a) { if (a==0) return 0; switch (a->type){ case Xpl_T: case Npl_T: case Lst_T: if(a->Genval.lval!=0) free_Gen_list(a->Genval.lval); break; case Ast_T: Dlist_del(SaveList,(node)(a->Genval.gval)); break; case Sys_T: case Mtx_T: if(a->Genval.lval!=0) Gmatrix_free((Gmatrix)a->Genval.gval); break; case Err_T: break; case Idf_T: if(a->Genval.idval!=0) mem_free(a->Genval.idval); break; case Str_T: if(a->Genval.gval!=0) mem_free(a->Genval.gval); break; case Ply_T: if(a->Genval.pval!=0) freeP(a->Genval.pval); break; default : break; } mem_free((char *)a); return 0; } Gen_node free_Gen_list(Gen_node a) { Gen_node b; while(a!=0){ b=a->next; a=free_Gen_node(a); a=b;} return 0; } Gen_node G_Print(Gen_node); void print_Gen_node(Gen_node g) { /* DEBUG */ /* if (g->type > 10) fprintf(stdout, "The type number is %d.\n", g->type); */ switch (g->type) { case Int_T: #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */," %d ",g->Genval.ival) #endif ; break; case Dbl_T: #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */," %f ",g->Genval.dval) #endif ; break; case Idf_T: #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */," %s ",g->Genval.idval) #endif ; break; case Str_T: #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */," %s ",g->Genval.gval); fprintf(stdout /* was Pel_Out */," %s "," case Str_T") #endif ; break; case Err_T: #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */," %s \n", "new gen_node:\n\n") #endif ; break; case Xpl_T: free_Gen_node(G_Print(copy_Gen_node(g))); #ifdef LOG_PRINT /* fprintf(stdout," %s "," case Xpl_T") */ #endif ; break; case Npl_T: ; break; case Lst_T: #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"{") ; print_Gen_list(g->Genval.lval); fprintf(stdout /* was Pel_Out */,"}") #endif ; ; break; case Ast_T: /* DEBUG */ /* printf("The type is Ast_T which is %d.\n",Ast_T); */ node_print(Dlist_data((node)g->Genval.gval)); #ifdef LOG_PRINT /* fprintf(stdout */ /* was Pel_Out */ /*, " %s "," case Ast_T") */ #endif ; break; case Sys_T: /* DEBUG */ /* printf("The type is Sys_T which is %d.\n",Sys_T); */ free_Gen_node(G_Print(copy_Gen_node(g))); #ifdef LOG_PRINT /* fprintf(stdout */ /* was Pel_Out */ /*, " %s "," case Sys_T") */ #endif ; break; case Mtx_T: fprintf(stdout /* was Pel_Out */, "%s","The vector of numbers of polynomials of each support type is:\n"); Gmatrix_print((Gmatrix)g->Genval.gval); break; case Prc_T: /* DEBUG */ printf("The type is Prc_T which is %d.\n",Prc_T); print_Proc(g->Genval.proc); #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */, " %s "," case Prc_T:") #endif ; break; case Cpx_T: printC(g->Genval.cval); /* DEBUG */ printf("The type is Cpx_T which is %d.\n",Cpx_T); #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */, " %s "," case Cpx_T") #endif ; break; case Ply_T: /* DEBUG */ /* printf(" The type is Ply_T which is %d. ",Ply_T); */ printP(g->Genval.pval); break; case Rng_T: #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"cannot display ring yet\n"); fprintf(stdout /* was Pel_Out */, " %s "," case Rng_T") #endif ; break; default: bad_error("unknown type in print_Gen_node"); } } void print_Gen_list(Gen_node g) { int tog=0; while (g!=0){ if (tog==1) fprintf(stdout /* was Pel_Out */,","); print_Gen_node(g); tog=1; g=g->next; } } void silent_print_Gen_list(Gen_node g) { while (g!=0) g=g->next; } Gen_node Gen_node_to_List(Gen_node g) {Gen_node a; a=gen_node(); a->type=Lst_T; a->Genval.lval=g; return a; } Gen_node Cat(Gen_node g1,Gen_node g2){ Gen_node a; if((a=g1)==0) return g2; while(a->next!=0) a=a->next; a->next=g2; return g1; } Gen_node copy_Gen_list(Gen_node a) { Gen_node n,pt; if (a==0) return 0; n=copy_Gen_node(a); pt=n; a=a->next; while(a!=0){ pt->next=copy_Gen_node(a); pt=pt->next; a=a->next; } return n; } Gen_node copy_Gen_node(Gen_node a) { Gen_node b; b=gen_node(); b->type=a->type; switch(a->type){ case Int_T: b->Genval.ival=a->Genval.ival; break; case Dbl_T: b->Genval.dval=a->Genval.dval; break; case Prc_T: b->Genval.proc=a->Genval.proc; break; case Xpl_T: case Npl_T: case Lst_T: b->Genval.lval=copy_Gen_list(a->Genval.lval); break; case Ast_T: b->Genval.gval= (char *)Dlist_add(SaveList, Dlist_data((node)a->Genval.gval)); break; case Sys_T: case Mtx_T: b->Genval.gval=(char *)Gmatrix_copy((Gmatrix)a->Genval.lval); break; case Idf_T: b->Genval.idval=Copy_String(a->Genval.idval); break; case Str_T: b->Genval.gval=Copy_String(a->Genval.gval); break; case Err_T: break; case Cpx_T: b->Genval.cval=a->Genval.cval; break; case Ply_T: b->Genval.pval=copyP(a->Genval.pval); break; case Rng_T: warning("can not copy ring"); default: warning("incomplete copy in copy_Gen_node()"); break; } return b; } char *Gen_idval(Gen_node g){ if (g==0||(g->type!=Idf_T&&g->type!=Str_T)) return 0; else return g->Genval.idval; } Gen_node Gen_set_next(Gen_node g,Gen_node h){ if (g==0) return 0; else return g->next=h; } Gen_node Gen_lval(Gen_node g){ if (g==0) return 0; else return g->Genval.lval; } Gen_node Gen_set_lval(Gen_node g,Gen_node g1){ if (g==0) return 0; else return (g->Genval.lval=g1); } Gen_node Gen_next(Gen_node g){ if (g==0) return 0; else return g->next; } int Gen_type(Gen_node g){ if (g==0) bad_error("requesting type of null node"); return g->type; } int Gen_set_int(Gen_node g,int i){ if (g==0) bad_error("setting int field of null node"); return g->Genval.ival=i; } int Gen_int(Gen_node g){ if (g==0) bad_error("getting int field of null node"); return g->Genval.ival; } int Gen_length(Gen_node g){ int ct=1; if (g==0) return 0; while((g=Gen_next(g))!=0)ct++; return ct; } Gen_node Gen_elt(Gen_node g, int idx){ while(--idx>0) g=Gen_next(g); return g; } polynomial1 Gen_poly(Gen_node g){ if (g==0) bad_error("getting polynomial1 from null node in Gentype (Pat)"); return (polynomial1)g->Genval.gval; } node Gen_aset(Gen_node g){ if (g==0) bad_error("getting aset from null node"); return Dlist_data((node)(g->Genval.gval)); } void print_Proc(Gen_node (*p)(Gen_node)) { #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"%p",p) #endif ; } /*used for reader.lex-- takes a string in quotes and removes outside quotes*/ char *Copy_String_NQ(char *s) { int l,i,j=0; char *res; l=strlen(s); res=(char *)mem_malloc((l-1)*sizeof(char)); for(i=0;i<=l;i++) if (s[i]!='"') res[j++]=s[i]; return res; } char *Copy_String(char *s) { /* char *strdup(); CANT DECLARE BUILTINS UNDER C++ */ return mem_strdup(s);} Gen_node IDND(char *s){ Gen_node a; a=gen_node(); a->type=Idf_T; a->Genval.idval=Copy_String(s); a->next=0; return a; } Gen_node ASTND(node n){ Gen_node a; a=gen_node(); a->type=Ast_T; a->Genval.gval=(char *)Dlist_add(SaveList,n); a->next=0; return a; } Gen_node INTND(int n){ Gen_node a; a=gen_node(); a->type=Int_T; a->Genval.ival=n; a->next=0; return a; } Gen_node DBLND(double d){ Gen_node a; a=gen_node(); a->type=Dbl_T; a->Genval.dval=d; a->next=0; return a; } Gen_node CPXND(fcomplex c){ Gen_node a; a=gen_node(); a->type=Cpx_T; a->Genval.cval=c; a->next=0; return a; } Gen_node PLYND(polynomial1 p) { Gen_node a; a=gen_node(); a->type=Ply_T; a->Genval.pval=p; a->next=0; return a; } Gen_node PND(Gen_node p(Gen_node)) { Gen_node a; a=gen_node(); a->type=Prc_T; a->Genval.proc=p; a->next=0; return a; } Gen_node Rerror(char *s,Gen_node g) { bad_error("We had an Rerror"); Gen_node ans; if (g!=0) free_Gen_list(g); #ifdef LOG_PRINT fprintf(stderr /* was Pel_Err */,"%s\n",s) #endif ; ans=gen_node(); ans->type=Err_T; return ans; } /* ** Print Command */ Gen_node G_Print(Gen_node g){ psys sys; node xl; if (Gen_length(g)!=1) return Rerror("Print: too many arguments",g); ; switch (Gen_type(g)){ case Ast_T: aset_print(Gen_aset(g)); break; case Sys_T: sys=Gen_to_psys(g); psys_print(sys); psys_free(sys); break; case Xpl_T: xl=Gen_to_Dvector_list(Gen_lval(g)); #ifdef LOG_PRINT xpl_fprint(stdout /* was Pel_Out */,xl) #endif ; break; default: print_Gen_node(g); } #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"\n") #endif ; free_Gen_list(g); return IDND(""); } gambit-0.2010.09.01/src/tools/enumpoly/pelgennd.h0000644000076500007650000000401211351773322016205 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* ** copyright (c) 1995 Birk Huber */ #include "pelconv.h" Gen_node gen_node(); Gen_node free_Gen_node(Gen_node a); Gen_node free_Gen_list(Gen_node a); void print_Gen_node(Gen_node g); void silent_print_Gen_list(Gen_node g); void print_Gen_list(Gen_node g); Gen_node Cat(Gen_node g1,Gen_node g2); Gen_node copy_Gen_list(Gen_node a); Gen_node copy_Gen_node(Gen_node a); char *Gen_idval(Gen_node g); Gen_node Gen_set_next(Gen_node g,Gen_node h); Gen_node Gen_lval(Gen_node g); Gen_node Gen_set_lval(Gen_node g,Gen_node g1); Gen_node Gen_next(Gen_node g); int Gen_type(Gen_node g); int Gen_set_int(Gen_node g,int i); int Gen_int(Gen_node g); int Gen_length(Gen_node g); Gen_node Gen_elt(Gen_node g, int idx); polynomial1 Gen_poly(Gen_node g); node Gen_aset(Gen_node g); void print_Proc(Gen_node (*p)(Gen_node)); /*used for reader.lex-- takes a string in quotes and removes outside quotes*/ char *Copy_String_NQ(char *s); char *Copy_String(char *s); Gen_node IDND(char *s); Gen_node ASTND(node n); Gen_node INTND(int n); Gen_node DBLND(double d); Gen_node CPXND(fcomplex c); Gen_node PLYND(polynomial1 p); Gen_node Rerror(char *s,Gen_node g); Gen_node G_Print(Gen_node g); gambit-0.2010.09.01/src/tools/enumpoly/pelgmatr.cc0000644000076500007650000001651311350032206016357 00000000000000/* ** copyright (c) 1995 Birk Huber */ #include "pelgmatr.h" #define min(i,j) ((i) < (j) ? (i): (j)) /*--------------------------------------------------------------- vector/matrix type a linear array of int, whith auxilary info. *) the number of elements that can be stored is in elt[0] *) the current number of rows is in elt[1] *) the current number of collumbs is in elt[2] The actual data are then stored in row major order from elt[3] on ---------------------------------------------------------------*/ /*------------------------------------------------------------- vector access macroes (which ignore any rows except for first) -------------------------------------------------------------*/ #define Vstore(V) ((V->store)) #define Vlength(V) ((V->topr)) #define Vref1(V,i) (&(((V->coords)[i-1]))) #define Vref0(V,i) (&(((V->coords)[i]))) #define Vref(V,i) Vref1(V,i) /*------------------------------------------------------------ matrix access macroes -------------------------------------------------------------*/ #define Mstore(V) ((V->store)) #define MMrows(V) ((V->store/V->ncols)) #define Mrows(V) ((V->topr)) #define Mcols(V) ((V->topc)) #define MNcols(V) ((V->ncols)) #define Mref1(V,i,j)(&(((V->coords)[(i-1)*(V->ncols)+j-1]))) #define Mref0(V,i,j)(&(((V->coords)[i*(V->ncols)+j]))) #define Mref(V,i,j) Mref1((V),i,j) int GMstore(Gmatrix M) { return Mstore(M); } int GMMrows(Gmatrix M) { return MMrows(M); } int GMrows(Gmatrix M) { return Mrows(M); } int GMcols(Gmatrix M) { return Mcols(M); } Gen_node *GMref1(Gmatrix M, int i, int j) { return Mref1(M, i, j); } /* ** Constructor/Destructors for Gmatrixes ** ** Gmatrix Gmatrix_free(int r, int c); ** New Gmatrix cabable of holding r rows, and c collumbs. ** Gmatrix Gmatrix_new(Gmatrix V); */ Gmatrix Gmatrix_new(int r, int c) { Gmatrix V; int i, j; V = (Gmatrix) mem_malloc(sizeof(struct Gmatrix_t)); if (!V) bad_error("allocation failure in Gmatrix_new()"); V->coords = (Gen_node *) mem_malloc(r * c * sizeof(Gen_node)); if (!V) bad_error("allocation failure 2 in Gmatrix_new()"); Mstore(V) = r * c; Mrows(V) = r; Mcols(V) = c; MNcols(V) = c; for (i = 1; i <= r; i++) { for (j = 1; j <= c; j++) *Mref(V, i, j)=0; } return V; } void Gmatrix_free(Gmatrix V) { int i, j; if (V != 0 && V->coords != 0) { for (i = 1; i <= Mrows(V); i++) for (j = 1; j <= Mcols(V); j++) free_Gen_list(*Mref(V, i, j)); mem_free((char *) (V->coords)); } if (V != 0) mem_free((char *) (V)); } /* ** Gmatrix_resize(R,r,c) ** Reset R to hold an r,by c matrix. ** if R has enough storage to hold an rxc matrix resets ** row and columb entrees of r to r and c. otherwise ** frees R and reallocates an rxc matrix ** DOES NOT PRESERVE INDECIES OF EXISTING DATA */ Gmatrix Gmatrix_resize(Gmatrix R, int r, int c) { if (R == 0 || Mstore(R) < (r * c)) { if (R != 0) Gmatrix_free(R); R = Gmatrix_new(r, c); } else { Mrows(R) = r; Mcols(R) = c; MNcols(R) = c; } return R; } Gmatrix Gmatrix_submat(Gmatrix R, int r, int c) { if (R == 0 || c > Mcols(R) || r > Mrows(R) * MNcols(R)) { bad_error("bad subscripts or zero matrix in Gmatrix_submat()"); } else { Mrows(R) = r; Mcols(R) = c; } return R; } /* ** Gmatrix_print(M): print a Gmatrix ** if M is null print <<>> and return fail. ** otherwise print matrix and return true. */ Gmatrix Gmatrix_print(Gmatrix M) { int i, j; if (M == 0) { fprintf(stdout /* was Pel_Out */,"<>"); return 0; } fprintf(stdout /* was Pel_Out */,"<"); for (i = 1; i <= Mrows(M); i++) { for (j = 1; j <= Mcols(M); j++) { print_Gen_list(*Mref(M, i, j)); /* if (j < Mcols(M)) printf(",\n "); */ } if (i < Mrows(M)) fprintf(stdout,";\n"); } fprintf(stdout /* was Pel_Out */,">\n"); return M; } /* ** Gmatrix_Dop(M1,M2, ) -- Add two Gmatrixes: ** if M1, and M2 are incompatable (or null) complain and return false. ** if *M3 has too little storage (or is null) free *M3 if nescesary ** and create new storage. */ Gmatrix Gmatrix_Dop(Gmatrix M1, Gmatrix M2, Gen_node (*op)(Gen_node)) { int i, j; Gmatrix R; if (M1 == 0||M2 == 0||Mrows(M1)!=Mrows(M2)|| Mcols(M1)!= Mcols(M2)) { bad_error("matrix_add: dimensions dont match\n"); } R=Gmatrix_new(Mrows(M1), Mcols(M1)); for (i = 1; i <= Mrows(M1); i++) for (j = 1; j <= Mcols(M1); j++) *Mref(R, i, j)=op(Link( copy_Gen_list(*Mref(M1, i, j)), copy_Gen_list(*Mref(M2, i, j)) )); return R; } Gmatrix Gmatrix_Sop(Gen_node g, Gmatrix M, Gen_node (*op)(Gen_node)) { int i, j; Gmatrix R; if (M == 0||g==0) bad_error("matrix_Sop: null arg\n"); R=Gmatrix_new(Mrows(M), Mcols(M)); for (i = 1; i <= Mrows(M); i++) for (j = 1; j <= Mcols(M); j++) *Mref(R, i, j)=op(Link( copy_Gen_list(g), copy_Gen_list(*Mref(M, i, j)) )); return R; } Gmatrix Gmatrix_Mop(Gmatrix M1, Gmatrix M2, Gen_node Aidentity, Gen_node (*opA)(Gen_node), Gen_node (*opM)(Gen_node)){ int i,j,k; Gmatrix R; if (M1==0|| M2==0 || Mcols(M1)!=Mrows(M2)) { warning("Gmatrix_mull: incompatible matrices"); return 0; } R=Gmatrix_new(Mrows(M1),Mcols(M2)); for(i=1; i<=Mrows(M1); i++) for(j=1;j<=Mcols(M2); j++){ *Mref(R,i,j)=copy_Gen_list(Aidentity); for(k=1; k<=Mcols(M1); k++) *Mref(R,i,j)= opA( Link(*Mref(R,i,j), opM(Link( copy_Gen_list(*Mref(M1,i,k)), copy_Gen_list(*Mref(M2,k,j)) )) )); } return R; } Gmatrix Gen_Mtx(Gen_node g){ return (Gmatrix) g->Genval.gval; } Gen_node GMND(Gmatrix M){ Gen_node a; a=gen_node(); a->type=Mtx_T; a->Genval.gval=(char *)M; a->next=0; return a; } Gmatrix Gmatrix_copy(Gmatrix M){ Gmatrix N; int i,j; N=Gmatrix_new(Mrows(M),Mcols(M)); for(i=1;i<=Mrows(M);i++) for(j=1;j<=Mcols(M);j++) *Mref(N,i,j)=copy_Gen_list(*Mref(M,i,j)); return N; } Gmatrix Gmatrix_Transpose(Gmatrix M){ Gmatrix N; int i,j; N=Gmatrix_new(Mcols(M),Mrows(M)); for(i=1;i<=Mrows(M);i++) for(j=1;j<=Mcols(M);j++) *Mref(N,j,i)=copy_Gen_list(*Mref(M,i,j)); return N; } int Gen_Mtx_Specs(Gen_node g,int *r, int *c, int *t){ int i, j; Gmatrix M; if (Gen_type(g)!=Mtx_T&&Gen_type(g)!=Sys_T)return FALSE; M=Gen_Mtx(g); *r=GMrows(M); *c=GMcols(M); *t=Int_T; for(i=1;i<=*r;i++) for(j=1;j<=*c;j++) *t=Common_Type(*t,Gen_type(*GMref(M,i,j))); return TRUE; } Gen_node Link(Gen_node g1, Gen_node g2) { #ifdef LOG_PRINT if (g1->next!=0) fprintf(stdout /* was Pel_Out */, "Warning in Link, g1 already has successor\n"); #endif g1->next=g2; return g1; } Gen_node SYSND(Gmatrix M){ Gen_node a; a=gen_node(); a->type=Sys_T; a->Genval.gval=(char *)M; a->next=0; return a; } Gen_node XPLND(Gen_node g) {Gen_node a; a=gen_node(); a->type=Xpl_T; a->Genval.lval=g; return a; } gambit-0.2010.09.01/src/tools/enumpoly/pelgmatr.h0000644000076500007650000000471311350032206016220 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* ** copyright (c) 1995 Birk Huber */ #ifndef PELICAN_GMATRIX_H #define PELICAN_GMATRIX_H #include "pelgntyp.h" #include "pelpred.h" struct Gmatrix_t { int store; int topc; int topr; int ncols; Gen_node *coords; }; typedef struct Gmatrix_t *Gmatrix; /* ** matrix access macroes */ int GMstore(Gmatrix M); /* maximum #elts available*/ int GMMrows(Gmatrix M); /* maximum #rows */ int GMrows(Gmatrix M); /* number rows stored */ int GMcols(Gmatrix M); /* number cols stored */ Gen_node *GMref1(Gmatrix M, int i, int j); #define GMref0(M,i,j) (GMref(M,(i+1),(j+1))) /* acces starting at 0 */ #define GMref(M,i,j) (GMref1((M),i,j)) /* use Mref1 by default */ /* ** Constructor/Gestructors/Gisplay */ Gmatrix Gmatrix_new(int r, int c); Gmatrix Gmatrix_resize(Gmatrix M, int r, int d); void Gmatrix_free(Gmatrix V); Gmatrix Gmatrix_print(Gmatrix M); /* ** Arithmatic and other operations on Gmatrices */ Gmatrix Gmatrix_Dop(Gmatrix M1, Gmatrix M2,Gen_node (*)(Gen_node)); Gmatrix Gmatrix_Sop(Gen_node g,Gmatrix M1 ,Gen_node (*)(Gen_node)); Gmatrix Gmatrix_Mop(Gmatrix M1, Gmatrix M2,Gen_node identity, Gen_node (*)(Gen_node),Gen_node (*)(Gen_node)); Gmatrix Gmatrix_Transpose(Gmatrix M1); Gen_node GMND(Gmatrix); Gmatrix Gmatrix_copy(Gmatrix M); Gmatrix Gen_Mtx(Gen_node g); int Gen_Mtx_Specs(Gen_node,int *, int *, int *); /* The following were moved from gennode.h to here on 3/26/00 - AMM */ Gen_node Link(Gen_node g1, Gen_node g2); Gen_node XPLND(Gen_node g); Gen_node SYSND(Gmatrix M); #endif /* PELICAN_GMATRIX_H */ gambit-0.2010.09.01/src/tools/enumpoly/pelgntyp.h0000644000076500007650000000576311351773322016271 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* ** copyright (c) 1995 Birk Huber */ #ifndef GENTYPE_H #define GENTYPE_H #include "pelpsys.h" /* define basic data types to be manipulated */ #define INVALID_T 0 /* ** Basic Numerical Types */ #define Int_T 2 #define Dbl_T 4 #define Cpx_T 6 #define Ply_T 8 #define Mtx_T 10 /* ** Other Types */ #define Str_T 50 #define Idf_T 60 #define Lst_T 70 #define Ast_T 80 #define Prc_T 90 #define Rng_T 1000 #define Err_T 1100 /* ** Alias Types */ #define Sys_T 100 #define Xpl_T 110 #define Npl_T 120 #ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL (void*)0 #endif #endif typedef struct Gen_node_tag *Gen_node; struct Gen_node_tag { int type; Gen_node next; union { int ival; double dval; fcomplex cval; polynomial1 pval; char *gval; char *idval; Gen_node (*proc)(Gen_node); struct Gen_node_tag *lval; } Genval; }; extern Pring Def_Ring; extern int N; Gen_node gen_node(); /* constructor for Gen_node */ Gen_node free_Gen_node(Gen_node); Gen_node free_Gen_list(Gen_node); Gen_node copy_Gen_node(Gen_node); Gen_node copy_Gen_list(Gen_node); void print_Gen_list(Gen_node); void print_Gen_node(Gen_node); Gen_node GMND(); Gen_node INTND(int); Gen_node DBLND(double); Gen_node CPXND(fcomplex); Gen_node PLYND(polynomial1); /* Gen_node SYSND(GMatrix); */ Gen_node XPLND(); Gen_node IDND(char *s); Gen_node PND(Gen_node p(Gen_node)); Gen_node Rerror(char *s, Gen_node g); /* accessors for Gen_nodes*/ Gen_node Gen_next(Gen_node); Gen_node Gen_set_next(Gen_node,Gen_node); int Gen_set_int(Gen_node g,int i); int Gen_int(Gen_node g); char *Gen_idval(Gen_node); Gen_node Gen_lval(Gen_node); Gen_node Gen_set_lval(Gen_node,Gen_node); int Gen_type(Gen_node); /* operations on Gen_Lists */ int Gen_length(Gen_node g); Gen_node Gen_elt(Gen_node g, int idx); Gen_node Gen_node_to_List(Gen_node); /*enclose a Gen_node in a list */ Gen_node Link(); /*link two gen nodes by their next pointers*/ Gen_node Cat(); /* miscalaneous */ char *Copy_String(char *); char *Copy_String_NQ(char *); Gen_node ASTND(node n); node Gen_aset(Gen_node g); polynomial1 Gen_poly(Gen_node g); #endif /* GENTYPE_H */ gambit-0.2010.09.01/src/tools/enumpoly/pelhomot.cc0000644000076500007650000032512011350032206016370 00000000000000/* Homotopies.c */ /* This is the implementation code from the various files that used to reside in the Cont subdirectory of Pelican0.80/source. */ #include "pelhomot.h" /**********************************************************************/ /*************** implementation code from Hom_params.c ****************/ /**********************************************************************/ double Hom_tol=.000001; /* tolerence for path tracking */ void print_Hom_params(FILE *outfile){ #ifdef HOM_PRINT fprintf(outfile," Hominuation Parameters:\n"); fprintf(outfile," Hom_tol=%g\n",Hom_tol) #endif ; } /* end Hom_params.c */ /************************************************************************/ /***************************** code from fixpnf.c ***********************/ /************************************************************************/ #define TRUE_ (1) #define FALSE_ (0) double get_abs_homog(); double coord_r, coord_i; /* Table of constant values */ static integer c__4 = 4; static integer c__1 = 1; /* Subroutine */ int fixpnf_0_(int n__, int *n, double *y, int *iflag, double *arcre, double *arcae, double *ansre, double *ansae, int *trace, double *a, int *nfe, double *arclen, double *yp, double *yold, double *ypold, double *qr, double *alpha, double *tz, int *pivot, double *w, double *wp, double *z0, double *z1, double *sspar, double *par, int *ipar, int tweak) /* added to adjust step size */ { /* System generated locals */ int qr_dim1, qr_offset, i__1, i__2; double d__1 /* ,abx UNUSED */; /* Builtin functions */ /* double sqrt(double); CANT DECLARE BUILTINS UNDER C++ */ integer s_wsfe(), do_fio(), e_wsfe(); /* in Hom_params.c these are int's */ /* Local variables */ static int nfec; static double hold; static int iter; extern double dnrm2_(integer *n, doublereal *dx, integer *incx); static double h, s; static long int crash; static int limit; extern double d1mach_(integer *); static long int start; static int nc, iflagc, jw; static double abserr, relerr; extern /* Subroutine */ int stepnf_(integer *n, integer *nfe, integer *iflag, logical *start, logical *crash, doublereal *hold, doublereal *h, doublereal *relerr, doublereal *abserr, doublereal *s, doublereal *y, doublereal *yp, doublereal *yold, doublereal *ypold, doublereal *a, doublereal *qr, doublereal *alpha, doublereal *tz, integer *pivot, doublereal *w, doublereal *wp, doublereal *z0, doublereal *z1, doublereal *sspar, doublereal *par, integer *ipar); static double curtol; extern /* Subroutine */ int rootnf_(int *n, int *nfe, int *iflag, double *relerr, double *abserr, double *y, double *yp, double *yold, double *ypold, double *a, double *qr, double *alpha, double *tz, int *pivot, double *w, double *wp, double *par, int *ipar); static int np1; static long int polsys; /* SUBROUTINE FIXPNF FINDS A FIXED POINT OR ZERO OF THE */ /* N-DIMENSIONAL VECTOR FUNCTION F(X), OR TRACKS A ZERO CURVE */ /* OF A GENERAL HOMOTOPY MAP RHO(A,LAMBDA,X). FOR THE FIXED */ /* POINT PROBLEM F(X) IS ASSUMED TO BE A C2 MAP OF SOME BALL */ /* INTO ITSELF. THE EQUATION X = F(X) IS SOLVED BY */ /* FOLLOWING THE ZERO CURVE OF THE HOMOTOPY MAP */ /* LAMBDA*(X - F(X)) + (1 - LAMBDA)*(X - A) , */ /* STARTING FROM LAMBDA = 0, X = A. THE CURVE IS PARAMETERIZED */ /* BY ARC LENGTH S, AND IS FOLLOWED BY SOLVING THE ORDINARY */ /* DIFFERENTIAL EQUATION D(HOMOTOPY MAP)/DS = 0 FOR */ /* Y(S) = (LAMBDA(S), X(S)) USING A HERMITE CUBIC PREDICTOR AND A */ /* CORRECTOR WHICH RETURNS TO THE ZERO CURVE ALONG THE FLOW NORMAL */ /* TO THE DAVIDENKO FLOW (WHICH CONSISTS OF THE INTEGRAL CURVES OF */ /* D(HOMOTOPY MAP)/DS ). */ /* FOR THE ZERO FINDING PROBLEM F(X) IS ASSUMED TO BE A C2 MAP */ /* SUCH THAT FOR SOME R > 0, X*F(X) >= 0 WHENEVER NORM(X) = R. */ /* THE EQUATION F(X) = 0 IS SOLVED BY FOLLOWING THE ZERO CURVE */ /* OF THE HOMOTOPY MAP */ /* LAMBDA*F(X) + (1 - LAMBDA)*(X - A) */ /* EMANATING FROM LAMBDA = 0, X = A. */ /* A MUST BE AN INTERIOR POINT OF THE ABOVE MENTIONED BALLS. */ /* FOR THE CURVE TRACKING PROBLEM RHO(A,LAMBDA,X) IS ASSUMED TO */ /* BE A C2 MAP FROM E**M X [0,1) X E**N INTO E**N, WHICH FOR */ /* ALMOST ALL PARAMETER VECTORS A IN SOME NONEMPTY OPEN SUBSET */ /* OF E**M SATISFIES */ /* RANK [D RHO(A,LAMBDA,X)/D LAMBDA , D RHO(A,LAMBDA,X)/DX] = N */ /* FOR ALL POINTS (LAMBDA,X) SUCH THAT RHO(A,LAMBDA,X)=0. IT IS */ /* FURTHER ASSUMED THAT */ /* RANK [ D RHO(A,0,X0)/DX ] = N . */ /* WITH A FIXED, THE ZERO CURVE OF RHO(A,LAMBDA,X) EMANATING */ /* FROM LAMBDA = 0, X = X0 IS TRACKED UNTIL LAMBDA = 1 BY */ /* SOLVING THE ORDINARY DIFFERENTIAL EQUATION */ /* D RHO(A,LAMBDA(S),X(S))/DS = 0 FOR Y(S) = (LAMBDA(S), X(S)), */ /* WHERE S IS ARC LENGTH ALONG THE ZERO CURVE. ALSO THE HOMOTOPY */ /* MAP RHO(A,LAMBDA,X) IS ASSUMED TO BE CONSTRUCTED SUCH THAT */ /* D LAMBDA(0)/DS > 0 . */ /* FOR THE FIXED POINT AND ZERO FINDING PROBLEMS, THE USER MUST SUPPLY */ /* A SUBROUTINE F(X,V) WHICH EVALUATES F(X) AT X AND RETURNS THE */ /* VECTOR F(X) IN V, AND A SUBROUTINE FJAC(X,V,K) WHICH RETURNS IN V */ /* THE KTH COLUMN OF THE JACOBIAN MATRIX OF F(X) EVALUATED AT X. FOR */ /* THE CURVE TRACKING PROBLEM, THE USER MUST SUPPLY A SUBROUTINE */ /* RHO(A,LAMBDA,X,V,PAR,IPAR) WHICH EVALUATES THE HOMOTOPY MAP RHO AT */ /* (A,LAMBDA,X) AND RETURNS THE VECTOR RHO(A,LAMBDA,X) IN V, AND A */ /* SUBROUTINE RHOJAC(A,LAMBDA,X,V,K,PAR,IPAR) WHICH RETURNS IN V THE KTH */ /* COLUMN OF THE N X (N+1) JACOBIAN MATRIX [D RHO/D LAMBDA, D RHO/DX] */ /* EVALUATED AT (A,LAMBDA,X). FIXPNF DIRECTLY OR INDIRECTLY USES */ /* THE SUBROUTINES STEPNF , TANGNF , ROOTNF , ROOT , F (OR RHO ), */ /* FJAC (OR RHOJAC ), D1MACH , AND THE BLAS FUNCTIONS DDOT AND */ /* DNRM2 . ONLY D1MACH CONTAINS MACHINE DEPENDENT CONSTANTS. */ /* NO OTHER MODIFICATIONS BY THE USER ARE REQUIRED. */ /* ON INPUT: */ /* N IS THE DIMENSION OF X, F(X), AND RHO(A,LAMBDA,X). */ /* Y IS AN ARRRAY OF LENGTH N + 1. (Y(2),...,Y(N+1)) = A IS THE */ /* STARTING POINT FOR THE ZERO CURVE FOR THE FIXED POINT AND */ /* ZERO FINDING PROBLEMS. (Y(2),...,Y(N+1)) = X0 FOR THE CURVE */ /* TRACKING PROBLEM. */ /* IFLAG CAN BE -2, -1, 0, 2, OR 3. IFLAG SHOULD BE 0 ON THE */ /* FIRST CALL TO FIXPNF FOR THE PROBLEM X=F(X), -1 FOR THE */ /* PROBLEM F(X)=0, AND -2 FOR THE PROBLEM RHO(A,LAMBDA,X)=0. */ /* IN CERTAIN SITUATIONS IFLAG IS SET TO 2 OR 3 BY FIXPNF, */ /* AND FIXPNF CAN BE CALLED AGAIN WITHOUT CHANGING IFLAG. */ /* ARCRE , ARCAE ARE THE RELATIVE AND ABSOLUTE ERRORS, RESPECTIVELY, */ /* ALLOWED THE NORMAL FLOW ITERATION ALONG THE ZERO CURVE. IF */ /* ARC?E .LE. 0.0 ON INPUT IT IS RESET TO .5*SQRT(ANS?E) . */ /* NORMALLY ARC?E SHOULD BE CONSIDERABLY LARGER THAN ANS?E . */ /* ANSRE , ANSAE ARE THE RELATIVE AND ABSOLUTE ERROR VALUES USED FOR */ /* THE ANSWER AT LAMBDA = 1. THE ACCEPTED ANSWER Y = (LAMBDA, X) */ /* SATISFIES */ /* |Y(1) - 1| .LE. ANSRE + ANSAE .AND. */ /* ||Z|| .LE. ANSRE*||X|| + ANSAE WHERE */ /* (.,Z) IS THE NEWTON STEP TO Y. */ /* TRACE IS AN INTEGER SPECIFYING THE LOGICAL I/O UNIT FOR */ /* INTERMEDIATE OUTPUT. IF TRACE .GT. 0 THE POINTS COMPUTED ON */ /* THE ZERO CURVE ARE WRITTEN TO I/O UNIT TRACE . */ /* A(1:*) CONTAINS THE PARAMETER VECTOR A . FOR THE FIXED POINT */ /* AND ZERO FINDING PROBLEMS, A NEED NOT BE INITIALIZED BY THE */ /* USER, AND IS ASSUMED TO HAVE LENGTH N. FOR THE CURVE */ /* TRACKING PROBLEM, A MUST BE INITIALIZED BY THE USER. */ /* YP(1:N+1) IS A WORK ARRAY CONTAINING THE TANGENT VECTOR TO */ /* THE ZERO CURVE AT THE CURRENT POINT Y . */ /* YOLD(1:N+1) IS A WORK ARRAY CONTAINING THE PREVIOUS POINT FOUND */ /* ON THE ZERO CURVE. */ /* YPOLD(1:N+1) IS A WORK ARRAY CONTAINING THE TANGENT VECTOR TO */ /* THE ZERO CURVE AT YOLD . */ /* QR(1:N,1:N+2), ALPHA(1:N), TZ(1:N+1), PIVOT(1:N+1) , W(1:N+1) , */ /* WP(1:N+1) , Z0(1:N+1) , Z1(1:N+1) ARE ALL WORK ARRAYS USED BY */ /* STEPNF TO CALCULATE THE TANGENT VECTORS AND NEWTON STEPS. */ /* SSPAR(1:8) = (LIDEAL, RIDEAL, DIDEAL, HMIN, HMAX, BMIN, BMAX, P) IS */ /* A VECTOR OF PARAMETERS USED FOR THE OPTIMAL STEP SIZE ESTIMATION. */ /* IF SSPAR(J) .LE. 0.0 ON INPUT, IT IS RESET TO A DEFAULT VALUE */ /* BY FIXPNF . OTHERWISE THE INPUT VALUE OF SSPAR(J) IS USED. */ /* SEE THE COMMENTS BELOW AND IN STEPNF FOR MORE INFORMATION ABOUT */ /* THESE CONSTANTS. */ /* PAR(1:*) AND IPAR(1:*) ARE ARRAYS FOR (OPTIONAL) USER PARAMETERS, */ /* WHICH ARE SIMPLY PASSED THROUGH TO THE USER WRITTEN SUBROUTINES */ /* RHO, RHOJAC. */ /* ON OUTPUT: */ /* N , TRACE , A ARE UNCHANGED. */ /* Y(1) = LAMBDA, (Y(2),...,Y(N+1)) = X, AND Y IS AN APPROXIMATE */ /* ZERO OF THE HOMOTOPY MAP. NORMALLY LAMBDA = 1 AND X IS A */ /* FIXED POINT(ZERO) OF F(X). IN ABNORMAL SITUATIONS LAMBDA */ /* MAY ONLY BE NEAR 1 AND X IS NEAR A FIXED POINT(ZERO). */ /* IFLAG = */ /* -2 CAUSES FIXPNF TO INITIALIZE EVERYTHING FOR THE PROBLEM */ /* RHO(A,LAMBDA,X) = 0 (USE ON FIRST CALL). */ /* -1 CAUSES FIXPNF TO INITIALIZE EVERYTHING FOR THE PROBLEM */ /* F(X) = 0 (USE ON FIRST CALL). */ /* 0 CAUSES FIXPNF TO INITIALIZE EVERYTHING FOR THE PROBLEM */ /* X = F(X) (USE ON FIRST CALL). */ /* 1 NORMAL RETURN. */ /* 2 SPECIFIED ERROR TOLERANCE CANNOT BE MET. SOME OR ALL OF */ /* ARCRE , ARCAE , ANSRE , ANSAE HAVE BEEN INCREASED TO */ /* SUITABLE VALUES. TO CONTINUE, JUST CALL FIXPNF AGAIN */ /* WITHOUT CHANGING ANY PARAMETERS. */ /* 3 STEPNF HAS BEEN CALLED 1000 TIMES. TO CONTINUE, CALL */ /* FIXPNF AGAIN WITHOUT CHANGING ANY PARAMETERS. */ /* 4 JACOBIAN MATRIX DOES NOT HAVE FULL RANK. THE ALGORITHM */ /* HAS FAILED (THE ZERO CURVE OF THE HOMOTOPY MAP CANNOT BE */ /* FOLLOWED ANY FURTHER). */ /* 5 THE TRACKING ALGORITHM HAS LOST THE ZERO CURVE OF THE */ /* HOMOTOPY MAP AND IS NOT MAKING PROGRESS. THE ERROR TOLERANCES */ /* ARC?E AND ANS?E WERE TOO LENIENT. THE PROBLEM SHOULD BE */ /* RESTARTED BY CALLING FIXPNF WITH SMALLER ERROR TOLERANCES */ /* AND IFLAG = 0 (-1, -2). */ /* 6 THE NORMAL FLOW NEWTON ITERATION IN STEPNF OR ROOTNF */ /* FAILED TO CONVERGE. THE ERROR TOLERANCES ANS?E MAY BE TOO */ /* STRINGENT. */ /* 7 ILLEGAL INPUT PARAMETERS, A FATAL ERROR. */ /* ARCRE , ARCAE , ANSRE , ANSAE ARE UNCHANGED AFTER A NORMAL RETURN */ /* (IFLAG = 1). THEY ARE INCREASED TO APPROPRIATE VALUES ON THE */ /* RETURN IFLAG = 2 . */ /* NFE IS THE NUMBER OF FUNCTION EVALUATIONS (= NUMBER OF */ /* JACOBIAN EVALUATIONS). */ /* ARCLEN IS THE LENGTH OF THE PATH FOLLOWED. */ /* ***** ARRAY DECLARATIONS. ***** */ /* ***** END OF DIMENSIONAL INFORMATION. ***** */ /* LIMITD IS AN UPPER BOUND ON THE NUMBER OF STEPS. IT MAY BE */ /* CHANGED BY CHANGING THE FOLLOWING PARAMETER STATEMENT: */ /* SWITCH FROM THE TOLERANCE ARC?E TO THE (FINER) TOLERANCE ANS?E IF */ /* THE CURVATURE OF ANY COMPONENT OF Y EXCEEDS CURSW. */ /* : : : : : : : : : : : : : : : : : : : : : : : : */ /* SET LOGICAL SWITCH TO REFLECT ENTRY POINT. */ /* Parameter adjustments */ --y; --a; --yp; --yold; --ypold; qr_dim1 = *n; qr_offset = qr_dim1 + 1; qr -= qr_offset; --alpha; --tz; --pivot; --w; --wp; --z0; --z1; --sspar; --par; --ipar; /* Function Body */ switch(n__) { case 1: goto L_polynf; } polsys = FALSE_; goto L11; L_polynf: polsys = TRUE_; L11: if (*n <= 0 || *ansre <= (float)0. || *ansae < (float)0.) { *iflag = 7; } if (*iflag >= -2 && *iflag <= 0) { goto L20; } if (*iflag == 2) { goto L120; } if (*iflag == 3) { goto L90; } /* ONLY VALID INPUT FOR IFLAG IS -2, -1, 0, 2, 3. */ *iflag = 7; return 0; /* ***** INITIALIZATION BLOCK. ***** */ L20: *arclen = (float)0.; if (*arcre <= (float)0.) { *arcre = sqrt(*ansre) * (float).5; } if (*arcae <= (float)0.) { *arcae = sqrt(*ansae) * (float).5; } nc = *n; nfec = 0; iflagc = *iflag; np1 = *n + 1; /* SET INITIAL CONDITIONS FOR FIRST CALL TO STEPNF . */ start = TRUE_; crash = FALSE_; hold = (float)1.; h = (float).1; s = (float)0.; ypold[1] = (float)1.; yp[1] = (float)1.; y[1] = (float)0.; i__1 = np1; for (jw = 2; jw <= i__1; ++jw) { ypold[jw] = (float)0.; yp[jw] = (float)0.; /* L40: */ } /* SET OPTIMAL STEP SIZE ESTIMATION PARAMETERS. */ /* LET Z[K] DENOTE THE NEWTON ITERATES ALONG THE FLOW NORMAL TO THE */ /* DAVIDENKO FLOW AND Y THEIR LIMIT. */ /* IDEAL CONTRACTION FACTOR: ||Z[2] - Z[1]|| / ||Z[1] - Z[0]|| */ if (sspar[1] <= (float)0.) { sspar[1] = (float).5; } /* IDEAL RESIDUAL FACTOR: ||RHO(A, Z[1])|| / ||RHO(A, Z[0])|| */ if (sspar[2] <= (float)0.) { sspar[2] = (float).01; } /* IDEAL DISTANCE FACTOR: ||Z[1] - Y|| / ||Z[0] - Y|| */ if (sspar[3] <= (float)0.) { sspar[3] = (float).5; } /* MINIMUM STEP SIZE HMIN . */ if (sspar[4] <= (float)0.) { sspar[4] = (sqrt(*n + (float)1.) + (float)4.) * d1mach_(&c__4); } /* MAXIMUM STEP SIZE HMAX . */ if (sspar[5] <= (float)0.) { sspar[5] = (float)1.; } /* MINIMUM STEP SIZE REDUCTION FACTOR BMIN . */ if (sspar[6] <= (float)0.) { sspar[6] = (float).1; } /* MAXIMUM STEP SIZE EXPANSION FACTOR BMAX . */ if (sspar[7] <= (float)0.) { sspar[7] = (float)3.; } /* ASSUMED OPERATING ORDER P . */ if (sspar[8] <= (float)0.) { sspar[8] = (float)2.; } /* Adjustments of step size */ if (tweak == 1) sspar[5] = (float).1; else if (tweak == 2) sspar[5] = (float).01; else if (tweak == 3) sspar[5] = (float).001; /* LOAD A FOR THE FIXED POINT AND ZERO FINDING PROBLEMS. */ if (iflagc >= -1) { i__1 = np1; for (jw = 2; jw <= i__1; ++jw) { a[jw - 1] = y[jw]; /* L60: */ } } L90: limit = 1000; /* Adjustment of maximum number of steps for smaller step size */ if (tweak == 1) limit = 10000; else if (tweak == 2) limit = 100000; else if (tweak == 3) limit = 1000000; /* ***** END OF INITIALIZATION BLOCK. ***** */ /* ***** MAIN LOOP. ***** */ L120: i__1 = limit; for (iter = 1; iter <= i__1; ++iter) { if (y[1] < (float)0.) { *arclen = s; *iflag = 5; return 0; } /* SET DIFFERENT ERROR TOLERANCE IF THE TRAJECTORY Y(S) HAS ANY HIGH */ /* CURVATURE COMPONENTS. */ /* L140: */ curtol = hold * 10.; relerr = *arcre; abserr = *arcae; i__2 = np1; for (jw = 1; jw <= i__2; ++jw) { if ((d__1 = yp[jw] - ypold[jw], abs((int)d__1)) > curtol) { relerr = *ansre; abserr = *ansae; goto L200; } /* L160: */ } /* TAKE A STEP ALONG THE CURVE. */ L200: stepnf_((integer *)&nc, (integer *)&nfec, (integer *)&iflagc, &start, &crash, &hold, &h, &relerr, &abserr, &s, &y[1], &yp[1], &yold[1], &ypold[1], &a[1], &qr[ qr_offset], &alpha[1], &tz[1], (integer *)&pivot[1], &w[1], &wp[1], &z0[ 1], &z1[1], &sspar[1], &par[1], (integer *)&ipar[1]); /* PRINT LATEST POINT ON CURVE IF REQUESTED. */ if (*trace > 0) { print_homog(y+2,&coord_r, &coord_i); #ifdef HOM_PRINT fprintf(Hom_LogFile,"C %g %g",coord_r,coord_i) #endif ; for(jw=2; jw<=np1; jw++){ #ifdef HOM_PRINT fprintf(Hom_LogFile," %d = %g",jw,y[jw]) #endif ; } #ifdef HOM_PRINT fprintf(Hom_LogFile," %g",y[1]) #endif ; } #ifdef HOM_PRINT fprintf(Hom_LogFile," 4 0 %d %d %f\n",iter,nfec,s) #endif ; *nfe = nfec; /* CHECK IF THE STEP WAS SUCCESSFUL. */ if (iflagc > 0) { *arclen = s; *iflag = iflagc; return 0; } if (crash) { /* RETURN CODE FOR ERROR TOLERANCE TOO SMALL. */ *iflag = 2; /* CHANGE ERROR TOLERANCES. */ if (*arcre < relerr) { *arcre = relerr; } if (*ansre < relerr) { *ansre = relerr; } if (*arcae < abserr) { *arcae = abserr; } if (*ansae < abserr) { *ansae = abserr; } /* CHANGE LIMIT ON NUMBER OF ITERATIONS. */ limit -= iter; return 0; } if (y[1] >= (float)1.) { /* USE HERMITE CUBIC INTERPOLATION AND NEWTON ITERATION TO GET THE */ /* ANSWER AT LAMBDA = 1.0 . */ /* SAVE YOLD FOR ARC LENGTH CALCULATION LATER. */ i__2 = np1; for (jw = 1; jw <= i__2; ++jw) { z0[jw] = yold[jw]; /* L260: */ } rootnf_(&nc, &nfec, &iflagc, ansre, ansae, &y[1], &yp[1], &yold[1], &ypold[1], &a[1], &qr[qr_offset], &alpha[1], &tz[1], &pivot[1], &w[1], &wp[1], &par[1], &ipar[1]); *nfe = nfec; *iflag = 1; /* SET ERROR FLAG IF ROOTNF COULD NOT GET THE POINT ON THE ZERO */ /* CURVE AT LAMBDA = 1.0 . */ if (iflagc > 0) { *iflag = iflagc; } /* CALCULATE FINAL ARC LENGTH. */ i__2 = np1; for (jw = 1; jw <= i__2; ++jw) { w[jw] = y[jw] - z0[jw]; /* L290: */ } *arclen = s - hold + dnrm2_((integer *)&np1, &w[1], &c__1); return 0; } /* FOR POLYNOMIAL SYSTEMS AND THE POLSYS HOMOTOPY MAP, */ /* D LAMBDA/DS .GE. 0 NECESSARILY. THIS CONDITION IS FORCED HERE IF */ /* THE ENTRY POINT WAS POLYNF . */ /* if (polsys) { */ if (yp[1] < (float)0.) { /* REVERSE TANGENT DIRECTION SO D LAMBDA/DS = YP(1) > 0 . */ i__2 = np1; for (jw = 1; jw <= i__2; ++jw) { yp[jw] = -yp[jw]; ypold[jw] = yp[jw]; /* L310: */ /* } */ /* FORCE STEPNF TO USE THE LINEAR PREDICTOR FOR THE NEXT STE P ONLY. */ start = TRUE_; } } /* L400: */ } /* ***** END OF MAIN LOOP. ***** */ /* LAMBDA HAS NOT REACHED 1 IN 1000 STEPS. */ *iflag = 3; *arclen = s; return 0; } /* fixpnf_ */ /* Subroutine */ int fixpnf_(int *n, double *y, int *iflag, double *arcre, double *arcae, double *ansre, double *ansae, int *trace, double *a, int *nfe, double *arclen, double *yp, double *yold, double *ypold, double *qr, double *alpha, double *tz, int *pivot, double *w, double *wp, double *z0, double *z1, double *sspar, double *par, int *ipar, int tweak) { return fixpnf_0_(0, n, y, iflag, arcre, arcae, ansre, ansae, trace, a, nfe, arclen, yp, yold, ypold, qr, alpha, tz, pivot, w, wp, z0, z1, sspar, par, ipar, tweak); } /* Subroutine */ int polynf_(int *n, double *y, int *iflag, double *arcre, double *arcae, double *ansre, double *ansae, int *trace, double *a, int *nfe, double *arclen, double *yp, double *yold, double *ypold, double *qr, double *alpha, double *tz, int *pivot, double *w, double *wp, double *z0, double *z1, double *sspar, double *par, int *ipar, int tweak) { return fixpnf_0_(1, n, y, iflag, arcre, arcae, ansre, ansae, trace, a, nfe, arclen, yp, yold, ypold, qr, alpha, tz, pivot, w, wp, z0, z1, sspar, par, ipar, tweak); } /* end fixpnf.c */ /**********************************************************************/ /***************** implementation code from Hom_Mem.c *****************/ /**********************************************************************/ /*-------------------------------------------------------------------- Workspace and Workspace management macros -------------------------------------------------------------------*/ #define TOPN 20 /*Assume no more than 20 variables*/ #define TOPM 500 /* Assume no more than 500 monomials total*/ static int Istore[TOPM*(TOPN+1)+3*TOPN+2+TOPM]; static double Dstore[TOPM*2+12*(TOPN+1)+8+TOPN*(TOPN+2)+1]; static int didx=0,iidx=0; /* initialization for storage currently static should be made dynamic*/ /* access funtions to double storage */ double *Dres(int sz){ int v=didx; didx+=sz; return Dstore+v;} int Dtop(){return didx;} int Dfree(int ntop){ didx=ntop; return 0;} /* access funtions to int storage */ int *Ires(int sz){ int v=iidx; iidx+=sz; return Istore+v;} int Itop(){return iidx;} int Ifree(int ntop){ iidx=ntop; return 0;} /* end Hom_Mem.c */ /**********************************************************************/ /***************** implementation code from d1mach.c ******************/ /**********************************************************************/ /* Table of constant values */ doublereal d1mach_(integer *i) { /* Initialized data */ static integer sc = 987; static struct { integer e_1[10]; doublereal e_2; } equiv_4 = { { 0, 1048576, -1, 2146435071, 0, 1017118720, 0, 1018167296, 1352628735, 1070810131 }, 0.0 }; /* System generated locals */ doublereal ret_val = 0.0; /* Builtin functions */ /* Subroutine */ int s_stop(); integer s_wsfe(), do_fio(), e_wsfe(); /* Local variables */ #define log10 ((integer *)&equiv_4 + 8) #define dmach ((doublereal *)&equiv_4) #define large ((integer *)&equiv_4 + 2) #define small ((integer *)&equiv_4) #define diver ((integer *)&equiv_4 + 6) #define right ((integer *)&equiv_4 + 4) /* DOUBLE-PRECISION MACHINE CONSTANTS */ /* D1MACH( 1) = B**(EMIN-1), THE SMALLEST POSITIVE MAGNITUDE. */ /* D1MACH( 2) = B**EMAX*(1 - B**(-T)), THE LARGEST MAGNITUDE. */ /* D1MACH( 3) = B**(-T), THE SMALLEST RELATIVE SPACING. */ /* D1MACH( 4) = B**(1-T), THE LARGEST RELATIVE SPACING. */ /* D1MACH( 5) = LOG10(B) */ /* TO ALTER THIS FUNCTION FOR A PARTICULAR ENVIRONMENT, */ /* THE DESIRED SET OF DATA STATEMENTS SHOULD BE ACTIVATED BY */ /* REMOVING THE C FROM COLUMN 1. */ /* ON RARE MACHINES A STATIC STATEMENT MAY NEED TO BE ADDED. */ /* (BUT PROBABLY MORE SYSTEMS PROHIBIT IT THAN REQUIRE IT.) */ /* FOR IEEE-ARITHMETIC MACHINES (BINARY STANDARD), ONE OF THE FIRST */ /* TWO SETS OF CONSTANTS BELOW SHOULD BE APPROPRIATE. IF YOU DO NOT */ /* KNOW WHICH SET TO USE, TRY BOTH AND SEE WHICH GIVES PLAUSIBLE */ /* VALUES. */ /* WHERE POSSIBLE, DECIMAL, OCTAL OR HEXADECIMAL CONSTANTS ARE USED */ /* TO SPECIFY THE CONSTANTS EXACTLY. SOMETIMES THIS REQUIRES USING */ /* EQUIVALENT INTEGER ARRAYS. IF YOUR COMPILER USES HALF-WORD */ /* INTEGERS BY DEFAULT (SOMETIMES CALLED INTEGER*2), YOU MAY NEED TO */ /* CHANGE INTEGER TO INTEGER*4 OR OTHERWISE INSTRUCT YOUR COMPILER */ /* TO USE FULL-WORD INTEGERS IN THE NEXT 5 DECLARATIONS. */ /* COMMENTS JUST BEFORE THE END STATEMENT (LINES STARTING WITH *) */ /* GIVE C SOURCE FOR D1MACH. */ /* MACHINE CONSTANTS FOR BIG-ENDIAN IEEE ARITHMETIC (BINARY FORMAT) */ /* MACHINES IN WHICH THE MOST SIGNIFICANT BYTE IS STORED FIRST, */ /* SUCH AS THE AT&T 3B SERIES, MOTOROLA 68000 BASED MACHINES (E.G. */ /* SUN 3), AND MACHINES THAT USE SPARC, HP, OR IBM RISC CHIPS. */ /* DATA SMALL(1),SMALL(2) / 1048576, 0 / */ /* DATA LARGE(1),LARGE(2) / 2146435071, -1 / */ /* DATA RIGHT(1),RIGHT(2) / 1017118720, 0 / */ /* DATA DIVER(1),DIVER(2) / 1018167296, 0 / */ /* DATA LOG10(1),LOG10(2) / 1070810131, 1352628735 /, SC/987/ */ /* MACHINE CONSTANTS FOR LITTLE-ENDIAN (BINARY) IEEE ARITHMETIC */ /* MACHINES IN WHICH THE LEAST SIGNIFICANT BYTE IS STORED FIRST, */ /* E.G. IBM PCS AND OTHER MACHINES THAT USE INTEL 80X87 OR DEC */ /* ALPHA CHIPS. */ /* MACHINE CONSTANTS FOR AMDAHL MACHINES. */ /* DATA SMALL(1),SMALL(2) / 1048576, 0 / */ /* DATA LARGE(1),LARGE(2) / 2147483647, -1 / */ /* DATA RIGHT(1),RIGHT(2) / 856686592, 0 / */ /* DATA DIVER(1),DIVER(2) / 873463808, 0 / */ /* DATA LOG10(1),LOG10(2) / 1091781651, 1352628735 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE BURROUGHS 1700 SYSTEM. */ /* DATA SMALL(1) / ZC00800000 / */ /* DATA SMALL(2) / Z000000000 / */ /* DATA LARGE(1) / ZDFFFFFFFF / */ /* DATA LARGE(2) / ZFFFFFFFFF / */ /* DATA RIGHT(1) / ZCC5800000 / */ /* DATA RIGHT(2) / Z000000000 / */ /* DATA DIVER(1) / ZCC6800000 / */ /* DATA DIVER(2) / Z000000000 / */ /* DATA LOG10(1) / ZD00E730E7 / */ /* DATA LOG10(2) / ZC77800DC0 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE BURROUGHS 5700 SYSTEM. */ /* DATA SMALL(1) / O1771000000000000 / */ /* DATA SMALL(2) / O0000000000000000 / */ /* DATA LARGE(1) / O0777777777777777 / */ /* DATA LARGE(2) / O0007777777777777 / */ /* DATA RIGHT(1) / O1461000000000000 / */ /* DATA RIGHT(2) / O0000000000000000 / */ /* DATA DIVER(1) / O1451000000000000 / */ /* DATA DIVER(2) / O0000000000000000 / */ /* DATA LOG10(1) / O1157163034761674 / */ /* DATA LOG10(2) / O0006677466732724 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE BURROUGHS 6700/7700 SYSTEMS. */ /* DATA SMALL(1) / O1771000000000000 / */ /* DATA SMALL(2) / O7770000000000000 / */ /* DATA LARGE(1) / O0777777777777777 / */ /* DATA LARGE(2) / O7777777777777777 / */ /* DATA RIGHT(1) / O1461000000000000 / */ /* DATA RIGHT(2) / O0000000000000000 / */ /* DATA DIVER(1) / O1451000000000000 / */ /* DATA DIVER(2) / O0000000000000000 / */ /* DATA LOG10(1) / O1157163034761674 / */ /* DATA LOG10(2) / O0006677466732724 /, SC/987/ */ /* MACHINE CONSTANTS FOR FTN4 ON THE CDC 6000/7000 SERIES. */ /* DATA SMALL(1) / 00564000000000000000B / */ /* DATA SMALL(2) / 00000000000000000000B / */ /* DATA LARGE(1) / 37757777777777777777B / */ /* DATA LARGE(2) / 37157777777777777774B / */ /* DATA RIGHT(1) / 15624000000000000000B / */ /* DATA RIGHT(2) / 00000000000000000000B / */ /* DATA DIVER(1) / 15634000000000000000B / */ /* DATA DIVER(2) / 00000000000000000000B / */ /* DATA LOG10(1) / 17164642023241175717B / */ /* DATA LOG10(2) / 16367571421742254654B /, SC/987/ */ /* MACHINE CONSTANTS FOR FTN5 ON THE CDC 6000/7000 SERIES. */ /* DATA SMALL(1) / O"00564000000000000000" / */ /* DATA SMALL(2) / O"00000000000000000000" / */ /* DATA LARGE(1) / O"37757777777777777777" / */ /* DATA LARGE(2) / O"37157777777777777774" / */ /* DATA RIGHT(1) / O"15624000000000000000" / */ /* DATA RIGHT(2) / O"00000000000000000000" / */ /* DATA DIVER(1) / O"15634000000000000000" / */ /* DATA DIVER(2) / O"00000000000000000000" / */ /* DATA LOG10(1) / O"17164642023241175717" / */ /* DATA LOG10(2) / O"16367571421742254654" /, SC/987/ */ /* MACHINE CONSTANTS FOR CONVEX C-1 */ /* DATA SMALL(1),SMALL(2) / '00100000'X, '00000000'X / */ /* DATA LARGE(1),LARGE(2) / '7FFFFFFF'X, 'FFFFFFFF'X / */ /* DATA RIGHT(1),RIGHT(2) / '3CC00000'X, '00000000'X / */ /* DATA DIVER(1),DIVER(2) / '3CD00000'X, '00000000'X / */ /* DATA LOG10(1),LOG10(2) / '3FF34413'X, '509F79FF'X /, SC/987/ */ /* MACHINE CONSTANTS FOR THE CRAY 1, XMP, 2, AND 3. */ /* DATA SMALL(1) / 201354000000000000000B / */ /* DATA SMALL(2) / 000000000000000000000B / */ /* DATA LARGE(1) / 577767777777777777777B / */ /* DATA LARGE(2) / 000007777777777777776B / */ /* DATA RIGHT(1) / 376434000000000000000B / */ /* DATA RIGHT(2) / 000000000000000000000B / */ /* DATA DIVER(1) / 376444000000000000000B / */ /* DATA DIVER(2) / 000000000000000000000B / */ /* DATA LOG10(1) / 377774642023241175717B / */ /* DATA LOG10(2) / 000007571421742254654B /, SC/987/ */ /* MACHINE CONSTANTS FOR THE DATA GENERAL ECLIPSE S/200 */ /* SMALL, LARGE, RIGHT, DIVER, LOG10 SHOULD BE DECLARED */ /* INTEGER SMALL(4), LARGE(4), RIGHT(4), DIVER(4), LOG10(4) */ /* NOTE - IT MAY BE APPROPRIATE TO INCLUDE THE FOLLOWING LINE - */ /* STATIC DMACH(5) */ /* DATA SMALL/20K,3*0/,LARGE/77777K,3*177777K/ */ /* DATA RIGHT/31420K,3*0/,DIVER/32020K,3*0/ */ /* DATA LOG10/40423K,42023K,50237K,74776K/, SC/987/ */ /* MACHINE CONSTANTS FOR THE HARRIS SLASH 6 AND SLASH 7 */ /* DATA SMALL(1),SMALL(2) / '20000000, '00000201 / */ /* DATA LARGE(1),LARGE(2) / '37777777, '37777577 / */ /* DATA RIGHT(1),RIGHT(2) / '20000000, '00000333 / */ /* DATA DIVER(1),DIVER(2) / '20000000, '00000334 / */ /* DATA LOG10(1),LOG10(2) / '23210115, '10237777 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE HONEYWELL DPS 8/70 SERIES. */ /* DATA SMALL(1),SMALL(2) / O402400000000, O000000000000 / */ /* DATA LARGE(1),LARGE(2) / O376777777777, O777777777777 / */ /* DATA RIGHT(1),RIGHT(2) / O604400000000, O000000000000 / */ /* DATA DIVER(1),DIVER(2) / O606400000000, O000000000000 / */ /* DATA LOG10(1),LOG10(2) / O776464202324, O117571775714 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE IBM 360/370 SERIES, */ /* THE XEROX SIGMA 5/7/9 AND THE SEL SYSTEMS 85/86. */ /* DATA SMALL(1),SMALL(2) / Z00100000, Z00000000 / */ /* DATA LARGE(1),LARGE(2) / Z7FFFFFFF, ZFFFFFFFF / */ /* DATA RIGHT(1),RIGHT(2) / Z33100000, Z00000000 / */ /* DATA DIVER(1),DIVER(2) / Z34100000, Z00000000 / */ /* DATA LOG10(1),LOG10(2) / Z41134413, Z509F79FF /, SC/987/ */ /* MACHINE CONSTANTS FOR THE INTERDATA 8/32 */ /* WITH THE UNIX SYSTEM FORTRAN 77 COMPILER. */ /* FOR THE INTERDATA FORTRAN VII COMPILER REPLACE */ /* THE Z'S SPECIFYING HEX CONSTANTS WITH Y'S. */ /* DATA SMALL(1),SMALL(2) / Z'00100000', Z'00000000' / */ /* DATA LARGE(1),LARGE(2) / Z'7EFFFFFF', Z'FFFFFFFF' / */ /* DATA RIGHT(1),RIGHT(2) / Z'33100000', Z'00000000' / */ /* DATA DIVER(1),DIVER(2) / Z'34100000', Z'00000000' / */ /* DATA LOG10(1),LOG10(2) / Z'41134413', Z'509F79FF' /, SC/987/ */ /* MACHINE CONSTANTS FOR THE PDP-10 (KA PROCESSOR). */ /* DATA SMALL(1),SMALL(2) / "033400000000, "000000000000 / */ /* DATA LARGE(1),LARGE(2) / "377777777777, "344777777777 / */ /* DATA RIGHT(1),RIGHT(2) / "113400000000, "000000000000 / */ /* DATA DIVER(1),DIVER(2) / "114400000000, "000000000000 / */ /* DATA LOG10(1),LOG10(2) / "177464202324, "144117571776 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE PDP-10 (KI PROCESSOR). */ /* DATA SMALL(1),SMALL(2) / "000400000000, "000000000000 / */ /* DATA LARGE(1),LARGE(2) / "377777777777, "377777777777 / */ /* DATA RIGHT(1),RIGHT(2) / "103400000000, "000000000000 / */ /* DATA DIVER(1),DIVER(2) / "104400000000, "000000000000 / */ /* DATA LOG10(1),LOG10(2) / "177464202324, "047674776746 /, SC/987/ */ /* MACHINE CONSTANTS FOR PDP-11 FORTRANS SUPPORTING */ /* 32-BIT INTEGERS (EXPRESSED IN INTEGER AND OCTAL). */ /* DATA SMALL(1),SMALL(2) / 8388608, 0 / */ /* DATA LARGE(1),LARGE(2) / 2147483647, -1 / */ /* DATA RIGHT(1),RIGHT(2) / 612368384, 0 / */ /* DATA DIVER(1),DIVER(2) / 620756992, 0 / */ /* DATA LOG10(1),LOG10(2) / 1067065498, -2063872008 /, SC/987/ */ /* DATA SMALL(1),SMALL(2) / O00040000000, O00000000000 / */ /* DATA LARGE(1),LARGE(2) / O17777777777, O37777777777 / */ /* DATA RIGHT(1),RIGHT(2) / O04440000000, O00000000000 / */ /* DATA DIVER(1),DIVER(2) / O04500000000, O00000000000 / */ /* DATA LOG10(1),LOG10(2) / O07746420232, O20476747770 /, SC/987/ */ /* MACHINE CONSTANTS FOR PDP-11 FORTRANS SUPPORTING */ /* 16-BIT INTEGERS (EXPRESSED IN INTEGER AND OCTAL). */ /* SMALL, LARGE, RIGHT, DIVER, LOG10 SHOULD BE DECLARED */ /* INTEGER SMALL(4), LARGE(4), RIGHT(4), DIVER(4), LOG10(4) */ /* DATA SMALL(1),SMALL(2) / 128, 0 / */ /* DATA SMALL(3),SMALL(4) / 0, 0 / */ /* DATA LARGE(1),LARGE(2) / 32767, -1 / */ /* DATA LARGE(3),LARGE(4) / -1, -1 / */ /* DATA RIGHT(1),RIGHT(2) / 9344, 0 / */ /* DATA RIGHT(3),RIGHT(4) / 0, 0 / */ /* DATA DIVER(1),DIVER(2) / 9472, 0 / */ /* DATA DIVER(3),DIVER(4) / 0, 0 / */ /* DATA LOG10(1),LOG10(2) / 16282, 8346 / */ /* DATA LOG10(3),LOG10(4) / -31493, -12296 /, SC/987/ */ /* DATA SMALL(1),SMALL(2) / O000200, O000000 / */ /* DATA SMALL(3),SMALL(4) / O000000, O000000 / */ /* DATA LARGE(1),LARGE(2) / O077777, O177777 / */ /* DATA LARGE(3),LARGE(4) / O177777, O177777 / */ /* DATA RIGHT(1),RIGHT(2) / O022200, O000000 / */ /* DATA RIGHT(3),RIGHT(4) / O000000, O000000 / */ /* DATA DIVER(1),DIVER(2) / O022400, O000000 / */ /* DATA DIVER(3),DIVER(4) / O000000, O000000 / */ /* DATA LOG10(1),LOG10(2) / O037632, O020232 / */ /* DATA LOG10(3),LOG10(4) / O102373, O147770 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE PRIME 50 SERIES SYSTEMS */ /* WITH 32-BIT INTEGERS AND 64V MODE INSTRUCTIONS, */ /* SUPPLIED BY IGOR BRAY. */ /* DATA SMALL(1),SMALL(2) / :10000000000, :00000100001 / */ /* DATA LARGE(1),LARGE(2) / :17777777777, :37777677775 / */ /* DATA RIGHT(1),RIGHT(2) / :10000000000, :00000000122 / */ /* DATA DIVER(1),DIVER(2) / :10000000000, :00000000123 / */ /* DATA LOG10(1),LOG10(2) / :11504046501, :07674600177 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE SEQUENT BALANCE 8000 */ /* DATA SMALL(1),SMALL(2) / $00000000, $00100000 / */ /* DATA LARGE(1),LARGE(2) / $FFFFFFFF, $7FEFFFFF / */ /* DATA RIGHT(1),RIGHT(2) / $00000000, $3CA00000 / */ /* DATA DIVER(1),DIVER(2) / $00000000, $3CB00000 / */ /* DATA LOG10(1),LOG10(2) / $509F79FF, $3FD34413 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE UNIVAC 1100 SERIES. */ /* DATA SMALL(1),SMALL(2) / O000040000000, O000000000000 / */ /* DATA LARGE(1),LARGE(2) / O377777777777, O777777777777 / */ /* DATA RIGHT(1),RIGHT(2) / O170540000000, O000000000000 / */ /* DATA DIVER(1),DIVER(2) / O170640000000, O000000000000 / */ /* DATA LOG10(1),LOG10(2) / O177746420232, O411757177572 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE VAX UNIX F77 COMPILER */ /* DATA SMALL(1),SMALL(2) / 128, 0 / */ /* DATA LARGE(1),LARGE(2) / -32769, -1 / */ /* DATA RIGHT(1),RIGHT(2) / 9344, 0 / */ /* DATA DIVER(1),DIVER(2) / 9472, 0 / */ /* DATA LOG10(1),LOG10(2) / 546979738, -805796613 /, SC/987/ */ /* MACHINE CONSTANTS FOR THE VAX-11 WITH */ /* FORTRAN IV-PLUS COMPILER */ /* DATA SMALL(1),SMALL(2) / Z00000080, Z00000000 / */ /* DATA LARGE(1),LARGE(2) / ZFFFF7FFF, ZFFFFFFFF / */ /* DATA RIGHT(1),RIGHT(2) / Z00002480, Z00000000 / */ /* DATA DIVER(1),DIVER(2) / Z00002500, Z00000000 / */ /* DATA LOG10(1),LOG10(2) / Z209A3F9A, ZCFF884FB /, SC/987/ */ /* MACHINE CONSTANTS FOR VAX/VMS VERSION 2.2 */ /* DATA SMALL(1),SMALL(2) / '80'X, '0'X / */ /* DATA LARGE(1),LARGE(2) / 'FFFF7FFF'X, 'FFFFFFFF'X / */ /* DATA RIGHT(1),RIGHT(2) / '2480'X, '0'X / */ /* DATA DIVER(1),DIVER(2) / '2500'X, '0'X / */ /* DATA LOG10(1),LOG10(2) / '209A3F9A'X, 'CFF884FB'X /, SC/987/ */ /* *** ISSUE STOP 779 IF ALL DATA STATEMENTS ARE COMMENTED... */ if (sc != 987) { /* s_stop("779", 3L); */exit(0); } /* *** ISSUE STOP 778 IF ALL DATA STATEMENTS ARE OBVIOUSLY WRONG... */ if (dmach[3] >= 1.) { /* s_stop("778", 3L); */ exit(0); } if (*i < 1 || *i > 5) { goto L999; } ret_val = dmach[*i - 1]; return ret_val; L999: /* s_wsfe(&io___8); do_fio(&c__1, (char *)&(*i), (ftnlen)sizeof(integer)); e_wsfe(); s_stop("", 0L); */ return ret_val; } /* d1mach_ */ #undef right #undef diver #undef small #undef large #undef dmach #undef log10 /* end d1mach.c */ /**********************************************************************/ /***************** implementation code from daxpy.c *******************/ /**********************************************************************/ /* Subroutine */ int daxpy_(integer *n, doublereal *da, doublereal *dx, integer *incx, doublereal *dy, integer *incy) { /* System generated locals */ integer i__1; /* Local variables */ static integer i, m, ix, iy, mp1; /* constant times a vector plus a vector. */ /* uses unrolled loops for increments equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* Parameter adjustments */ --dy; --dx; /* Function Body */ if (*n <= 0) { return 0; } if (*da == 0.) { return 0; } if (*incx == 1 && *incy == 1) { goto L20; } /* code for unequal increments or equal increments */ /* not equal to 1 */ ix = 1; iy = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*n) + 1) * *incy + 1; } i__1 = *n; for (i = 1; i <= i__1; ++i) { dy[iy] += *da * dx[ix]; ix += *incx; iy += *incy; /* L10: */ } return 0; /* code for both increments equal to 1 */ /* clean-up loop */ L20: m = *n % 4; if (m == 0) { goto L40; } i__1 = m; for (i = 1; i <= i__1; ++i) { dy[i] += *da * dx[i]; /* L30: */ } if (*n < 4) { return 0; } L40: mp1 = m + 1; i__1 = *n; for (i = mp1; i <= i__1; i += 4) { dy[i] += *da * dx[i]; dy[i + 1] += *da * dx[i + 1]; dy[i + 2] += *da * dx[i + 2]; dy[i + 3] += *da * dx[i + 3]; /* L50: */ } return 0; } /* daxpy_ */ /* end daxpy.c */ /**********************************************************************/ /***************** implementation code from dcopy.c *******************/ /**********************************************************************/ /* Subroutine */ int dcopy_(integer *n, doublereal *dx, integer *incx, doublereal *dy, integer *incy) { /* System generated locals */ integer i__1; /* Local variables */ static integer i, m, ix, iy, mp1; /* copies a vector, x, to a vector, y. */ /* uses unrolled loops for increments equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* Parameter adjustments */ --dy; --dx; /* Function Body */ if (*n <= 0) { return 0; } if (*incx == 1 && *incy == 1) { goto L20; } /* code for unequal increments or equal increments */ /* not equal to 1 */ ix = 1; iy = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*n) + 1) * *incy + 1; } i__1 = *n; for (i = 1; i <= i__1; ++i) { dy[iy] = dx[ix]; ix += *incx; iy += *incy; /* L10: */ } return 0; /* code for both increments equal to 1 */ /* clean-up loop */ L20: m = *n % 7; if (m == 0) { goto L40; } i__1 = m; for (i = 1; i <= i__1; ++i) { dy[i] = dx[i]; /* L30: */ } if (*n < 7) { return 0; } L40: mp1 = m + 1; i__1 = *n; for (i = mp1; i <= i__1; i += 7) { dy[i] = dx[i]; dy[i + 1] = dx[i + 1]; dy[i + 2] = dx[i + 2]; dy[i + 3] = dx[i + 3]; dy[i + 4] = dx[i + 4]; dy[i + 5] = dx[i + 5]; dy[i + 6] = dx[i + 6]; /* L50: */ } return 0; } /* dcopy_ */ /* end dcopy.c */ /**********************************************************************/ /***************** implementation code from dcpose.c ******************/ /**********************************************************************/ /* Table of constant values */ /* static integer c__1 = 1; NOW REDUNDANT */ /* Subroutine */ int dcpose_(integer *ndim, integer *n, doublereal *qr, doublereal *alpha, integer *pivot, integer *ierr, doublereal *y, doublereal *sum) { /* System generated locals */ integer qr_dim1, qr_offset, i__1, i__2, i__3; doublereal d__1; /* Builtin functions */ /* double sqrt(double); CANT DECLARE BUILTINS UNDER C++ */ /* Local variables */ static doublereal beta; static integer jbar; extern doublereal ddot_(integer *n, doublereal *dx, integer *incx, doublereal *dy, integer *incy); static doublereal qrkk; static integer i, j, k; static doublereal sigma, alphak; static integer kp1, np1; /* SUBROUTINE DCPOSE IS A MODIFICATION OF THE ALGOL PROCEDURE */ /* DECOMPOSE IN P. BUSINGER AND G. H. GOLUB, LINEAR LEAST */ /* SQUARES SOLUTIONS BY HOUSEHOLDER TRANSFORMATIONS, */ /* NUMER. MATH. 7 (1965) 269-276. */ /* Parameter adjustments */ qr_dim1 = *ndim; qr_offset = qr_dim1 + 1; qr -= qr_offset; --alpha; --pivot; --y; --sum; /* Function Body */ *ierr = 0; np1 = *n + 1; i__1 = np1; for (j = 1; j <= i__1; ++j) { sum[j] = ddot_(n, &qr[j * qr_dim1 + 1], &c__1, &qr[j * qr_dim1 + 1], & c__1); /* L20: */ pivot[j] = j; } i__1 = *n; for (k = 1; k <= i__1; ++k) { sigma = sum[k]; jbar = k; kp1 = k + 1; i__2 = np1; for (j = kp1; j <= i__2; ++j) { if (sigma >= sum[j]) { goto L40; } sigma = sum[j]; jbar = j; L40: ; } if (jbar == k) { goto L70; } i = pivot[k]; pivot[k] = pivot[jbar]; pivot[jbar] = i; sum[jbar] = sum[k]; sum[k] = sigma; i__2 = *n; for (i = 1; i <= i__2; ++i) { sigma = qr[i + k * qr_dim1]; qr[i + k * qr_dim1] = qr[i + jbar * qr_dim1]; qr[i + jbar * qr_dim1] = sigma; /* L50: */ } /* END OF COLUMN INTERCHANGE. */ L70: i__2 = *n - k + 1; sigma = ddot_(&i__2, &qr[k + k * qr_dim1], &c__1, &qr[k + k * qr_dim1] , &c__1); if (sigma != (float)0.) { goto L60; } *ierr = 1; return 0; L60: if (k == *n) { goto L500; } qrkk = qr[k + k * qr_dim1]; alphak = -sqrt(sigma); if (qrkk < (float)0.) { alphak = -alphak; } alpha[k] = alphak; beta = (float)1. / (sigma - qrkk * alphak); qr[k + k * qr_dim1] = qrkk - alphak; i__2 = np1; for (j = kp1; j <= i__2; ++j) { /* L80: */ i__3 = *n - k + 1; y[j] = beta * ddot_(&i__3, &qr[k + k * qr_dim1], &c__1, &qr[k + j * qr_dim1], &c__1); } i__3 = np1; for (j = kp1; j <= i__3; ++j) { i__2 = *n; for (i = k; i <= i__2; ++i) { qr[i + j * qr_dim1] -= qr[i + k * qr_dim1] * y[j]; /* L90: */ } /* Computing 2nd power */ d__1 = qr[k + j * qr_dim1]; sum[j] -= d__1 * d__1; /* L100: */ } L500: ; } alpha[*n] = qr[*n + *n * qr_dim1]; return 0; } /* dcpose_ */ /* end dcpose.c */ /**********************************************************************/ /****************** implementation code from ddot.c *******************/ /**********************************************************************/ doublereal ddot_(integer *n, doublereal *dx, integer *incx, doublereal *dy, integer *incy) { /* System generated locals */ integer i__1; doublereal ret_val; /* Local variables */ static integer i, m; static doublereal dtemp; static integer ix, iy, mp1; /* forms the dot product of two vectors. */ /* uses unrolled loops for increments equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* Parameter adjustments */ --dy; --dx; /* Function Body */ ret_val = 0.; dtemp = 0.; if (*n <= 0) { return ret_val; } if (*incx == 1 && *incy == 1) { goto L20; } /* code for unequal increments or equal increments */ /* not equal to 1 */ ix = 1; iy = 1; if (*incx < 0) { ix = (-(*n) + 1) * *incx + 1; } if (*incy < 0) { iy = (-(*n) + 1) * *incy + 1; } i__1 = *n; for (i = 1; i <= i__1; ++i) { dtemp += dx[ix] * dy[iy]; ix += *incx; iy += *incy; /* L10: */ } ret_val = dtemp; return ret_val; /* code for both increments equal to 1 */ /* clean-up loop */ L20: m = *n % 5; if (m == 0) { goto L40; } i__1 = m; for (i = 1; i <= i__1; ++i) { dtemp += dx[i] * dy[i]; /* L30: */ } if (*n < 5) { goto L60; } L40: mp1 = m + 1; i__1 = *n; for (i = mp1; i <= i__1; i += 5) { dtemp = dtemp + dx[i] * dy[i] + dx[i + 1] * dy[i + 1] + dx[i + 2] * dy[i + 2] + dx[i + 3] * dy[i + 3] + dx[i + 4] * dy[i + 4]; /* L50: */ } L60: ret_val = dtemp; return ret_val; } /* ddot_ */ /* end ddot.c */ /**********************************************************************/ /******************* implementation code from divp.c *********************/ /**********************************************************************/ /* Table of constant values */ static integer c__2 = 2; /* Subroutine */ int divp_(doublereal *xxxx, doublereal *yyyy, doublereal *zzzz, integer *ierr) { static doublereal xnum, denom; extern doublereal d1mach_(integer *i); /* THIS SUBROUTINE PERFORMS DIVISION OF COMPLEX NUMBERS: */ /* ZZZZ = XXXX/YYYY */ /* ON INPUT: */ /* XXXX IS AN ARRAY OF LENGTH TWO REPRESENTING THE FIRST COMPLEX */ /* NUMBER, WHERE XXXX(1) = REAL PART OF XXXX AND XXXX(2) = */ /* IMAGINARY PART OF XXXX. */ /* YYYY IS AN ARRAY OF LENGTH TWO REPRESENTING THE SECOND COMPLEX */ /* NUMBER, WHERE YYYY(1) = REAL PART OF YYYY AND YYYY(2) = */ /* IMAGINARY PART OF YYYY. */ /* ON OUTPUT: */ /* ZZZZ IS AN ARRAY OF LENGTH TWO REPRESENTING THE RESULT OF */ /* THE DIVISION, ZZZZ = XXXX/YYYY, WHERE ZZZZ(1) = */ /* REAL PART OF ZZZZ AND ZZZZ(2) = IMAGINARY PART OF ZZZZ. */ /* IERR = */ /* 1 IF DIVISION WOULD HAVE CAUSED OVERFLOW. IN THIS CASE, THE */ /* APPROPRIATE PARTS OF ZZZZ ARE SET EQUAL TO THE LARGEST */ /* FLOATING POINT NUMBER, AS GIVEN BY FUNCTION D1MACH . */ /* 0 IF DIVISION DOES NOT CAUSE OVERFLOW. */ /* DECLARATION OF INPUT */ /* DECLARATION OF OUTPUT */ /* DECLARATION OF VARIABLES */ /* Parameter adjustments */ --zzzz; --yyyy; --xxxx; /* Function Body */ *ierr = 0; denom = yyyy[1] * yyyy[1] + yyyy[2] * yyyy[2]; xnum = xxxx[1] * yyyy[1] + xxxx[2] * yyyy[2]; if (dblabs(denom) >= (float)1. || (dblabs(denom) < (float)1. && dblabs(xnum) / d1mach_(&c__2) < dblabs(denom)) ) { zzzz[1] = xnum / denom; } else { zzzz[1] = d1mach_(&c__2); *ierr = 1; } xnum = xxxx[2] * yyyy[1] - xxxx[1] * yyyy[2]; if (dblabs(denom) >= (float)1. || (dblabs(denom) < (float)1. && dblabs(xnum) / d1mach_(&c__2) < dblabs(denom))) { zzzz[2] = xnum / denom; } else { zzzz[2] = d1mach_(&c__2); *ierr = 1; } return 0; } /* divp_ */ /* end divp.c */ /**********************************************************************/ /****************** implementation code from dnrm2.c ******************/ /**********************************************************************/ doublereal dnrm2_(integer *n, doublereal *dx, integer *incx) { /* Initialized data */ static doublereal zero = 0.; static doublereal one = 1.; static doublereal cutlo = 8.232e-11; static doublereal cuthi = 1.304e19; /* Format strings */ static char fmt_30[] = ""; static char fmt_50[] = ""; static char fmt_70[] = ""; static char fmt_110[] = ""; /* System generated locals */ integer i__1; doublereal ret_val, d__1; /* Builtin functions */ /* double sqrt(double); CANT DECLARE BUILTINS UNDER C++ */ /* Local variables */ static doublereal xmax; static integer next, i, j, ix; static doublereal hitest, sum; /* Assigned format variables */ char *next_fmt; /* Parameter adjustments */ --dx; /* Function Body */ /* euclidean norm of the n-vector stored in dx() with storage */ /* increment incx . */ /* if n .le. 0 return with result = 0. */ /* if n .ge. 1 then incx must be .ge. 1 */ /* c.l.lawson, 1978 jan 08 */ /* modified to correct failure to update ix, 1/25/92. */ /* modified 3/93 to return if incx .le. 0. */ /* four phase method using two built-in constants that are */ /* hopefully applicable to all machines. */ /* cutlo = maximum of dsqrt(u/eps) over all known machines. */ /* cuthi = minimum of dsqrt(v) over all known machines. */ /* where */ /* eps = smallest no. such that eps + 1. .gt. 1. */ /* u = smallest positive no. (underflow limit) */ /* v = largest no. (overflow limit) */ /* brief outline of algorithm.. */ /* phase 1 scans zero components. */ /* move to phase 2 when a component is nonzero and .le. cutlo */ /* move to phase 3 when a component is .gt. cutlo */ /* move to phase 4 when a component is .ge. cuthi/m */ /* where m = n for x() real and m = 2*n for complex. */ /* values for cutlo and cuthi.. */ /* from the environmental parameters listed in the imsl converter */ /* document the limiting values are as follows.. */ /* cutlo, s.p. u/eps = 2**(-102) for honeywell. close seconds are */ /* univac and dec at 2**(-103) */ /* thus cutlo = 2**(-51) = 4.44089e-16 */ /* cuthi, s.p. v = 2**127 for univac, honeywell, and dec. */ /* thus cuthi = 2**(63.5) = 1.30438e19 */ /* cutlo, d.p. u/eps = 2**(-67) for honeywell and dec. */ /* thus cutlo = 2**(-33.5) = 8.23181d-11 */ /* cuthi, d.p. same as s.p. cuthi = 1.30438d19 */ /* data cutlo, cuthi / 8.232d-11, 1.304d19 / */ /* data cutlo, cuthi / 4.441e-16, 1.304e19 / */ if (*n > 0 && *incx > 0) { goto L10; } ret_val = zero; goto L300; L10: next = 0; next_fmt = fmt_30; sum = zero; i = 1; ix = 1; /* begin main loop */ L20: switch ((int)next) { case 0: goto L30; case 1: goto L50; case 2: goto L70; case 3: goto L110; } L30: if ((d__1 = dx[i], dblabs(d__1)) > cutlo) { goto L85; } next = 1; next_fmt = fmt_50; xmax = zero; /* phase 1. sum is zero */ L50: if (dx[i] == zero) { goto L200; } if ((d__1 = dx[i], dblabs(d__1)) > cutlo) { goto L85; } /* prepare for phase 2. */ next = 2; next_fmt = fmt_70; goto L105; /* prepare for phase 4. */ L100: ix = j; next = 3; next_fmt = fmt_110; sum = sum / dx[i] / dx[i]; L105: xmax = (d__1 = dx[i], dblabs(d__1)); goto L115; /* phase 2. sum is small. */ /* scale to avoid destructive underflow. */ L70: if ((d__1 = dx[i], dblabs(d__1)) > cutlo) { goto L75; } /* common code for phases 2 and 4. */ /* in phase 4 sum is large. scale to avoid overflow. */ L110: if ((d__1 = dx[i], dblabs(d__1)) <= xmax) { goto L115; } /* Computing 2nd power */ d__1 = xmax / dx[i]; sum = one + sum * (d__1 * d__1); xmax = (d__1 = dx[i], dblabs(d__1)); goto L200; L115: /* Computing 2nd power */ d__1 = dx[i] / xmax; sum += d__1 * d__1; goto L200; /* prepare for phase 3. */ L75: sum = sum * xmax * xmax; /* for real or d.p. set hitest = cuthi/n */ /* for complex set hitest = cuthi/(2*n) */ L85: hitest = cuthi / (real) (*n); /* phase 3. sum is mid-range. no scaling. */ i__1 = *n; for (j = ix; j <= i__1; ++j) { if ((d__1 = dx[i], dblabs(d__1)) >= hitest) { goto L100; } /* Computing 2nd power */ d__1 = dx[i]; sum += d__1 * d__1; i += *incx; /* L95: */ } ret_val = sqrt(sum); goto L300; L200: ++ix; i += *incx; if (ix <= *n) { goto L20; } /* end of main loop. */ /* compute square root and adjust for scaling. */ ret_val = xmax * sqrt(sum); L300: return ret_val; } /* dnrm2_ */ /* end dnrm2.c */ /**********************************************************************/ /***************** implementation code from dscal.c *******************/ /**********************************************************************/ /* Subroutine */ int dscal_(integer *n, doublereal *da, doublereal *dx, integer *incx) { /* System generated locals */ integer i__1, i__2; /* Local variables */ static integer i, m, nincx, mp1; /* scales a vector by a constant. */ /* uses unrolled loops for increment equal to one. */ /* jack dongarra, linpack, 3/11/78. */ /* modified 3/93 to return if incx .le. 0. */ /* Parameter adjustments */ --dx; /* Function Body */ if (*n <= 0 || *incx <= 0) { return 0; } if (*incx == 1) { goto L20; } /* code for increment not equal to 1 */ nincx = *n * *incx; i__1 = nincx; i__2 = *incx; for (i = 1; i__2 < 0 ? i >= i__1 : i <= i__1; i += i__2) { dx[i] = *da * dx[i]; /* L10: */ } return 0; /* code for increment equal to 1 */ /* clean-up loop */ L20: m = *n % 5; if (m == 0) { goto L40; } i__2 = m; for (i = 1; i <= i__2; ++i) { dx[i] = *da * dx[i]; /* L30: */ } if (*n < 5) { return 0; } L40: mp1 = m + 1; i__2 = *n; for (i = mp1; i <= i__2; i += 5) { dx[i] = *da * dx[i]; dx[i + 1] = *da * dx[i + 1]; dx[i + 2] = *da * dx[i + 2]; dx[i + 3] = *da * dx[i + 3]; dx[i + 4] = *da * dx[i + 4]; /* L50: */ } return 0; } /* dscal_ */ /* end dscal.c */ /**********************************************************************/ /******************* implementation code from f.c *********************/ /**********************************************************************/ /* Subroutine */ int f_(doublereal *x, doublereal *v) { /* EVALUATE F(X) AND RETURN IN THE VECTOR V . */ /* Parameter adjustments */ --v; --x; /* Function Body */ return 0; } /* f_ */ /* end f.c */ /**********************************************************************/ /***************** implementation code from fjac.c ********************/ /**********************************************************************/ /* Subroutine */ int fjac_(doublereal *x, doublereal *v, integer *k) { /* RETURN IN V THE KTH COLUMN OF THE JACOBIAN MATRIX OF */ /* F(X) EVALUATED AT X . */ /* Parameter adjustments */ --v; --x; /* Function Body */ return 0; } /* fjac_ */ /* end fjac.c */ /**********************************************************************/ /***************** implementation code from idamax.c ******************/ /**********************************************************************/ integer idamax_(integer *n, doublereal *dx, integer *incx) { /* System generated locals */ integer ret_val, i__1; doublereal d__1; /* Local variables */ static doublereal dmax_; static integer i, ix; /* finds the index of element having max. absolute value. */ /* jack dongarra, linpack, 3/11/78. */ /* modified 3/93 to return if incx .le. 0. */ /* Parameter adjustments */ --dx; /* Function Body */ ret_val = 0; if (*n < 1 || *incx <= 0) { return ret_val; } ret_val = 1; if (*n == 1) { return ret_val; } if (*incx == 1) { goto L20; } /* code for increment not equal to 1 */ ix = 1; dmax_ = dblabs(dx[1]); ix += *incx; i__1 = *n; for (i = 2; i <= i__1; ++i) { if ((d__1 = dx[ix], dblabs(d__1)) <= dmax_) { goto L5; } ret_val = i; dmax_ = (d__1 = dx[ix], dblabs(d__1)); L5: ix += *incx; /* L10: */ } return ret_val; /* code for increment equal to 1 */ L20: dmax_ = dblabs(dx[1]); i__1 = *n; for (i = 2; i <= i__1; ++i) { if ((d__1 = dx[i], dblabs(d__1)) <= dmax_) { goto L30; } ret_val = i; dmax_ = (d__1 = dx[i], dblabs(d__1)); L30: ; } return ret_val; } /* idamax_ */ /* end idamax.c */ /**********************************************************************/ /****************** implementation code from root.c *******************/ /**********************************************************************/ double d_sign(double *arg1, double *arg2){ if (*arg2>=0.0) return dblabs(*arg1); else return -1.0*dblabs(*arg1); } /* Table of constant values */ /* static integer c__4 = 4; NOW REDUNDANT */ static doublereal c_b17 = 1.; /* Subroutine */ int root_(doublereal *t, doublereal *ft, doublereal *b, doublereal *c, doublereal *relerr, doublereal *abserr, integer *iflag) { /* System generated locals */ doublereal d__1, d__2; /* Builtin functions */ double d_sign(double *arg1, double *arg2); /* Local variables */ static doublereal acmb, acbs, a, p, q, u; extern doublereal d1mach_(integer *i); static integer kount; static doublereal ae, fa, fb, fc; static integer ic; static doublereal re, fx, cmb, tol; /* ROOT COMPUTES A ROOT OF THE NONLINEAR EQUATION F(X)=0 */ /* WHERE F(X) IS A CONTINOUS REAL FUNCTION OF A SINGLE REAL */ /* VARIABLE X. THE METHOD USED IS A COMBINATION OF BISECTION */ /* AND THE SECANT RULE. */ /* NORMAL INPUT CONSISTS OF A CONTINUOS FUNCTION F AND AN */ /* INTERVAL (B,C) SUCH THAT F(B)*F(C).LE.0.0. EACH ITERATION */ /* FINDS NEW VALUES OF B AND C SUCH THAT THE INTERVAL(B,C) IS */ /* SHRUNK AND F(B)*F(C).LE.0.0. THE STOPPING CRITERION IS */ /* DABS(B-C).LE.2.0*(RELERR*DABS(B)+ABSERR) */ /* WHERE RELERR=RELATIVE ERROR AND ABSERR=ABSOLUTE ERROR ARE */ /* INPUT QUANTITIES. SET THE FLAG, IFLAG, POSITIVE TO INITIALIZE */ /* THE COMPUTATION. AS B,C AND IFLAG ARE USED FOR BOTH INPUT AND */ /* OUTPUT, THEY MUST BE VARIABLES IN THE CALLING PROGRAM. */ /* IF 0 IS A POSSIBLE ROOT, ONE SHOULD NOT CHOOSE ABSERR=0.0. */ /* THE OUTPUT VALUE OF B IS THE BETTER APPROXIMATION TO A ROOT */ /* AS B AND C ARE ALWAYS REDEFINED SO THAT DABS(F(B)).LE.DABS(F(C)). */ /* TO SOLVE THE EQUATION, ROOT MUST EVALUATE F(X) REPEATEDLY. THIS */ /* IS DONE IN THE CALLING PROGRAM. WHEN AN EVALUATION OF F IS */ /* NEEDED AT T, ROOT RETURNS WITH IFLAG NEGATIVE. EVALUATE FT=F(T) */ /* AND CALL ROOT AGAIN. DO NOT ALTER IFLAG. */ /* WHEN THE COMPUTATION IS COMPLETE, ROOT RETURNS TO THE CALLING */ /* PROGRAM WITH IFLAG POSITIVE= */ /* IFLAG=1 IF F(B)*F(C).LT.0 AND THE STOPPING CRITERION IS MET. */ /* =2 IF A VALUE B IS FOUND SUCH THAT THE COMPUTED VALUE */ /* F(B) IS EXACTLY ZERO. THE INTERVAL (B,C) MAY NOT */ /* SATISFY THE STOPPING CRITERION. */ /* =3 IF DABS(F(B)) EXCEEDS THE INPUT VALUES DABS(F(B)), */ /* DABS(F(C)). IN THIS CASE IT IS LIKELY THAT B IS CLOSE */ /* TO A POLE OF F. */ /* =4 IF NO ODD ORDER ROOT WAS FOUND IN THE INTERVAL. A */ /* LOCAL MINIMUM MAY HAVE BEEN OBTAINED. */ /* =5 IF TOO MANY FUNCTION EVALUATIONS WERE MADE. */ /* (AS PROGRAMMED, 500 ARE ALLOWED.) */ /* THIS CODE IS A MODIFICATION OF THE CODE ZEROIN WHICH IS COMPLETELY */ /* EXPLAINED AND DOCUMENTED IN THE TEXT NUMERICAL COMPUTING: AN */ /* INTRODUCTION, BY L. F. SHAMPINE AND R. C. ALLEN. */ /* CALLS D1MACH . */ if (*iflag >= 0) { goto L100; } *iflag = dblabs(*iflag); switch ((int)*iflag) { case 1: goto L200; case 2: goto L300; case 3: goto L400; } L100: u = d1mach_(&c__4); re = max(*relerr,u); ae = max(*abserr,0.); ic = 0; acbs = (d__1 = *b - *c, dblabs(d__1)); a = *c; *t = a; *iflag = -1; return 0; L200: fa = *ft; *t = *b; *iflag = -2; return 0; L300: fb = *ft; fc = fa; kount = 2; /* Computing MAX */ d__1 = dblabs(fb), d__2 = dblabs(fc); fx = max(d__1,d__2); L1: if (dblabs(fc) >= dblabs(fb)) { goto L2; } /* INTERCHANGE B AND C SO THAT ABS(F(B)).LE.ABS(F(C)). */ a = *b; fa = fb; *b = *c; fb = fc; *c = a; fc = fa; L2: cmb = (*c - *b) * (float).5; acmb = dblabs(cmb); tol = re * dblabs(*b) + ae; /* TEST STOPPING CRITERION AND FUNCTION COUNT. */ if (acmb <= tol) { goto L8; } if (kount >= 500) { goto L12; } /* CALCULATE NEW ITERATE EXPLICITLY AS B+P/Q */ /* WHERE WE ARRANGE P.GE.0. THE IMPLICIT */ /* FORM IS USED TO PREVENT OVERFLOW. */ p = (*b - a) * fb; q = fa - fb; if (p >= (float)0.) { goto L3; } p = -p; q = -q; /* UPDATE A, CHECK IF REDUCTION IN THE SIZE OF BRACKETING */ /* INTERVAL IS SATISFACTORY. IF NOT BISECT UNTIL IT IS. */ L3: a = *b; fa = fb; ++ic; if (ic < 4) { goto L4; } if (acmb * (float)8. >= acbs) { goto L6; } ic = 0; acbs = acmb; /* TEST FOR TOO SMALL A CHANGE. */ L4: if (p > dblabs(q) * tol) { goto L5; } /* INCREMENT BY TOLERANCE */ /* sign gives sign(arg2)*|arg1| */ *b += d_sign(&tol, &cmb); goto L7; /* ROOT OUGHT TO BE BETWEEN B AND (C+B)/2 */ L5: if (p >= cmb * q) { goto L6; } /* USE SECANT RULE. */ *b += p / q; goto L7; /* USE BISECTION. */ L6: *b = (*c + *b) * (float).5; /* HAVE COMPLETED COMPUTATION FOR NEW ITERATE B. */ L7: *t = *b; *iflag = -3; return 0; L400: fb = *ft; if (fb == (float)0.) { goto L9; } ++kount; if (d_sign(&c_b17, &fb) != d_sign(&c_b17, &fc)) { goto L1; } *c = a; fc = fa; goto L1; /* FINISHED. SET IFLAG. */ L8: if (d_sign(&c_b17, &fb) == d_sign(&c_b17, &fc)) { goto L11; } if (dblabs(fb) > fx) { goto L10; } *iflag = 1; return 0; L9: *iflag = 2; return 0; L10: *iflag = 3; return 0; L11: *iflag = 4; return 0; L12: *iflag = 5; return 0; } /* root_ */ /* end root.c */ /**********************************************************************/ /***************** implementation code from rootnf.c ******************/ /**********************************************************************/ /* Table of constant values */ /* static int c__4 = 4; static int c__1 = 1; */ /* Subroutine */ int rootnf_(int *n, int *nfe, int *iflag, double *relerr, double *abserr, double *y, double *yp, double *yold, double *ypold, double *a, double *qr, double *alpha, double *tz, int *pivot, double *w, double *wp, double *par, int *ipar) { /* System generated locals */ int qr_dim1, qr_offset, i__1; double d__1; /* Local variables */ static double dels, aerr, rerr; static int judy; extern /* Subroutine */ int root_(doublereal *t, doublereal *ft, doublereal *b, doublereal *c, doublereal *relerr, doublereal *abserr, integer *iflag); static double sout; extern double dnrm2_(integer *n, doublereal *dx, integer *incx); static double u; static int lcode; extern double d1mach_(integer *); static double qsout, sa, sb; static int jw; /* extern */ /* Subroutine */ /* int tangnf_(); IN pelutils.h */ static int np1; /* ROOTNF FINDS THE POINT YBAR = (1, XBAR) ON THE ZERO CURVE OF THE */ /* HOMOTOPY MAP. IT STARTS WITH TWO POINTS YOLD=(LAMBDAOLD,XOLD) AND */ /* Y=(LAMBDA,X) SUCH THAT LAMBDAOLD < 1 <= LAMBDA , AND ALTERNATES */ /* BETWEEN HERMITE CUBIC INTERPOLATION AND NEWTON ITERATION UNTIL */ /* CONVERGENCE. */ /* ON INPUT: */ /* N = DIMENSION OF X AND THE HOMOTOPY MAP. */ /* NFE = NUMBER OF JACOBIAN MATRIX EVALUATIONS. */ /* IFLAG = -2, -1, OR 0, INDICATING THE PROBLEM TYPE. */ /* RELERR, ABSERR = RELATIVE AND ABSOLUTE ERROR VALUES. THE ITERATION IS */ /* CONSIDERED TO HAVE CONVERGED WHEN A POINT Y=(LAMBDA,X) IS FOUND */ /* SUCH THAT */ /* |Y(1) - 1| <= RELERR + ABSERR AND */ /* ||Z|| <= RELERR*||X|| + ABSERR , WHERE */ /* (?,Z) IS THE NEWTON STEP TO Y=(LAMBDA,X). */ /* Y(1:N+1) = POINT (LAMBDA(S), X(S)) ON ZERO CURVE OF HOMOTOPY MAP. */ /* YP(1:N+1) = UNIT TANGENT VECTOR TO THE ZERO CURVE OF THE HOMOTOPY MAP */ /* AT Y . */ /* YOLD(1:N+1) = A POINT DIFFERENT FROM Y ON THE ZERO CURVE. */ /* YPOLD(1:N+1) = UNIT TANGENT VECTOR TO THE ZERO CURVE OF THE HOMOTOPY */ /* MAP AT YOLD . */ /* A(1:*) = PARAMETER VECTOR IN THE HOMOTOPY MAP. */ /* QR(1:N,1:N+2), ALPHA(1:N), TZ(1:N+1), PIVOT(1:N+1), W(1:N+1), */ /* WP(1:N+1) ARE WORK ARRAYS USED FOR THE QR FACTORIZATION (IN THE */ /* NEWTON STEP CALCULATION) AND THE INTERPOLATION. */ /* PAR(1:*) AND IPAR(1:*) ARE ARRAYS FOR (OPTIONAL) USER PARAMETERS, */ /* WHICH ARE SIMPLY PASSED THROUGH TO THE USER WRITTEN SUBROUTINES */ /* RHO, RHOJAC. */ /* ON OUTPUT: */ /* N , RELERR , ABSERR , A ARE UNCHANGED. */ /* NFE HAS BEEN UPDATED. */ /* IFLAG */ /* = -2, -1, OR 0 (UNCHANGED) ON A NORMAL RETURN. */ /* = 4 IF A JACOBIAN MATRIX WITH RANK < N HAS OCCURRED. THE */ /* ITERATION WAS NOT COMPLETED. */ /* = 6 IF THE ITERATION FAILED TO CONVERGE. Y AND YOLD CONTAIN */ /* THE LAST TWO POINTS FOUND ON THE ZERO CURVE. */ /* Y IS THE POINT ON THE ZERO CURVE OF THE HOMOTOPY MAP AT LAMBDA = 1 . */ /* CALLS D1MACH , DNRM2 , ROOT , TANGNF . */ /* ***** ARRAY DECLARATIONS. ***** */ /* ***** END OF DIMENSIONAL INFORMATION. ***** */ /* THE LIMIT ON THE NUMBER OF ITERATIONS ALLOWED MAY BE CHANGED BY */ /* CHANGING THE FOLLOWING PARAMETER STATEMENT: */ /* DEFINITION OF HERMITE CUBIC INTERPOLANT VIA DIVIDED DIFFERENCES. */ /* Parameter adjustments */ --wp; --w; --pivot; --tz; --alpha; qr_dim1 = *n; qr_offset = qr_dim1 + 1; qr -= qr_offset; --a; --ypold; --yold; --yp; --y; --par; --ipar; /* Function Body */ u = d1mach_(&c__4); rerr = max(*relerr,u); aerr = max(*abserr,0.); np1 = *n + 1; /* ***** MAIN LOOP. ***** */ /* L100: */ for (judy = 1; judy <= 20; ++judy) { i__1 = np1; for (jw = 1; jw <= i__1; ++jw) { tz[jw] = y[jw] - yold[jw]; /* L110: */ } dels = dnrm2_((integer *)&np1, &tz[1], &c__1); /* USING TWO POINTS AND TANGENTS ON THE HOMOTOPY ZERO CURVE, CONSTRUCT */ /* THE HERMITE CUBIC INTERPOLANT Q(S). THEN USE ROOT TO FIND THE S */ /* CORRESPONDING TO LAMBDA = 1 . THE TWO POINTS ON THE ZERO CURVE AR E */ /* ALWAYS CHOSEN TO BRACKET LAMBDA=1, WITH THE BRACKETING INTERVAL */ /* ALWAYS BEING [0, DELS]. */ sa = (float)0.; sb = dels; lcode = 1; L130: root_(&sout, &qsout, &sa, &sb, &rerr, &aerr, (integer *)&lcode); if (lcode > 0) { goto L140; } qsout = ((((yp[1] - (y[1] - yold[1]) / dels) / dels - ((y[1] - yold[1] ) / dels - ypold[1]) / dels) / dels * (sout - dels) + ((y[1] - yold[1]) / dels - ypold[1]) / dels) * sout + ypold[1]) * sout + yold[1] - (float)1.; goto L130; /* IF LAMBDA = 1 WERE BRACKETED, ROOT CANNOT FAIL. */ L140: if (lcode > 2) { *iflag = 6; return 0; } /* CALCULATE Q(SA) AS THE INITIAL POINT FOR A NEWTON ITERATION. */ i__1 = np1; for (jw = 1; jw <= i__1; ++jw) { w[jw] = ((((yp[jw] - (y[jw] - yold[jw]) / dels) / dels - ((y[jw] - yold[jw]) / dels - ypold[jw]) / dels) / dels * (sa - dels) + ((y[jw] - yold[jw]) / dels - ypold[jw]) / dels) * sa + ypold[jw]) * sa + yold[jw]; /* L150: */ } /* CALCULATE NEWTON STEP AT Q(SA). */ tangnf_(&sa, &w[1], &wp[1], &ypold[1], &a[1], &qr[qr_offset], &alpha[ 1], &tz[1], &pivot[1], nfe, n, iflag, &par[1], &ipar[1]); if (*iflag > 0) { return 0; } /* NEXT POINT = CURRENT POINT + NEWTON STEP. */ i__1 = np1; for (jw = 1; jw <= i__1; ++jw) { w[jw] += tz[jw]; /* L160: */ } /* GET THE TANGENT WP AT W AND THE NEXT NEWTON STEP IN TZ . */ tangnf_(&sa, &w[1], &wp[1], &ypold[1], &a[1], &qr[qr_offset], &alpha[ 1], &tz[1], &pivot[1], nfe, n, iflag, &par[1], &ipar[1]); if (*iflag > 0) { return 0; } /* TAKE NEWTON STEP AND CHECK CONVERGENCE. */ i__1 = np1; for (jw = 1; jw <= i__1; ++jw) { w[jw] += tz[jw]; /* L170: */ } if ((d__1 = w[1] - (float)1., dblabs(d__1)) <= rerr + aerr && dnrm2_((integer *)n, & tz[2], &c__1) <= rerr * dnrm2_((integer*)n, &w[2], &c__1) + aerr) { i__1 = np1; for (jw = 1; jw <= i__1; ++jw) { y[jw] = w[jw]; /* L180: */ } return 0; } /* IF THE ITERATION HAS NOT CONVERGED, DISCARD ONE OF THE OLD POINTS */ /* SUCH THAT LAMBDA = 1 IS STILL BRACKETED. */ if ((yold[1] - (float)1.) * (w[1] - (float)1.) > (float)0.) { i__1 = np1; for (jw = 1; jw <= i__1; ++jw) { yold[jw] = w[jw]; ypold[jw] = wp[jw]; /* L200: */ } } else { i__1 = np1; for (jw = 1; jw <= i__1; ++jw) { y[jw] = w[jw]; yp[jw] = wp[jw]; /* L210: */ } } /* L300: */ } /* ***** END OF MAIN LOOP. ***** */ /* THE ALTERNATING OSCULATORY CUBIC INTERPOLATION AND NEWTON ITERATION */ /* HAS NOT CONVERGED IN LIMIT STEPS. ERROR RETURN. */ *iflag = 6; return 0; } /* rootnf_ */ /* end rootnf.c */ /**********************************************************************/ /******************* implementation code from stepnf.c *********************/ /**********************************************************************/ /* Table of constant values */ /* static integer c__4 = 4; static integer c__1 = 1; */ /* Subroutine */ int stepnf_(integer *n, integer *nfe, integer *iflag, logical *start, logical *crash, doublereal *hold, doublereal *h, doublereal *relerr, doublereal *abserr, doublereal *s, doublereal *y, doublereal *yp, doublereal *yold, doublereal *ypold, doublereal *a, doublereal *qr, doublereal *alpha, doublereal *tz, integer *pivot, doublereal *w, doublereal *wp, doublereal *z0, doublereal *z1, doublereal *sspar, doublereal *par, integer *ipar) { /* System generated locals */ integer qr_dim1, qr_offset, i__1; doublereal d__1, d__2, d__3, d__4; /* Builtin functions */ /* double sqrt(double), pow(double,double); CANT DECLARE BUILTINS UNDER C++ */ /* Local variables */ static logical fail; static doublereal temp; static integer judy; static doublereal twou; extern doublereal dnrm2_(integer *n, doublereal *dx, integer *incx); static doublereal dcalc; static integer j; static doublereal lcalc, hfail, rcalc; static integer itnum; extern doublereal d1mach_(integer *i); static doublereal fouru, ht; /*extern */ /* Subroutine */ /* int tangnf_(); IN pelutils.h */ static doublereal rholen; static integer np1; /* STEPNF TAKES ONE STEP ALONG THE ZERO CURVE OF THE HOMOTOPY MAP */ /* USING A PREDICTOR-CORRECTOR ALGORITHM. THE PREDICTOR USES A HERMITE */ /* CUBIC INTERPOLANT, AND THE CORRECTOR RETURNS TO THE ZERO CURVE ALONG */ /* THE FLOW NORMAL TO THE DAVIDENKO FLOW. STEPNF ALSO ESTIMATES A */ /* STEP SIZE H FOR THE NEXT STEP ALONG THE ZERO CURVE. NORMALLY */ /* STEPNF IS USED INDIRECTLY THROUGH FIXPNF , AND SHOULD BE CALLED */ /* DIRECTLY ONLY IF IT IS NECESSARY TO MODIFY THE STEPPING ALGORITHM'S */ /* PARAMETERS. */ /* ON INPUT: */ /* N = DIMENSION OF X AND THE HOMOTOPY MAP. */ /* NFE = NUMBER OF JACOBIAN MATRIX EVALUATIONS. */ /* IFLAG = -2, -1, OR 0, INDICATING THE PROBLEM TYPE. */ /* START = .TRUE. ON FIRST CALL TO STEPNF , .FALSE. OTHERWISE. */ /* HOLD = ||Y - YOLD||; SHOULD NOT BE MODIFIED BY THE USER. */ /* H = UPPER LIMIT ON LENGTH OF STEP THAT WILL BE ATTEMPTED. H MUST BE */ /* SET TO A POSITIVE NUMBER ON THE FIRST CALL TO STEPNF . */ /* THEREAFTER STEPNF CALCULATES AN OPTIMAL VALUE FOR H , AND H */ /* SHOULD NOT BE MODIFIED BY THE USER. */ /* RELERR, ABSERR = RELATIVE AND ABSOLUTE ERROR VALUES. THE ITERATION IS */ /* CONSIDERED TO HAVE CONVERGED WHEN A POINT W=(LAMBDA,X) IS FOUND */ /* SUCH THAT */ /* ||Z|| <= RELERR*||W|| + ABSERR , WHERE */ /* Z IS THE NEWTON STEP TO W=(LAMBDA,X). */ /* S = (APPROXIMATE) ARC LENGTH ALONG THE HOMOTOPY ZERO CURVE UP TO */ /* Y(S) = (LAMBDA(S), X(S)). */ /* Y(1:N+1) = PREVIOUS POINT (LAMBDA(S), X(S)) FOUND ON THE ZERO CURVE OF */ /* THE HOMOTOPY MAP. */ /* YP(1:N+1) = UNIT TANGENT VECTOR TO THE ZERO CURVE OF THE HOMOTOPY MAP */ /* AT Y . */ /* YOLD(1:N+1) = A POINT BEFORE Y ON THE ZERO CURVE OF THE HOMOTOPY MAP. */ /* YPOLD(1:N+1) = UNIT TANGENT VECTOR TO THE ZERO CURVE OF THE HOMOTOPY */ /* MAP AT YOLD . */ /* A(1:*) = PARAMETER VECTOR IN THE HOMOTOPY MAP. */ /* QR(1:N,1:N+2), ALPHA(1:N), TZ(1:N+1), PIVOT(1:N+1), W(1:N+1), */ /* WP(1:N+1) ARE WORK ARRAYS USED FOR THE QR FACTORIZATION (IN THE */ /* NEWTON STEP CALCULATION) AND THE INTERPOLATION. */ /* Z0(1:N+1), Z1(1:N+1) ARE WORK ARRAYS USED FOR THE ESTIMATION OF THE */ /* NEXT STEP SIZE H . */ /* SSPAR(1:8) = (LIDEAL, RIDEAL, DIDEAL, HMIN, HMAX, BMIN, BMAX, P) IS */ /* A VECTOR OF PARAMETERS USED FOR THE OPTIMAL STEP SIZE ESTIMATION. */ /* PAR(1:*) AND IPAR(1:*) ARE ARRAYS FOR (OPTIONAL) USER PARAMETERS, */ /* WHICH ARE SIMPLY PASSED THROUGH TO THE USER WRITTEN SUBROUTINES */ /* RHO, RHOJAC. */ /* ON OUTPUT: */ /* N , A , SSPAR ARE UNCHANGED. */ /* NFE HAS BEEN UPDATED. */ /* IFLAG */ /* = -2, -1, OR 0 (UNCHANGED) ON A NORMAL RETURN. */ /* = 4 IF A JACOBIAN MATRIX WITH RANK < N HAS OCCURRED. THE */ /* ITERATION WAS NOT COMPLETED. */ /* = 6 IF THE ITERATION FAILED TO CONVERGE. W CONTAINS THE LAST */ /* NEWTON ITERATE. */ /* START = .FALSE. ON A NORMAL RETURN. */ /* CRASH */ /* = .FALSE. ON A NORMAL RETURN. */ /* = .TRUE. IF THE STEP SIZE H WAS TOO SMALL. H HAS BEEN */ /* INCREASED TO AN ACCEPTABLE VALUE, WITH WHICH STEPNF MAY BE */ /* CALLED AGAIN. */ /* = .TRUE. IF RELERR AND/OR ABSERR WERE TOO SMALL. THEY HAVE */ /* BEEN INCREASED TO ACCEPTABLE VALUES, WITH WHICH STEPNF MAY */ /* BE CALLED AGAIN. */ /* HOLD = ||Y - YOLD||. */ /* H = OPTIMAL VALUE FOR NEXT STEP TO BE ATTEMPTED. NORMALLY H SHOULD */ /* NOT BE MODIFIED BY THE USER. */ /* RELERR, ABSERR ARE UNCHANGED ON A NORMAL RETURN. */ /* S = (APPROXIMATE) ARC LENGTH ALONG THE ZERO CURVE OF THE HOMOTOPY MAP */ /* UP TO THE LATEST POINT FOUND, WHICH IS RETURNED IN Y . */ /* Y, YP, YOLD, YPOLD CONTAIN THE TWO MOST RECENT POINTS AND TANGENT */ /* VECTORS FOUND ON THE ZERO CURVE OF THE HOMOTOPY MAP. */ /* CALLS D1MACH , DNRM2 , TANGNF . */ /* ***** ARRAY DECLARATIONS. ***** */ /* ***** END OF DIMENSIONAL INFORMATION. ***** */ /* THE LIMIT ON THE NUMBER OF NEWTON ITERATIONS ALLOWED BEFORE REDUCING */ /* THE STEP SIZE H MAY BE CHANGED BY CHANGING THE FOLLOWING PARAMETER */ /* STATEMENT: */ /* DEFINITION OF HERMITE CUBIC INTERPOLANT VIA DIVIDED DIFFERENCES. */ /* Parameter adjustments */ --z1; --z0; --wp; --w; --pivot; --tz; --alpha; qr_dim1 = *n; qr_offset = qr_dim1 + 1; qr -= qr_offset; --a; --ypold; --yold; --yp; --y; --sspar; --par; --ipar; /* Function Body */ twou = d1mach_(&c__4) * (float)2.; fouru = twou + twou; np1 = *n + 1; *crash = TRUE_; /* THE ARCLENGTH S MUST BE NONNEGATIVE. */ if (*s < (float)0.) { return 0; } /* IF STEP SIZE IS TOO SMALL, DETERMINE AN ACCEPTABLE ONE. */ if (*h < fouru * (*s + (float)1.)) { *h = fouru * (*s + (float)1.); return 0; } /* IF ERROR TOLERANCES ARE TOO SMALL, INCREASE THEM TO ACCEPTABLE VALUES. */ temp = dnrm2_(&np1, &y[1], &c__1); if ((*relerr * temp + *abserr) * (float).5 >= twou * temp) { goto L40; } if (*relerr != (float)0.) { *relerr = fouru * (fouru + (float)1.); *abserr = max(*abserr,0.); } else { *abserr = fouru * temp; } return 0; L40: *crash = FALSE_; if (! (*start)) { goto L300; } /* ***** STARTUP SECTION(FIRST STEP ALONG ZERO CURVE. ***** */ fail = FALSE_; *start = FALSE_; /* DETERMINE SUITABLE INITIAL STEP SIZE. */ /* Computing MIN */ d__1 = min(*h,.1), d__2 = sqrt(sqrt(*relerr * temp + *abserr)); *h = min(d__1,d__2); /* USE LINEAR PREDICTOR ALONG TANGENT DIRECTION TO START NEWTON ITERATION. */ ypold[1] = (float)1.; i__1 = np1; for (j = 2; j <= i__1; ++j) { ypold[j] = (float)0.; /* L50: */ } tangnf_(s, &y[1], &yp[1], &ypold[1], &a[1], &qr[qr_offset], &alpha[1], &tz[1], (int *)&pivot[1], (int *)nfe, (int *)n, (int *)iflag, &par[1], (int *)&ipar[1]); if (*iflag > 0) { return 0; } L70: i__1 = np1; for (j = 1; j <= i__1; ++j) { temp = y[j] + *h * yp[j]; w[j] = temp; z0[j] = temp; /* L80: */ } for (judy = 1; judy <= 4; ++judy) { rholen = (float)-1.; /* CALCULATE THE NEWTON STEP TZ AT THE CURRENT POINT W . */ tangnf_(&rholen, &w[1], &wp[1], &ypold[1], &a[1], &qr[qr_offset], &alpha[1], &tz[1], (int *)&pivot[1], (int *)nfe, (int *)n, (int *)iflag, &par[1], (int *)&ipar[1]) ; if (*iflag > 0) { return 0; } /* TAKE NEWTON STEP AND CHECK CONVERGENCE. */ i__1 = np1; for (j = 1; j <= i__1; ++j) { w[j] += tz[j]; /* L90: */ } itnum = judy; /* COMPUTE QUANTITIES USED FOR OPTIMAL STEP SIZE ESTIMATION. */ if (judy == 1) { lcalc = dnrm2_(&np1, &tz[1], &c__1); rcalc = rholen; i__1 = np1; for (j = 1; j <= i__1; ++j) { z1[j] = w[j]; /* L110: */ } } else if (judy == 2) { lcalc = dnrm2_(&np1, &tz[1], &c__1) / lcalc; rcalc = rholen / rcalc; } /* GO TO MOP-UP SECTION AFTER CONVERGENCE. */ if (dnrm2_(&np1, &tz[1], &c__1) <= *relerr * dnrm2_(&np1, &w[1], & c__1) + *abserr) { goto L600; } /* L200: */ } /* NO CONVERGENCE IN LITFH ITERATIONS. REDUCE H AND TRY AGAIN. */ if (*h <= fouru * (*s + (float)1.)) { *iflag = 6; return 0; } *h *= (float).5; goto L70; /* ***** END OF STARTUP SECTION. ***** */ /* ***** PREDICTOR SECTION. ***** */ L300: fail = FALSE_; /* COMPUTE POINT PREDICTED BY HERMITE INTERPOLANT. USE STEP SIZE H */ /* COMPUTED ON LAST CALL TO STEPNF . */ L320: i__1 = np1; for (j = 1; j <= i__1; ++j) { d__1 = *hold + *h; temp = ((((yp[j] - (y[j] - yold[j]) / *hold) / *hold - ((y[j] - yold[ j]) / *hold - ypold[j]) / *hold) / *hold * (d__1 - *hold) + (( y[j] - yold[j]) / *hold - ypold[j]) / *hold) * d__1 + ypold[j] ) * d__1 + yold[j]; w[j] = temp; z0[j] = temp; /* L330: */ } /* ***** END OF PREDICTOR SECTION. ***** */ /* ***** CORRECTOR SECTION. ***** */ for (judy = 1; judy <= 4; ++judy) { rholen = (float)-1.; /* CALCULATE THE NEWTON STEP TZ AT THE CURRENT POINT W . */ tangnf_(&rholen, &w[1], &wp[1], &yp[1], &a[1], &qr[qr_offset], &alpha[1], &tz[1], (int *)&pivot[1], (int *)nfe, (int *)n, (int *)iflag, &par[1], (int *)&ipar[1]); if (*iflag > 0) { return 0; } /* TAKE NEWTON STEP AND CHECK CONVERGENCE. */ i__1 = np1; for (j = 1; j <= i__1; ++j) { w[j] += tz[j]; /* L420: */ } itnum = judy; /* COMPUTE QUANTITIES USED FOR OPTIMAL STEP SIZE ESTIMATION. */ if (judy == 1) { lcalc = dnrm2_(&np1, &tz[1], &c__1); rcalc = rholen; i__1 = np1; for (j = 1; j <= i__1; ++j) { z1[j] = w[j]; /* L440: */ } } else if (judy == 2) { lcalc = dnrm2_(&np1, &tz[1], &c__1) / lcalc; rcalc = rholen / rcalc; } /* GO TO MOP-UP SECTION AFTER CONVERGENCE. */ if (dnrm2_(&np1, &tz[1], &c__1) <= *relerr * dnrm2_(&np1, &w[1], & c__1) + *abserr) { goto L600; } /* L500: */ } /*NO CONVERGENCE IN LITFH ITERATIONS. RECORD FAILURE AT CALCULATED H , */ /* SAVE THIS STEP SIZE, REDUCE H AND TRY AGAIN. */ fail = TRUE_; hfail = *h; if (*h <= fouru * (*s + (float)1.)) { *iflag = 6; return 0; } *h *= (float).5; goto L320; /* ***** END OF CORRECTOR SECTION. ***** */ /* ***** MOP-UP SECTION. ***** */ /* YOLD AND Y ALWAYS CONTAIN THE LAST TWO POINTS FOUND ON THE ZERO */ /* CURVE OF THE HOMOTOPY MAP. YPOLD AND YP CONTAIN THE TANGENT */ /* VECTORS TO THE ZERO CURVE AT YOLD AND Y , RESPECTIVELY. */ L600: i__1 = np1; for (j = 1; j <= i__1; ++j) { yold[j] = y[j]; ypold[j] = yp[j]; y[j] = w[j]; yp[j] = wp[j]; w[j] = y[j] - yold[j]; /* L620: */ } /* UPDATE ARC LENGTH. */ *hold = dnrm2_(&np1, &w[1], &c__1); *s += *hold; /* ***** END OF MOP-UP SECTION. ***** */ /* ***** OPTIMAL STEP SIZE ESTIMATION SECTION. ***** */ /* CALCULATE THE DISTANCE FACTOR DCALC . */ /* L700: */ i__1 = np1; for (j = 1; j <= i__1; ++j) { tz[j] = z0[j] - y[j]; w[j] = z1[j] - y[j]; /* L710: */ } dcalc = dnrm2_(&np1, &tz[1], &c__1); if (dcalc != (float)0.) { dcalc = dnrm2_(&np1, &w[1], &c__1) / dcalc; } /* THE OPTIMAL STEP SIZE HBAR IS DEFINED BY */ /* HT=HOLD * [MIN(LIDEAL/LCALC, RIDEAL/RCALC, DIDEAL/DCALC)]**(1/P) */ /* HBAR = MIN [ MAX(HT, BMIN*HOLD, HMIN), BMAX*HOLD, HMAX ] */ /* IF CONVERGENCE HAD OCCURRED AFTER 1 ITERATION, SET THE CONTRACTION */ /* FACTOR LCALC TO ZERO. */ if (itnum == 1) { lcalc = (float)0.; } /* FORMULA FOR OPTIMAL STEP SIZE. */ if (lcalc + rcalc + dcalc == (float)0.) { ht = sspar[7] * *hold; } else { /* Computing MAX */ d__2 = lcalc / sspar[1], d__3 = rcalc / sspar[2], d__2 = max(d__2, d__3), d__3 = dcalc / sspar[3]; d__1 = (float)1. / max(d__2,d__3); d__4 = (float)1. / sspar[8]; /* ht = pow_dd(&d__1, &d__4) * *hold; */ ht=pow(d__1,d__4) * *hold; } /* HT CONTAINS THE ESTIMATED OPTIMAL STEP SIZE. NOW PUT IT WITHIN */ /* REASONABLE BOUNDS. */ /* Computing MIN */ /* Computing MAX */ d__3 = ht, d__4 = sspar[6] * *hold, d__3 = max(d__3,d__4); d__1 = max(d__3,sspar[4]), d__2 = sspar[7] * *hold, d__1 = min(d__1,d__2); *h = min(d__1,sspar[5]); if (itnum == 1) { /* IF CONVERGENCE HAD OCCURRED AFTER 1 ITERATION, DON'T DECREASE H . */ *h = max(*h,*hold); } else if (itnum == 4) { /* IF CONVERGENCE REQUIRED THE MAXIMUM LITFH ITERATIONS, DON'T */ /* INCREASE H . */ *h = min(*h,*hold); } /* IF CONVERGENCE DID NOT OCCUR IN LITFH ITERATIONS FOR A PARTICULAR */ /* H = HFAIL , DON'T CHOOSE THE NEW STEP SIZE LARGER THAN HFAIL . */ if (fail) { *h = min(*h,hfail); } return 0; } /* stepnf_ */ /* end stepnf.c */ /**********************************************************************/ /***************** implementation code from Pmatrix.c *****************/ /**********************************************************************/ #define min(i,j) ((i) < (j) ? (i): (j)) #define FALSE 0 #define TRUE 1 /*--------------------------------------------------------------- vector/matrix type a linear array of int, whith auxilary info. *) the number of elements that can be stored is in elt[0] *) the current number of rows is in elt[1] *) the current number of collumbs is in elt[2] The actual data are then stored in row major order from elt[3] on ---------------------------------------------------------------*/ struct Pmatrix_t { int store; /* maximum number of helts reserved */ int topc; /* effective number of columbs */ int topr; /* effective number of rows */ int ncols; /* number of elts between first elts of rows */ polynomial1 *coords; }; /* ** a couple of functions which are defined in files that ** I don't want to include right now, when things stableize ** bad_error -- used mainly to stop things when a function ** is passed bad input, as things stablizes ** less catastrophic reactions may be introduced. ** mem_alloc, ** mem_free -- call malloc and free with some extra book-keeping. */ void bad_error(char *); /* WEIRD - The first pair of declarations below are the global one, which are now (6/13/99) included from pelutils.h. They replace the second pair, which had been declared at this point, specifically for this file, EVEN THOUGH THE ARGUMENT LIST IS DIFFERENT. I do not understand. - AMM */ /* void *mem_malloc(int); void mem_free(void *); */ /* char *mem_malloc(size_t); void mem_free(char *); */ /*------------------------------------------------------------- vector access macroes (which ignore any rows except for first) -------------------------------------------------------------*/ #define Vstore(V) ((V->store)) /* maximum #elts available */ #define Vlength(V) ((V->topr)) /* actual #elts stored */ #define Vref1(V,i) (&(((V->coords)[i-1]))) /*acces ith elt (starting at 1) */ #define Vref0(V,i) (&(((V->coords)[i]))) /*acces ith elt (starting at 0) */ #define Vref(V,i) Vref1(V,i) /*------------------------------------------------------------ matrix access macroes -------------------------------------------------------------*/ #define Mstore(V) ((V->store)) /* maximum #elts available */ #define MMrows(V) ((V->store/V->ncols)) /* maximum #rows */ #define Mrows(V) ((V->topr)) /* number rows stored */ #define Mcols(V) ((V->topc)) /* number cols stored */ #define MNcols(V) ((V->ncols)) /* number cols stored */ #define Mref1(V,i,j) (&(((V->coords)[(i-1)*(V->ncols)+j-1]))) #define Mref0(V,i,j) (&(((V->coords)[i*(V->ncols)+j]))) #define Mref(V,i,j) Mref1((V),i,j) int PMstore(Pmatrix M) { return Mstore(M); } int PMMrows(Pmatrix M) { return MMrows(M); } int PMrows(Pmatrix M) { return Mrows(M); } int PMcols(Pmatrix M) { return Mcols(M); } polynomial1 *PMref1(Pmatrix M, int i, int j) { return Mref1(M, i, j); } /* ** Constructor/Destructors for Pmatrixes ** ** Pmatrix Pmatrix_free(int r, int c); ** New Pmatrix cabable of holding r rows, and c collumbs. ** Pmatrix Pmatrix_new(Pmatrix V); */ Pmatrix Pmatrix_new(int r, int c) { Pmatrix V; int i, j; V = (Pmatrix) mem_malloc(sizeof(struct Pmatrix_t)); if (!V) bad_error("allocation failure in Pmatrix_new()"); V->coords = (polynomial1 *) mem_malloc(r * c * sizeof(polynomial1)); if (!V) bad_error("allocation failure 2 in Pmatrix_new()"); Mstore(V) = r * c; Mrows(V) = r; Mcols(V) = c; MNcols(V) = c; for (i = 1; i <= r; i++) { for (j = 1; j <= c; j++) *Mref(V, i, j)=0; } return V; } void Pmatrix_free(Pmatrix V) { int i, j; if (V != 0 && V->coords != 0) { for (i = 1; i <= Mrows(V); i++) for (j = 1; j <= Mcols(V); j++) freeP(*Mref(V, i, j)); mem_free((char *) (V->coords)); } if (V != 0) mem_free((char *) (V)); } /* ** Pmatrix_resize(R,r,c) ** Reset R to hold an r,by c matrix. ** if R has enough storage to hold an rxc matrix resets ** row and columb entrees of r to r and c. otherwise ** frees R and reallocates an rxc matrix ** DOES NOT PRESERVE INDECIES OF EXISTING DATA */ Pmatrix Pmatrix_resize(Pmatrix R, int r, int c) { if (R == 0 || Mstore(R) < (r * c)) { if (R != 0) Pmatrix_free(R); R = Pmatrix_new(r, c); } else { Mrows(R) = r; Mcols(R) = c; MNcols(R) = c; } return R; } Pmatrix Pmatrix_submat(Pmatrix R, int r, int c) { if (R == 0 || c > Mcols(R) || r > Mrows(R) * MNcols(R)) { bad_error("bad subscripts or zero matrix in Pmatrix_submat()"); } else { Mrows(R) = r; Mcols(R) = c; } return R; } /* ** Pmatrix_print(M): print an Pmatrix ** if M is null print <<>> and return fail. ** otherwise print matrix and return true. */ Pmatrix Pmatrix_print(Pmatrix M) { int i, j; if (M == 0) { printf("<<>>"); return 0; } printf("<"); for (i = 1; i <= Mrows(M); i++) { printf("<"); for (j = 1; j <= Mcols(M); j++) { printP(*Mref(M, i, j)); if (j < Mcols(M)) printf(", "); } printf(">"); if (i < Mrows(M)) printf("\n"); } printf(">"); return M; } Pmatrix Pmatrix_copy(Pmatrix P){ Pmatrix C; int i,j; C=Pmatrix_new(Mrows(P),Mcols(P)); for(i=1;i<=Mrows(P);i++){ for(j=1;j<=Mcols(P);j++){ *Mref(C,i,j)=copyP(*Mref(P,i,j)); } } return C; } /* end Pmatrix.c */ /**********************************************************************/ /********* implementation code from the original Homotopies.c *********/ /**********************************************************************/ /*------------------------------------------------------------------ Homotopies.c created 9/15/1994 last modified 9/15/994 Birk Huber (birk@math.cornell.edu ALL RIGHTS RESERVED Store and evaluate Homotopies for Continuation module of Pelican. the functions rho and rhojac are defined to be usable by the hompack code (originaly in fortran translated with the help of f2c). The representation of Homotopies and implementation is very similar to that used by hompack and described in Morgans book. -------------------------------------------------------------------*/ /*------------------------------------------------------------------ globals representing the homotopy and macroes for accessing them The system of complex polynomial1s is represented in real form -----------------------------------------------------------------*/ /* parameters affecting the homotopy */ int Hom_defd = 0; /* 0 no homotopy initialized , 1 else*/ int Hom_use_proj = 1; /* 0 dont use proj trans, 1 else*/ int Hom_num_vars = 0; /* number of complex vars in curr hom*/ /* private variables defining homotopy */ static int NV,N,N1,M; static int *Starting_Monomial; static int *Number_of_Monomials; static int *Exponents; static int *Hdegree; static int *Edegree; static double *Coefitients; static int *Deformation; static double *Proj_Trans; /* index in monomial list (starting at 0) of equation i*/ #define monst(i,j) ((Starting_Monomial[(i)-1])+(j)-1) /* number of monomials in the ith equation */ #define Nmon(i) (Number_of_Monomials[(i)-1]) /* exponent of variable k in monomial j of equation i */ #define Exp(i,j,k) Exponents[(monst(i,j))*NV+(k)-1] /* get the exponent of the deformation parameter in the jth monomial of the ith equation */ #define Def(i,j) Deformation[monst(i,j)] /* get the real and imaginary part of jth monomial of ith equation */ #define RCoef(i,j) Coefitients[2*(monst(i,j))] #define ICoef(i,j) Coefitients[2*(monst(i,j))+1] /* real and imaginary parts of coordinates defining the projective transformation */ #define RPtrans(j) Proj_Trans[2*(j)-2] #define IPtrans(j) Proj_Trans[2*(j)-1] /* exponent of homogenizing variable in jthmonomial of ith equation*/ #define Hdeg(i,j) Hdegree[monst(i,j)] /* degree of equation i */ #define Edeg(i) Edegree[i-1] extern Pring Def_Ring; Pvector psys_to_Pvec(psys sys){ polynomial1 tmpm,tmpp; int j; Pvector PV; PV=Pvector_new(psys_d(sys)); FORALL_POLY(sys, tmpp=0; FORALL_MONO(sys, tmpm=makeP(Def_Ring); *poly_coef(tmpm)=Complex(*psys_coef_real(sys), *psys_coef_imag(sys)); *poly_def(tmpm)=*psys_def(sys); *poly_homog(tmpm)=*psys_homog(sys); for(j=1;j<=psys_d(sys);j++) *poly_exp(tmpm,j)=*psys_exp(sys,j); tmpp=addPPP(tmpp,tmpm,tmpp); freeP(tmpm); ) *PVref(PV,psys_eqno(sys))=tmpp; ) return PV; } // WARNING: RDM added the following just to get to compile under BCC // I have no idea if this is correct!!! #if !defined(HAVE_DRAND48) double drand48() { return rand(); } #endif // HAVE_DRAND48 /*------------------------------------------------------------------- init_hom takes a Pvector and loads the above data structures to hold a representation of the system. -------------------------------------------------------------------*/ int init_hom(psys PS){ Pvector P; polynomial1 ptr; int i,j,k; double t; /* double drand48(); CANT DECLARE BUILTINS UNDER C++ */ int seed=12; P=psys_to_Pvec(PS); NV=poly_dim(*PMref(P,1,1)); /* number of complex variables*/ N=2*NV; /* number of real coordinates */ N1=N+1; /* number of realcoords incl lift coord*/ /* check that P has n elts, and that Ring has NV vars */ if ( NV != PMcols(P)) { printf("warning nonsquare homotopy in init_HPK\n"); Hom_defd=0; } /* Set number of vars for external use */ Hom_num_vars=NV; /* free all work space */ Dfree(0); Ifree(0); /* count monomials in equations to initialize monst and Nmon*/ Starting_Monomial=Ires(NV+1); Number_of_Monomials=Ires(NV); Starting_Monomial[0]=0; for(i=0;i1){ d=(*k)/2; /* determine the complex var to diff by.*/ for(i=1;i<=NV;i++){ v[2*i-2]=0.0; v[2*i-1]=0.0; if (Hom_use_proj==1){ for(j=1;j<=Nmon(i);j++){ if (Hdeg(i,j)!=0){ c=Cmul(Complex(RCoef(i,j),ICoef(i,j)), Cpow(Hpath(*lambda),Def(i,j))); for(h=1;h<=NV;h++) c=Cmul(c,Cpow(Complex(x[2*h-2],x[2*h-1]),Exp(i,j,h))); c=Cmul(c,Cpow(PN,Hdeg(i,j)-1)); c=Cmul(c,Complex(t=Hdeg(i,j),0.0)); c=Cmul(c,Complex(RPtrans(d),IPtrans(d))); v[2*i-2]+=c.r; v[2*i-1]+=c.i; } } } for(j=1;j<=Nmon(i);j++){ if (Exp(i,j,d)!=0){ c=Cmul(Complex(RCoef(i,j),ICoef(i,j)), Cpow(Hpath(*lambda),Def(i,j))); for(h=1;h= 0 THE NORM IS NOT */ /* COMPUTED AND RHOLEN IS NOT CHANGED. */ /* Y(1:N+1) = CURRENT POINT (LAMBDA(S), X(S)). */ /* YPOLD(1:N+1) = UNIT TANGENT VECTOR AT PREVIOUS POINT ON THE ZERO */ /* CURVE OF THE HOMOTOPY MAP. */ /* A(1:*) = PARAMETER VECTOR IN THE HOMOTOPY MAP. */ /* QR(1:N,1:N+2), ALPHA(1:N), TZ(1:N+1), PIVOT(1:N+1) ARE WORK ARRAYS */ /* USED FOR THE QR FACTORIZATION. */ /* NFE = NUMBER OF JACOBIAN MATRIX EVALUATIONS = NUMBER OF HOMOTOPY */ /* FUNCTION EVALUATIONS. */ /* N = DIMENSION OF X. */ /* IFLAG = -2, -1, OR 0, INDICATING THE PROBLEM TYPE. */ /* PAR(1:*) AND IPAR(1:*) ARE ARRAYS FOR (OPTIONAL) USER PARAMETERS, */ /* WHICH ARE SIMPLY PASSED THROUGH TO THE USER WRITTEN SUBROUTINES */ /* RHO, RHOJAC. */ /* ON OUTPUT: */ /* RHOLEN = ||RHO(A, LAMBDA(S), X(S)|| IF RHOLEN < 0 ON INPUT. */ /* OTHERWISE RHOLEN IS UNCHANGED. */ /* Y, YPOLD, A, N ARE UNCHANGED. */ /* YP(1:N+1) = DY/DS = UNIT TANGENT VECTOR TO INTEGRAL CURVE OF */ /* D(HOMOTOPY MAP)/DS = 0 AT Y(S) = (LAMBDA(S), X(S)) . */ /* TZ = THE NEWTON STEP = -(PSEUDO INVERSE OF (D RHO(A,Y(S))/D LAMBDA , */ /* D RHO(A,Y(S))/DX)) * RHO(A,Y(S)) . */ /* NFE HAS BEEN INCRMENTED BY 1. */ /* IFLAG IS UNCHANGED, UNLESS THE QR FACTORIZATION DETECTS A RANK < N, */ /* IN WHICH CASE THE TANGENT AND NEWTON STEP VECTORS ARE NOT COMPUTED */ /* AND TANGNF RETURNS WITH IFLAG = 4 . */ /* CALLS DDOT , DNRM2 , F (OR RHO ), FJAC (OR RHOJAC ). */ /* ***** ARRAY DECLARATIONS. ***** */ /* ARRAYS FOR COMPUTING THE JACOBIAN MATRIX AND ITS KERNEL. */ /* ***** END OF DIMENSIONAL INFORMATION. ***** */ /* Parameter adjustments */ --pivot; --tz; --alpha; qr_dim1 = *n; qr_offset = qr_dim1 + 1; qr -= qr_offset; --a; --ypold; --yp; --y; --par; --ipar; /* Function Body */ lambda = y[1]; np1 = *n + 1; np2 = *n + 2; ++(*nfe); /* NFE CONTAINS THE NUMBER OF JACOBIAN EVALUATIONS. */ /* * * * * * * * * * * * * * * * * * */ /* COMPUTE THE JACOBIAN MATRIX, STORE IT AND HOMOTOPY MAP IN QR. */ if (*iflag == -2) { /* QR = ( D RHO(A,LAMBDA,X)/D LAMBDA , D RHO(A,LAMBDA,X)/DX , */ /* RHO(A,LAMBDA,X) ) . */ i__1 = np1; for (k = 1; k <= i__1; ++k) { rhojac_(&a[1], &lambda, &y[2], &qr[k * qr_dim1 + 1], &k, &par[1], &ipar[1]); /* L30: */ } rho_(&a[1], &lambda, &y[2], &qr[np2 * qr_dim1 + 1], &par[1], &ipar[1]) ; } else { f_(&y[2], &tz[1]); if (*iflag == 0) { /* QR = ( A - F(X), I - LAMBDA*DF(X) , */ /* X - A + LAMBDA*(A - F(X)) ) . */ i__1 = *n; for (j = 1; j <= i__1; ++j) { sigma = a[j]; beta = sigma - tz[j]; qr[j + qr_dim1] = beta; /* L100: */ qr[j + np2 * qr_dim1] = y[j + 1] - sigma + lambda * beta; } i__1 = *n; for (k = 1; k <= i__1; ++k) { fjac_(&y[2], &tz[1], (integer *)&k); kp1 = k + 1; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L110: */ qr[j + kp1 * qr_dim1] = -lambda * tz[j]; } /* L120: */ qr[k + kp1 * qr_dim1] += (float)1.; } } else { /* QR = ( F(X) - X + A, LAMBDA*DF(X) + (1 - LAMBDA)*I , */ /* X - A + LAMBDA*(F(X) - X + A) ) . */ /* L140: */ i__1 = *n; for (j = 1; j <= i__1; ++j) { sigma = y[j + 1] - a[j]; beta = tz[j] - sigma; qr[j + qr_dim1] = beta; /* L150: */ qr[j + np2 * qr_dim1] = sigma + lambda * beta; } i__1 = *n; for (k = 1; k <= i__1; ++k) { fjac_(&y[2], &tz[1], (integer *)&k); kp1 = k + 1; i__2 = *n; for (j = 1; j <= i__2; ++j) { /* L160: */ qr[j + kp1 * qr_dim1] = lambda * tz[j]; } /* L170: */ qr[k + kp1 * qr_dim1] = (float)1. - lambda + qr[k + kp1 * qr_dim1]; } } } /* * * * * * * * * * * * * * * * * * */ /* COMPUTE THE NORM OF THE HOMOTOPY MAP IF IT WAS REQUESTED. */ if (*rholen < (float)0.) { *rholen = dnrm2_((integer *)n, &qr[np2 * qr_dim1 + 1], &c__1); } /* REDUCE THE JACOBIAN MATRIX TO UPPER TRIANGULAR FORM. */ /* THE FOLLOWING CODE IS A MODIFICATION OF THE ALGOL PROCEDURE */ /* DECOMPOSE IN P. BUSINGER AND G. H. GOLUB, LINEAR LEAST */ /* SQUARES SOLUTIONS BY HOUSEHOLDER TRANSFORMATIONS, */ /* NUMER. MATH. 7 (1965) 269-276. */ i__1 = np1; for (j = 1; j <= i__1; ++j) { yp[j] = ddot_((integer *)n, &qr[j * qr_dim1 + 1], &c__1, &qr[j * qr_dim1 + 1], &c__1); /* L220: */ pivot[j] = j; } i__1 = *n; for (k = 1; k <= i__1; ++k) { sigma = yp[k]; jbar = k; kp1 = k + 1; i__2 = np1; for (j = kp1; j <= i__2; ++j) { if (sigma >= yp[j]) { goto L240; } sigma = yp[j]; jbar = j; L240: ; } if (jbar == k) { goto L260; } i = pivot[k]; pivot[k] = pivot[jbar]; pivot[jbar] = i; yp[jbar] = yp[k]; yp[k] = sigma; i__2 = *n; for (i = 1; i <= i__2; ++i) { sigma = qr[i + k * qr_dim1]; qr[i + k * qr_dim1] = qr[i + jbar * qr_dim1]; qr[i + jbar * qr_dim1] = sigma; /* L250: */ } /* END OF COLUMN INTERCHANGE. */ L260: i__2 = *n - k + 1; sigma = ddot_((integer *)&i__2, &qr[k + k * qr_dim1], &c__1, &qr[k + k * qr_dim1], &c__1); if (sigma == (float)0.) { *iflag = 4; return 0; } /* L270: */ if (k == *n) { goto L300; } qrkk = qr[k + k * qr_dim1]; alphak = -sqrt(sigma); if (qrkk < (float)0.) { alphak = -alphak; } alpha[k] = alphak; beta = (float)1. / (sigma - qrkk * alphak); qr[k + k * qr_dim1] = qrkk - alphak; i__2 = np2; for (j = kp1; j <= i__2; ++j) { i__3 = *n - k + 1; sigma = beta * ddot_((integer *)&i__3, &qr[k + k * qr_dim1], &c__1, &qr[k + j * qr_dim1], &c__1); i__3 = *n; for (i = k; i <= i__3; ++i) { qr[i + j * qr_dim1] -= qr[i + k * qr_dim1] * sigma; /* L280: */ } if (j < np2) { /* Computing 2nd power */ d__1 = qr[k + j * qr_dim1]; yp[j] -= d__1 * d__1; } /* L290: */ } L300: ; } alpha[*n] = qr[*n + *n * qr_dim1]; /* COMPUTE KERNEL OF JACOBIAN, WHICH SPECIFIES YP=DY/DS. */ tz[np1] = (float)1.; for (i = *n; i >= 1; --i) { sum = (float)0.; i__1 = np1; for (j = i + 1; j <= i__1; ++j) { /* L330: */ sum += qr[i + j * qr_dim1] * tz[j]; } /* L340: */ tz[i] = -sum / alpha[i]; } ypnorm = dnrm2_((integer *)&np1, &tz[1], &c__1); i__1 = np1; for (k = 1; k <= i__1; ++k) { /* L360: */ yp[pivot[k]] = tz[k] / ypnorm; } if (ddot_((integer *)&np1, &yp[1], &c__1, &ypold[1], &c__1) >= (float)0.) { goto L380; } i__1 = np1; for (i = 1; i <= i__1; ++i) { /* L370: */ yp[i] = -yp[i]; } /* YP IS THE UNIT TANGENT VECTOR IN THE CORRECT DIRECTION. */ /* COMPUTE THE MINIMUM NORM SOLUTION OF [D RHO(Y(S))] V = -RHO(Y(S)). */ /* V IS GIVEN BY P - (P,Q)Q , WHERE P IS ANY SOLUTION OF */ /* [D RHO] V = -RHO AND Q IS A UNIT VECTOR IN THE KERNEL OF [D RHO]. */ L380: for (i = *n; i >= 1; --i) { sum = qr[i + np1 * qr_dim1] + qr[i + np2 * qr_dim1]; i__1 = *n; for (j = i + 1; j <= i__1; ++j) { /* L430: */ sum += qr[i + j * qr_dim1] * alpha[j]; } /* L440: */ alpha[i] = -sum / alpha[i]; } i__1 = *n; for (k = 1; k <= i__1; ++k) { /* L450: */ tz[pivot[k]] = alpha[k]; } tz[pivot[np1]] = (float)1.; /* TZ NOW CONTAINS A PARTICULAR SOLUTION P, AND YP CONTAINS A VECTOR Q */ /* IN THE KERNEL(THE TANGENT). */ sigma = ddot_((integer *)&np1, &tz[1], &c__1, &yp[1], &c__1); i__1 = np1; for (j = 1; j <= i__1; ++j) { tz[j] -= sigma * yp[j]; /* L470: */ } /* TZ IS THE NEWTON STEP FROM THE CURRENT POINT Y(S) = (LAMBDA(S), X(S)). */ return 0; } /* tangnf_ */ /* end tangnf.c */ gambit-0.2010.09.01/src/tools/enumpoly/pelhomot.h0000644000076500007650000002347211350032206016237 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* Homotopies.h */ /* This file and Homotopies.c contain the code that was in the Cont subdirectory of the source directory of the original Pelican 0.80 */ #ifndef HOMOTOPIES_H #define HOMOTOPIES_H #include #include "pelpsys.h" /************************************************************************/ /**************** header information from Hom_params.h ******************/ /************************************************************************/ #define Hom_LogFile stdout /* was Pel_Log */ #define Hom_OutFile stdout /* was Pel_Out */ extern int Hom_defd; extern int Hom_use_proj; extern int Hom_use_scale; extern int Hom_num_vars; extern char Hom_LogName[]; extern FILE *Pel_Log; extern FILE *Pel_Out; extern double Hom_tol; extern int Hom_use_proj; void print_Hom_params(FILE *); /* end Hom_params.h */ /************************************************************************/ /****************** header information from Hom_Mem.h *******************/ /************************************************************************/ double *Dres(int); int Dtop(); int Dfree(int ntop); int *Ires(int sz); int Itop(); int Ifree(int ntop); /* end Hom_Mem.h */ /************************************************************************/ /******************** header information from f2c.h *********************/ /************************************************************************/ typedef long int integer; typedef char *address; typedef short int shortint; typedef float real; typedef double doublereal; typedef struct { real r, i; } complex; typedef struct { doublereal r, i; } doublecomplex; typedef long int logical; typedef short int shortlogical; typedef char logical1; typedef char integer1; /* typedef long long longint; */ /* system-dependent */ #define TRUE_ (1) #define FALSE_ (0) /* Extern is for use with -E */ #ifndef Extern #define Extern extern #endif /* I/O stuff */ #ifdef f2c_i2 /* for -i2 */ typedef short flag; typedef short ftnlen; typedef short ftnint; #else typedef long flag; typedef long ftnlen; typedef long ftnint; #endif /*external read, write*/ typedef struct { flag cierr; ftnint ciunit; flag ciend; char *cifmt; ftnint cirec; } cilist; /*internal read, write*/ typedef struct { flag icierr; char *iciunit; flag iciend; char *icifmt; ftnint icirlen; ftnint icirnum; } icilist; /*open*/ typedef struct { flag oerr; ftnint ounit; char *ofnm; ftnlen ofnmlen; char *osta; char *oacc; char *ofm; ftnint orl; char *oblnk; } olist; /*close*/ typedef struct { flag cerr; ftnint cunit; char *csta; } cllist; /*rewind, backspace, endfile*/ typedef struct { flag aerr; ftnint aunit; } alist; /* inquire */ typedef struct { flag inerr; ftnint inunit; char *infile; ftnlen infilen; ftnint *inex; /*parameters in standard's order*/ ftnint *inopen; ftnint *innum; ftnint *innamed; char *inname; ftnlen innamlen; char *inacc; ftnlen inacclen; char *inseq; ftnlen inseqlen; char *indir; ftnlen indirlen; char *infmt; ftnlen infmtlen; char *inform; ftnint informlen; char *inunf; ftnlen inunflen; ftnint *inrecl; ftnint *innrec; char *inblank; ftnlen inblanklen; } inlist; #define VOID void union Multitype { /* for multiple entry points */ integer1 g; shortint h; integer i; /* longint j; */ real r; doublereal d; complex c; doublecomplex z; }; typedef union Multitype Multitype; typedef long Long; /* No longer used; formerly in Namelist */ struct Vardesc { /* for Namelist */ char *name; char *addr; ftnlen *dims; int type; }; typedef struct Vardesc Vardesc; struct Namelist { char *name; Vardesc **vars; int nvars; }; typedef struct Namelist Namelist; #define dblabs(x) ((x) >= 0 ? (x) : -(x)) #define dabs(x) (doublereal)dblabs(x) /* #define min(a,b) ((a) <= (b) ? (a) : (b)) */ #define max(a,b) ((a) >= (b) ? (a) : (b)) #define dmin(a,b) (doublereal)min(a,b) #define dmax(a,b) (doublereal)max(a,b) /* procedure parameter types for -A and -C++ */ #define F2C_proc_par_types 1 #ifdef __cplusplus typedef int /* Unknown procedure type */ (*U_fp)(...); typedef shortint (*J_fp)(...); typedef integer (*I_fp)(...); typedef real (*R_fp)(...); typedef doublereal (*D_fp)(...), (*E_fp)(...); typedef /* Complex */ VOID (*C_fp)(...); typedef /* Double Complex */ VOID (*Z_fp)(...); typedef logical (*L_fp)(...); typedef shortlogical (*K_fp)(...); typedef /* Character */ VOID (*H_fp)(...); typedef /* Subroutine */ int (*S_fp)(...); #else typedef int /* Unknown procedure type */ (*U_fp)(); typedef shortint (*J_fp)(); typedef integer (*I_fp)(); typedef real (*R_fp)(); typedef doublereal (*D_fp)(), (*E_fp)(); typedef /* Complex */ VOID (*C_fp)(); typedef /* Double Complex */ VOID (*Z_fp)(); typedef logical (*L_fp)(); typedef shortlogical (*K_fp)(); typedef /* Character */ VOID (*H_fp)(); typedef /* Subroutine */ int (*S_fp)(); #endif /* E_fp is for real functions when -R is not specified */ typedef VOID C_f; /* complex function */ typedef VOID H_f; /* character function */ typedef VOID Z_f; /* double complex function */ typedef doublereal E_f; /* real function with -R not specified */ /* undef any lower-case symbols that your C compiler predefines, e.g.: */ #ifndef Skip_f2c_Undefs #undef cray #undef gcos #undef mc68010 #undef mc68020 #undef mips #undef pdp11 #undef sgi #undef sparc #undef sun #undef sun2 #undef sun3 #undef sun4 #undef u370 #undef u3b #undef u3b2 #undef u3b5 #undef unix #undef vax #endif /* end of f2c.h */ /************************************************************************/ /***************** header information from Pmatrix.h *****************/ /************************************************************************/ typedef struct Pmatrix_t *Pmatrix; typedef struct Pmatrix_t *Pvector; /* ** matrix access macroes */ int PMstore(Pmatrix M); /* maximum #elts available*/ int PMMrows(Pmatrix M); /* maximum #rows */ int PMrows(Pmatrix M); /* number rows stored */ int PMcols(Pmatrix M); /* number cols stored */ polynomial1 *PMref1(Pmatrix,int,int); #define PMref0(M,i,j) (PMref(M,(i+1),(j+1))) #define PMref(M,i,j) (PMref1((M),i,j)) #define PVref0(M,j) (PMref(M,1,(j+1))) #define PVref(M,j) (PMref1((M),1,j)) #define PVlength(M) (PMcols(M)) /* ** Constructor/Pestructors/Pisplay */ Pmatrix Pmatrix_new(int r, int c); Pmatrix Pmatrix_resize(Pmatrix M, int r, int d); void Pmatrix_free(Pmatrix V); Pmatrix Pmatrix_print(Pmatrix M); #define Pvector_print(V) (Pmatrix_print(V)) #define Pvector_new(n) (Pmatrix_new(1,n)) #define Pvector_free(V) (Pmatrix_free(V)) #define Pvector_resize(M,d) (Pmatrix_resize(M,1,d)) /* ** Arithmatic and other operations on Pmatrices */ Pmatrix Pmatrix_add(Pmatrix M1, Pmatrix M2, Pmatrix *M3); #define add_Pvector(V1,V2,V3) add_Pmatrix(V1,V2,V3) /*Pmatrix Pmatrix_mull(Pmatrix M1, Pmatrix M2, Pmatrix *M3); */ Pmatrix Pmatrix_dot(Pmatrix M1, Pmatrix M2, Pmatrix M3); void PMset(Pmatrix M, int i, int j, signed int k); signed long int PMget(Pmatrix M, int i, int j); int Pmatrix_gcd_reduce(Pmatrix M); int Pmatrix_backsolve(Pmatrix N, Pmatrix S); int Pmatrix_rref(Pmatrix N,int *det); Pmatrix Pmatrix_resize(Pmatrix M, int r, int d); Pmatrix Pmatrix_submat(Pmatrix R, int r, int c); #define Pvector_copy(M) Pmatrix_copy(M) Pmatrix Pmatrix_copy(Pmatrix M); /* end of Pmatrix.h */ /************************************************************************/ /********** header information from the original Homotopies.h ***********/ /************************************************************************/ void print_homog(double *x,double *coord_r,double *coord_i); int init_hom(psys P); void Htransform(Dvector X); void Huntransform(Dvector X); int HPK_cont(Dvector X); /* end, original Homotopies.h */ /************************************************************************/ /********************** declaration of fixpnf_(..) **********************/ /************************************************************************/ void print_proj_trans(); int fixpnf_(int *n, double *y, int *iflag, double *arcre, double *arcae, double *ansre, double *ansae, int *trace, double *a, int *nfe, double *arclen, double *yp, double *yold, double *ypold, double *qr, double *alpha, double *tz, int *pivot, double *w, double *wp, double *z0, double *z1, double *sspar, double *par, int *ipar, int tweak); /* Reduce step size, increase # of steps */ /***********************************************************************/ /******************* header information for tangnf.c *******************/ /***********************************************************************/ int tangnf_(double *rholen, double *y, double *yp, double *ypold, double *a, double *qr, double *alpha, double *tz, int *pivot, int *nfe, int *n, int *iflag, double *par, int *ipar); #endif /* HOMOTOPIES_H */ gambit-0.2010.09.01/src/tools/enumpoly/pelpred.cc0000644000076500007650000000741411350032206016177 00000000000000/* ** copyright (c) 1995 Birk Huber */ #include "pelpred.h" int Is_Numeric(int t){ switch(t){ case Int_T: case Dbl_T: case Cpx_T: case Ply_T: case Mtx_T: case Sys_T: return TRUE; break; default: return FALSE; } return FALSE; } /* ** Common_Type takes two ptype and returns the simplest ** ptype to which both can be coerced. ** ** Vector, and List handling must still be implemented. ** The code does make assumptions about the values ** associated with the types. */ int Common_Type(int t1, int t2){ int temp; if (t1==t2)return t2; if (t1>t2){ temp=t2; t2=t1; t1=temp;} if (Is_Numeric(t1)==TRUE&&Is_Numeric(t2)==TRUE) return t2; return INVALID_T; } int Can_Be_Poly(Gen_node g) { if (g==0) return 0; switch (g->type){ case Int_T: case Dbl_T: case Cpx_T: case Ply_T: return 1; break; default: return 0; } return 0; } int Can_Be_Cpx(Gen_node g) { if (g==0) return 0; switch (g->type){ case Int_T: case Dbl_T: case Cpx_T: return 1; break; default: return 0; } return 0; } int Can_Be_Dbl(Gen_node g) { if (g==0) return 0; switch (g->type){ case Int_T: case Dbl_T: return 1; break; default: return 0; } return 0; } int Can_Be_Int(Gen_node g) { if (g==0) return 0; switch (g->type){ case Int_T: return 1; break; default: return 0; } return 0; } int Can_Be_Number(Gen_node g, int t){ if (Common_Type(Gen_type(g),t)==t) return TRUE; else return FALSE; } int Can_Be_Vector(Gen_node g, int Tp){ int r,c,t; if (Gen_Mtx_Specs(g,&r,&c,&t)==FALSE) return -1; if (r!=1 || c<1 || Common_Type(t,Tp)!=Tp) return -1; return c; } int Can_Be_Matrix(Gen_node g, int Tp){ int r,c,t; if (Gen_Mtx_Specs(g,&r,&c,&t)==FALSE) return -1; if (r<1 || c<1 || Common_Type(t,Tp)!=Tp) return -1; return c; } int Can_Be_Aset(Gen_node g){ if (g==0) return FALSE; if (Gen_type(g)==Ast_T) return TRUE; else return FALSE; } int Can_Be_List(Gen_node g){ if (g==0) return FALSE; switch (Gen_type(g)){ case Xpl_T: case Npl_T: case Lst_T: /*case SLL_T:*/ return TRUE; break; default: break; } return FALSE; } int Can_Be_Xpnt(Gen_node ptr){ if (Can_Be_Vector(ptr,Dbl_T)==2*N+3) return TRUE; else return FALSE; } int Can_Be_List_Of(Gen_node ptr, int (*pred)(Gen_node)){ if (Can_Be_List(ptr)==FALSE) return FALSE; ptr=Gen_lval(ptr); while(ptr!=0){ if (pred(ptr)!=TRUE) return FALSE; ptr=Gen_next(ptr); } return TRUE; } /* ** Gen_Can_Be_Aset ** Input: A Gen_node g ** Output: TRUE if g consists of a list of point configuration ** (each point configuration represented by a ** vectors of points) ** (each point represented by a vector of integers) ** (all points must have same number of coords). ** FALSE otherwise; ** Side Effects r is set to number of. ** d is set to number of coords for points. */ int Gen_Can_Be_Aset(Gen_node g,int *r, int *d){ Gen_node ptr; Gmatrix M; int j,tn=0, td=0, tt=0,n; *r=0; *d=0; for(ptr=g;ptr!=0;ptr=Gen_next(ptr)){ Gen_Mtx_Specs(ptr,&tn,&td,&tt); if (tn!=1 || td==0) return FALSE; M=Gen_Mtx(ptr); n=tn; for(j=1;j<=n;j++){ Gen_Mtx_Specs(*GMref(M,1,j),&tn,&td,&tt); if (tt!=Int_T || tn!=1 || td==0) return FALSE; if (*d!=0 && *d!=td ) return FALSE; if (*d==0) *d=td; } (*r)++; } return TRUE; } gambit-0.2010.09.01/src/tools/enumpoly/pelpred.h0000644000076500007650000000254611350032206016042 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* ** copyright (c) 1995 Birk Huber */ #include "pelgmatr.h" int Can_Be_Poly(Gen_node g); int Can_Be_Cpx(Gen_node g); int Can_Be_Dbl(Gen_node g); int Can_Be_Int(Gen_node g); int Can_Be_Aset(Gen_node g); int Can_Be_Vector(Gen_node g, int Tp); int Can_Be_Matrix(Gen_node g, int Tp); int Can_Be_List(Gen_node g); int Common_Type(int,int); int Is_Numeric(int t); int Can_Be_Number(Gen_node g, int t); int Gen_Can_Be_Aset(Gen_node g,int *r, int *d); int Can_Be_List_Of(Gen_node ptr, int (*pred)(Gen_node)); int Can_Be_Xpnt(Gen_node ptr); gambit-0.2010.09.01/src/tools/enumpoly/pelprgen.cc0000644000076500007650000006067611350032206016371 00000000000000/* ** Proc_Gen.c ** Commands defining Pelican functions ** ** copyright (c) 1995 Birk Huber */ /* This version is obtained from editing by Andy McLennan - 1999 */ #include "pelprgen.h" static int time0 = 0; /* initialized to 0 to get rid of warning - AMM */ /* -------------------------------------------------------------- Install_Command(Gen_node (*G)(),char *s) takes a pointer to a Shell Procedure and a string s, installs the pair on the symbol table-- and returns the value of the resulting symbol table entry. Error Conditions: if either G or S are NULL nothing is done and Null is returned if Gen_node() fails NULL is returned. install will return NULL on some error conditions and this will be passed through lock and returned. --------------------------------------------------------------*/ /* Sym_ent Install_Command(Gen_node (*G)(),char *s){ return lock(install(s,PND(G))); } */ /*----------------------------------------------------------------- int Install_Gen_Commands() Uses Install_Command to install all Commands On the symbol table. Always returns 1; Error Conditions: None; -----------------------------------------------------------------*/ /******************************************************************** Begin Command Definitions ********************************************************************/ /* ** Help Command: */ Gen_node G_Help(Gen_node g){ char *lable; if (Gen_length(g)!=1 || (lable=Gen_idval(Gen_elt(g,1)))==0) return Rerror("usage: help(topic) where topic is a string",g); /* print_doc(lable); REMOVED */ free_Gen_list(g); g=IDND(""); return g; } /* ** Aset Command (tested on poly's) */ /* aset psys_to_aset(psys); IN psys.h */ Gen_node G_Aset(Gen_node g){ psys P; aset A=0; /* if (Gen_length(g)==1&&Can_Be_Vector(g,Ply_T)>0){ */ if (Gen_length(g)==1&&Can_Be_Vector(g,Ply_T)>0){ P=Gen_to_psys(g); /* free_Gen_list(g); */ A=psys_to_aset(P); psys_free(P); return ASTND(A); } return List_To_Aset(g); } /* ** Cayley Triangulation Command (tested: looses 2 ) ** (problem probably in cly_triangulate) */ Gen_node G_Ctrig(Gen_node g){ aset A=0,CP=0; Ivector T=0; int r = 0; Gen_node ptr; int nargs; LOCS(2); PUSH_LOC(A); PUSH_LOC(CP); nargs=Gen_length(g); if ( (nargs ==0) || (nargs==1 && Can_Be_Aset(Gen_elt(g,1))!=TRUE)|| (nargs==2 && (r=Can_Be_Vector(Gen_elt(g,2),Int_T))<0)){ POP_LOCS(); return Rerror("Usage: Ctrig(Aset,)",g); } A=Gen_aset(Gen_elt(g,1)); if (nargs==2 ){ if (r==aset_r(A)) T=Gen_to_Imatrix(Gen_elt(g,2)); else { POP_LOCS(); return Rerror("Usage: Ctrig(Aset,)",g); } } time0=set_mark(); CP=cly_triangulate(A,T,TRUE,TRUE); #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"\ntime used %d,\n",read_mark(time0)) #endif ; free_Gen_list(g); if (CP!=0){ ptr=(g=Imatrix_to_Gen((Imatrix)Car(Car(CP)))); while((CP=Cdr(CP))!=0) ptr=Gen_set_next(ptr, Imatrix_to_Gen((Imatrix)Car(Car(CP)))); g=Gen_node_to_List(g); } else g=IDND(""); if (T!=0) Imatrix_free(T); POP_LOCS(); return g; } /* ** Cayley Triangulation Command (tested: looses 2 ) ** (problem probably in cly_triangulate ) */ Gen_node G_GenSolve(Gen_node g, int tweak){ aset A=0; int seed; psys Sys; /* Cayley_continue(aset,Ivector,node *,int,int); IN cly_all.h */ node Sols=0; Ivector T=0; int r; int nargs; LOCS(2); PUSH_LOC(A); PUSH_LOC(Sols); nargs=Gen_length(g); if ( (nargs <2) || (Can_Be_Aset(Gen_elt(g,1))!=TRUE)|| ((r=Can_Be_Vector(Gen_elt(g,2),Int_T))<0)|| (nargs>=3 && Can_Be_Int(Gen_elt(g,3))!=TRUE)|| (nargs>3)){ POP_LOCS(); return Rerror("Usage: GenSolve(Aset,,Int)",g); } A=Gen_aset(Gen_elt(g,1)); if (nargs>=2 ){ if (r==aset_r(A)) T=Gen_to_Imatrix(Gen_elt(g,2)); else { POP_LOCS(); return Rerror("Usage: GenSolve(Aset,,Int)",g); } } if (nargs==3) seed=Gen_To_Int(Gen_elt(g,3)); else seed=20; time0=set_mark(); Sys=Cayley_continue(A,T,&Sols,seed,tweak); #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"\ntime used %d,\n",read_mark(time0)) #endif ; #ifdef LOG_PRINT xpl_fprint(stdout /* was Pel_Out */,Sols) #endif ; free_Gen_list(g); g=Gen_node_to_List(Link(Gen_from_psys(Sys),Xpl_to_Gen(Sols))); if (T!=0) Imatrix_free(T); psys_free(Sys); POP_LOCS(); return g; } /* ** MSD Command (not working, not tested) */ Gen_node G_MSD(Gen_node g){ aset A=0,CP=0; Ivector T=0; int r; Gen_node ptr; int nargs; LOCS(2); PUSH_LOC(A); PUSH_LOC(CP); nargs=Gen_length(g); if((nargs!=2) || (Can_Be_Aset(Gen_elt(g,1))!=TRUE)|| ((r=Can_Be_Vector(Gen_elt(g,2),Int_T))<0)){ POP_LOCS(); return Rerror("Usage: Ctrig(Aset,)",g); } A=Gen_aset(Gen_elt(g,1)); if (r==aset_r(A)) T=Gen_to_Imatrix(Gen_elt(g,2)); else { POP_LOCS(); return Rerror("Usage: Ctrig(Aset,)",g); } time0=set_mark(); CP=MSD(A,T); #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"\ntime used %d,\n",read_mark(time0)) #endif ; free_Gen_list(g); if (CP!=0){ ptr=(g=Imatrix_to_Gen((Imatrix)Car(Car(CP)))); while((CP=Cdr(CP))!=0) ptr=Gen_set_next(ptr, Imatrix_to_Gen((Imatrix)Car(Car(CP)))); g=Gen_node_to_List(g); } else g=IDND(""); if (T!=0) Imatrix_free(T); POP_LOCS(); return g; } /* ** Qtrig Command (tested) */ Gen_node G_Qtrig(Gen_node g){ aset A=0,CP=0; Ivector T=0; int r = 0; Gen_node ptr; int nargs; LOCS(2); PUSH_LOC(A); PUSH_LOC(CP); nargs=Gen_length(g); if ((nargs ==0) || (nargs==1 && Can_Be_Aset(Gen_elt(g,1))!=TRUE )|| (nargs==2 && (r=Can_Be_Vector(Gen_elt(g,2),Int_T))<0)){ POP_LOCS(); return Rerror("Usage: Qtrig(Aset,)",g); } A=Gen_aset(Gen_elt(g,1)); if (nargs==2 ){ if (r==aset_r(A)) T=Gen_to_Imatrix(Gen_elt(g,2)); else { POP_LOCS(); return Rerror("Usage: Qtrig(Aset,)",g); } } time0=set_mark(); CP=aset_print_subdiv(A,aset_lower_facets(A),T); /* #ifdef LOG_PRINT fprintf(stdout // was Pel_Out ,"\ntime used %d,\n",read_mark(time0)) #endif ; */ /* -- SUSPICIOUS free_Gen_list(g); */ if (CP!=0){ ptr=(g=Imatrix_to_Gen((Imatrix)Car(Car(CP)))); while((CP=Cdr(CP))!=0){ ptr=Gen_set_next(ptr,Imatrix_to_Gen((Imatrix)Car(Car(CP)))); } g=Gen_node_to_List(g); } else g=IDND(""); if (T!=0) Imatrix_free(T); POP_LOCS(); return g; } /* ** Extremal Command (tested) */ Gen_node G_Extremal(Gen_node g){ aset A; if (Gen_length(g)!=1 || Can_Be_Aset(Gen_elt(g,1))!=TRUE) return Rerror("Extremal: Usage Extremal(Ast)",g); A=Gen_aset(g); time0=set_mark(); aset_extremal(A); /* #ifdef LOG_PRINT fprintf(stdout // was Pel_Out ,"\ntime used %d,\n",read_mark(time0)) #endif ; */ return g; } /* ** UnLift Command (tested) */ Gen_node G_UnLift(Gen_node g){ Gen_node ptr; psys M; if (Gen_length(g)==1){ switch (Gen_type(g)){ case Ast_T: aset_unlift(Gen_aset(g)); return g; break; case Ply_T: unliftP(Gen_poly(g)); return g; break; case Sys_T: case Mtx_T: if (Can_Be_Vector(g,Ply_T)>0){ M=Gen_to_psys(g); /* free_Gen_list(g); */ psys_lift(M,0); g=Gen_from_psys(M); psys_free(M); return g; } break; default: if ( Can_Be_List(g)==TRUE ){ ptr=Gen_lval(g); while(ptr!=0){ if (Can_Be_Vector(ptr,Dbl_T)<1){ return Rerror("Usage: Unlift({})",g); } free_Gen_node(*GMref(Gen_Mtx(ptr),1, GMcols(Gen_Mtx(ptr)))); *GMref(Gen_Mtx(ptr),1,GMcols(Gen_Mtx(ptr)))=DBLND(0.0); ptr=Gen_next(ptr); } return g; } else return Rerror("Usage: Unlift(Aset||{})",g); } } return 0; /* not reachable */ } /* ** Randlift Command (tested) */ Gen_node G_RandLift(Gen_node g){ aset A; /* int seed, low, high; if (Gen_length(g)!=4 || Can_Be_Aset(Gen_elt(g,1))!=TRUE|| Can_Be_Int(Gen_elt(g,2))!=TRUE|| Can_Be_Int(Gen_elt(g,3))!=TRUE|| Can_Be_Int(Gen_elt(g,4))!=TRUE) return Rerror("Usage: RandLift(Ast,Int,Int,Int)",g); A=Gen_aset(Gen_elt(g,1)); seed=Gen_To_Int(Gen_elt(g,2)); low=Gen_To_Int(Gen_elt(g,3)); high=Gen_To_Int(Gen_elt(g,4)); aset_randlift(A,seed,low,high); free_Gen_list(Gen_elt(g,2)); return g; */ A=Gen_aset(g); aset_randlift(A,10,0,200); return g; } /* ** Lift Command */ /* ** Face Command */ Gen_node G_Face(Gen_node g){ aset A; int n; Imatrix Norm; if (Gen_length(g)==2 && Can_Be_Aset(Gen_elt(g,1))==TRUE ) { A=Gen_aset(Gen_elt(g,1)); n=Can_Be_Vector(Gen_elt(g,2),Int_T); if (n==aset_dim(A)) { Norm=Gen_to_Imatrix(Gen_elt(g,2)); free_Gen_list(g); g=ASTND(aset_face(A,Norm)); Imatrix_free(Norm); return g; } } return Rerror("Usage: Face(Aset,Norm)",g); } Gen_node G_Save(Gen_node g){ FILE *tmp; if (Gen_length(g)!=1) return Rerror("Print: too many arguments",g); tmp=stdout /* was Pel_Out */; /* stdout // was Pel_Out =Pel_Log; */ #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"\n") #endif ; switch (Gen_type(g)){ case Ast_T: aset_print(Gen_aset(g)); break; default: print_Gen_node(g); } #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"\n") #endif ; /* Pel_Log=tmp; */ free_Gen_list(g); return IDND(""); } /* ** System Command (tested) */ Gen_node G_System(Gen_node g) { int i,order=0; Gmatrix M; /* Gen_node SYSND(); IN gennode.h */ Gen_node T; if (Can_Be_Vector(Gen_elt(g,1),Ply_T)<0){ return Rerror("System: Usage System()",g); } M=Gmatrix_copy(Gen_Mtx(g)); free_Gen_list(g); while (order==0){ order=1; for(i=1;i=2 && Can_Be_Aset(Gen_elt(g,1))!=TRUE && Can_Be_Vector(Gen_elt(g,2),Int_T)<1) || (l==3 && Can_Be_Int(Gen_elt(g,3))!=TRUE) || (l>3)) { return Rerror("Usage: GenPoly(Aset,,[Int]);",g); } A=Gen_aset(Gen_elt(g,1)); I=Gen_to_Imatrix(Gen_elt(g,2)); if (l==3) seed=Gen_To_Int(Gen_elt(g,3)); else seed=3; P=aset_to_psys(A,I,seed); free_Gen_list(g); g=Gen_from_psys(P); psys_free(P); Imatrix_free(I); return g; } /* ** Atype command (tested) */ Gen_node G_AType(Gen_node g){ Ivector I; psys P; if (Gen_length(g)!=1 || Can_Be_Vector(Gen_elt(g,1),Ply_T)<1) { return Rerror("Usage: AType();",g); } P=Gen_to_psys(g); /* free_Gen_list(g); */ I=psys_type(P); g=Imatrix_to_Gen(I); Imatrix_free(I); psys_free(P); return g; } /* ** Continuation Command (tested) */ Gen_node G_Cont(Gen_node g, int tweak){ psys P; node Sl; if ( Gen_length(g)!=2|| Can_Be_Vector(Gen_elt(g,1),Ply_T)<=0|| Can_Be_List(Gen_elt(g,2))!=TRUE) return Rerror("Usage: Cont(PSys,)",g); P=Gen_to_psys(Gen_elt(g,1)); Sl=Gen_to_Dvector_list(Gen_lval(Gen_elt(g,2))); time0=set_mark(); Sl=psys_hom(P,Sl,tweak); /* #ifdef LOG_PRINT fprintf(stdout // was Pel_Out ,"time used %d,\n",read_mark(time0)) #endif ; */ free_Gen_list(g); psys_free(P); return Xpl_to_Gen(Sl); } /* ** Solve Command (tested) */ Gen_node G_Solve(Gen_node g, int tweak){ psys P; node Sl=0,Nl=0; /* char *tmp; UNUSED */ LOCS(2); PUSH_LOC(Sl); PUSH_LOC(Nl); if ( Gen_length(g)!=2|| Can_Be_Vector(Gen_elt(g,1),Ply_T)<=0|| Can_Be_List(Gen_elt(g,2))!=TRUE) return Rerror("Usage: Solve(PSys,{})",g); P=Gen_to_psys(Gen_elt(g,1)); Nl=Gen_to_Ivector_list(Gen_lval(Gen_elt(g,2))); time0=set_mark(); while (Nl!=0){ Sl=list_cat(psys_solve(P,(Imatrix)Car(Car(Nl)),tweak),Sl); Nl=Cdr(Nl); } /* Pel_New_Log(strcat(FilePrefix,".start")); */ #ifdef G_SOLVE_PRINT fprintf(stdout /* was Pel_Log */,"%% Pelican Output File: Generic System and Solutions\n"); fprintf(stdout /* was Pel_Log */,"G="); psys_fprint(stdout /* was Pel_Log */,P); fprintf(stdout /* was Pel_Log */,";\n"); fprintf(stdout /* was Pel_Log */,"S=\n"); xpl_fprint(stdout /* was Pel_Log */,Sl); /* Pel_Open_Log(Pel_LogName); */ #endif ; /* SUSPICIOUS free_Gen_list(g); */ psys_free(P); POP_LOCS(); return Xpl_to_Gen(Sl); } /* ** ParamSet Command (tested) */ Gen_node G_ParamSet(Gen_node g){ Gen_node ptr; if (g==0) return Rerror("NULL Arg in SetParam",g); ptr=g; while (ptr!=0){ if (ptr->type!=Idf_T) return Rerror("Expecting Identifier in SetParam",g); SET_D_PARAM(Hom_tol) /* SET_I_PARAM(Hom_use_proj) */ SET_D_PARAM(PN_dt0) SET_D_PARAM(PN_maxdt) SET_D_PARAM(PN_mindt) SET_D_PARAM(PN_scaledt) SET_D_PARAM(PN_cfac) SET_D_PARAM(PN_NYtol) SET_D_PARAM(PN_NDtol) SET_D_PARAM(PN_Nratio) SET_D_PARAM(PN_tfinal) SET_D_PARAM(PN_FYtol) SET_D_PARAM(PN_FDtol) SET_D_PARAM(PN_Fratio) SET_D_PARAM(PN_Nratio) SET_I_PARAM(PN_maxsteps) SET_B_PARAM(Show_Sys) SET_B_PARAM(Show_Xpl) SET_S_PARAM(FilePrefix) else if (strcmp(ptr->Genval.idval,"Use_Hompack")==0){ Cont_Alg=USE_HOMPACK; ptr=ptr->next; } else if (strcmp(ptr->Genval.idval,"Use_PNewton")==0){ Cont_Alg=USE_PNEWTON; ptr=ptr->next; } else return Rerror("Unrecognized Parameter",g); } free_Gen_list(g); return IDND(""); } #undef SET_D_PARAM #undef SET_I_PARAM #undef SET_B_PARAM /* ** ParamShow Command */ #define SHOW_PARAM(Svar,T)\ else if (strcmp(ptr->Genval.idval,#Svar)==0)\ fprintf(stdout /* was Pel_Out */,#Svar T,Svar); #define SHOW_I_PARAM(Svar) SHOW_PARAM(Svar,"=%d") #define SHOW_D_PARAM(Svar) SHOW_PARAM(Svar,"=%g") #define SHOW_S_PARAM(Svar) SHOW_PARAM(Svar,"=%s") #define SHOW_B_PARAM(Svar)\ else if (strcmp(ptr->Genval.idval,#Svar)==0){\ if (Svar==TRUE) fprintf(stdout /* was Pel_Out */,#Svar "=TRUE");\ else fprintf(stdout /* was Pel_Out */,#Svar "=FALSE");\ } #define DIS_PARAM(Svar,T) fprintf(stdout /* was Pel_Out */,#Svar T,Svar); Gen_node G_ParamShow(Gen_node g){ Gen_node ptr; if (g==0) return Rerror("NULL Arg in ShowParam",g); ptr=g; while (ptr!=0){ if (ptr->type!=Idf_T) return Rerror("Expecting Identifier ShowParam",g); SHOW_D_PARAM(Hom_tol) SHOW_D_PARAM(PN_dt0) SHOW_D_PARAM(PN_maxdt) SHOW_D_PARAM(PN_mindt) SHOW_D_PARAM(PN_scaledt) SHOW_D_PARAM(PN_cfac) SHOW_D_PARAM(PN_tfinal) SHOW_D_PARAM(PN_NYtol) SHOW_D_PARAM(PN_NDtol) SHOW_D_PARAM(PN_Nratio) SHOW_D_PARAM(PN_FYtol) SHOW_D_PARAM(PN_FDtol) SHOW_D_PARAM(PN_Fratio) SHOW_I_PARAM(PN_maxsteps) SHOW_B_PARAM(Show_Sys) SHOW_B_PARAM(Show_Xpl) SHOW_S_PARAM(FilePrefix) /* SHOW_I_PARAM(Hom_use_proj) */ else if (strcmp(ptr->Genval.idval,"Cont_Alg")==0){ if (Cont_Alg==USE_HOMPACK) #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"Using Hompack") #endif ; else if (Cont_Alg==USE_PNEWTON) #ifdef LOG_PRINT fprintf(stdout /* was Pel_Out */,"Using PNewton") #endif ; } else if (strcmp(ptr->Genval.idval,"Hom_Params")==0) print_Hom_params(stdout /* was Pel_Out */); else if (strcmp(ptr->Genval.idval,"PN_Params")==0){ DIS_PARAM(PN_dt0,"= %g, ") DIS_PARAM(PN_scaledt,"=%g, \n") DIS_PARAM(PN_maxdt,"= %g, ") DIS_PARAM(PN_mindt,"= %g\n") DIS_PARAM(PN_cfac, "= %g, ") DIS_PARAM(PN_tfinal," = %g, ") DIS_PARAM(PN_maxsteps,"=%d\n") DIS_PARAM(PN_NYtol,"= %g, ") DIS_PARAM(PN_NDtol,"= %g, ") DIS_PARAM(PN_Nratio,"= %g\n") DIS_PARAM(PN_FYtol,"= %g, ") DIS_PARAM(PN_FDtol,"= %g, ") DIS_PARAM(PN_Fratio,"= %g\n") } else return Rerror("Unrecognized Parameter",g); ptr=ptr->next; } free_Gen_list(g); return IDND(""); } #undef SHOW_PARAM #undef SHOW_I_PARAM #undef SHOW_D_PARAM #undef SHOW_B_PARAM #undef DIS_PARAM /* ** NormSub Command (tested) */ Gen_node G_NormSub(Gen_node g){ psys P; Imatrix Nrm; if (Gen_length(g)!=2 || (Can_Be_Vector(Gen_elt(g,1),Ply_T)<=0)|| (Can_Be_Vector(Gen_elt(g,2),Int_T)<=0)) return Rerror("Usage: NormSub(,)",g); P=Gen_to_psys(Gen_elt(g,1)); Nrm=Gen_to_Imatrix(Gen_elt(g,2)); P=psys_norm_sub(P,Nrm); free_Gen_list(g); g=Gen_from_psys(P); psys_free(P); Imatrix_free(Nrm); return g; } /* ** Lead Command (tested) */ Gen_node G_Lead(Gen_node g){ psys PS1,PS2; if (Gen_length(g)!=1 || (Can_Be_Vector(Gen_elt(g,1),Ply_T)<=0)) return Rerror("Usage: Lead()",g); PS1=Gen_to_psys(g); free_Gen_list(g); PS2=psys_lead(PS1); g=Gen_from_psys(PS2); psys_free(PS2); psys_free(PS1); return g; } /* ** Verify Command (tested) */ Gen_node G_Verify(Gen_node g){ Gen_node ptr,res,ptc; psys PS; Dmatrix D; if (Gen_length(g)!=2|| Can_Be_Vector(Gen_elt(g,1),Ply_T)<0|| Can_Be_List(Gen_elt(g,2))!=TRUE) return Rerror("Usage: Verify(,{}",g); PS=Gen_to_psys(Gen_elt(g,1)); ptr=Gen_lval(Gen_elt(g,2)); ptc=(res=gen_node()); while(ptr!=0){ if (Can_Be_Vector(ptr,Dbl_T)==2*N+3){ D=Gen_to_Dmatrix(ptr); Gen_set_next(ptc,Dbl_To_Gen(psys_abs(PS,D))); ptc=Gen_next(ptc); Dmatrix_free(D); } ptr=Gen_next(ptr); } psys_free(PS); /* free_Gen_list(g); */ g=Gen_node_to_List(Gen_next(res)); free_Gen_node(res); return g; } /* ** Eval Command */ Gen_node G_Eval(Gen_node g){ Gen_node ptr,res,ptc; psys PS; Dmatrix X=0,Y=0; Gmatrix V=0; int i,xp; if (Gen_length(g)!=2|| Can_Be_Vector(Gen_elt(g,1),Ply_T)<0|| ( ((xp=Can_Be_Xpnt(Gen_elt(g,2)))==FALSE) && (Can_Be_List_Of(Gen_elt(g,2),*Can_Be_Xpnt)==FALSE))) return Rerror("Usage: Eval(,{}",g); PS=Gen_to_psys(Gen_elt(g,1)); if (xp==TRUE) ptr=Gen_elt(g,2); else ptr=Gen_lval(Gen_elt(g,2)); ptc=(res=gen_node()); while(ptr!=0){ if (Can_Be_Vector(ptr,Dbl_T)==2*N+3){ X=Gen_to_Dmatrix(ptr); V=Gmatrix_new(1,N); Y= psys_eval(PS,X,Y); for(i=1;i<=N;i++){ *GMref(V,1,i)=Cpx_To_Gen(Complex(DVref(Y,2*i-1),DVref(Y,2*i))); } Gen_set_next(ptc,GMND(V)); ptc=Gen_next(ptc); Dmatrix_free(X); } ptr=Gen_next(ptr); } psys_free(PS); free_Gen_list(g); Dmatrix_free(Y); if (xp==TRUE) g=Gen_next(res); else g=Gen_node_to_List(Gen_next(res)); free_Gen_node(res); return g; } /* ** BinSolve Command: (tested) */ Gen_node G_BinSolve(Gen_node g){ psys P; node Sl; if ( Gen_length(g)!=1|| Can_Be_Vector(Gen_elt(g,1),Ply_T)<=0) return Rerror("Usage: BinSolve()",g); P=Gen_to_psys(Gen_elt(g,1)); time0=set_mark(); Sl=psys_binsolve(P); free_Gen_list(g); psys_free(P); return Xpl_to_Gen(Sl); } /* ** Scale Command (tested) */ Gen_node G_Scale(Gen_node g){ psys PS; Dmatrix S; int l; if ( ((l=Gen_length(g))<1)|| ((l>=1)&&(Can_Be_Vector(Gen_elt(g,1),Ply_T)<=0))|| ((l>=2)&&(Gen_type(Gen_elt(g,2))!=Idf_T))|| (l>2)) return Rerror("Usage: Scale(,[Idf])",g); PS=Gen_to_psys(g); S=psys_scale(PS); if (l==2) install(Gen_idval(Gen_elt(g,2)),Dmatrix_to_Gen(S)); /* free_Gen_list(g); */ g=Gen_from_psys(PS); Dmatrix_free(S); psys_free(PS); return g; } /* ** UnScale Command (tested) */ Gen_node G_UnScale(Gen_node g){ Gen_node ptr, res,rptr; Dmatrix scl; Dmatrix root = NULL; /* Initialized to get rid of C++ warning */ if (g==0 || Gen_length(g)!=2 || Can_Be_Vector(Gen_elt(g,2),Dbl_T)!=N || Can_Be_List(g)!=TRUE) return Rerror("Usage: UnScale({},)version 1",g); rptr=(res=gen_node()); ptr=Gen_lval(g); scl=Gen_to_Dmatrix(Gen_elt(g,2)); while(ptr!=0){ if (Can_Be_Vector(ptr,Dbl_T)!=2*N+3){ Dmatrix_free(scl); free_Gen_list(Gen_next(res)); free_Gen_node(res); return Rerror("Usage: UnScale({},) version 2",g); } root=Gen_to_Dmatrix(ptr); xpnt_unscale(root,scl); Gen_set_next(rptr,Dmatrix_to_Gen(root)); rptr=Gen_next(rptr); ptr=Gen_next(ptr); } /* free_Gen_list(g); */ g=XPLND(Gen_next(res)); free_Gen_node(res); Dmatrix_free(scl); Dmatrix_free(root); return g; } /* ** ScaleXPL Command (tested) */ Gen_node G_ScaleXPL(Gen_node g){ Gen_node ptr, res,rptr; Dmatrix scl; Dmatrix root = NULL; /* Initialized to get rid of C++ warning. */ int i; if (g==0 || Gen_length(g)!=2 || Can_Be_Vector(Gen_elt(g,2),Dbl_T)!=N || Can_Be_List(g)!=TRUE) return Rerror("Usage: XScale({},)",g); rptr=(res=gen_node()); ptr=Gen_lval(g); scl=Gen_to_Dmatrix(Gen_elt(g,2)); while(ptr!=0){ if (Can_Be_Vector(ptr,Dbl_T)!=2*N+3){ Dmatrix_free(scl); free_Gen_list(Gen_next(res)); free_Gen_node(res); return Rerror("Usage: UnScale({},)",g); } for(i=1;i<=N;i++){ if (DVref(scl,i)!=0.0) DVref(scl,i)=1.0/DVref(scl,i);} root=Gen_to_Dmatrix(ptr); xpnt_unscale(root,scl); Gen_set_next(rptr,Dmatrix_to_Gen(root)); rptr=Gen_next(rptr); ptr=Gen_next(ptr); } /* free_Gen_list(g); */ g=XPLND(Gen_next(res)); free_Gen_node(res); Dmatrix_free(scl); Dmatrix_free(root); return g; } /* ** Affine Command */ Gen_node G_Affine(Gen_node g){ Gen_node ptr, res,rptr; Dmatrix root; if (g==0 || Gen_length(g)!=1 || Can_Be_List(g)!=TRUE) return Rerror("Usage: Affine({})",g); rptr=(res=gen_node()); ptr=Gen_lval(g); while(ptr!=0){ if (Can_Be_Vector(ptr,Dbl_T)!=2*N+3){ free_Gen_list(Gen_next(res)); free_Gen_node(res); return Rerror("Usage: Affine({})",g); } root=Gen_to_Dmatrix(ptr); xpnt_affine(root); Gen_set_next(rptr,Dmatrix_to_Gen(root)); rptr=Gen_next(rptr); ptr=Gen_next(ptr); } /* free_Gen_list(g); */ g=XPLND(Gen_next(res)); free_Gen_node(res); return g; } /* ** Normalize Command */ Gen_node G_Normalize(Gen_node g){ Gen_node ptr, res,rptr; Dmatrix root; if (g==0 || Gen_length(g)!=1 || Can_Be_List(g)!=TRUE) return Rerror("Usage: Normalize({})",g); rptr=(res=gen_node()); ptr=Gen_lval(g); while(ptr!=0){ if (Can_Be_Vector(ptr,Dbl_T)!=2*N+3){ free_Gen_list(Gen_next(res)); free_Gen_node(res); return Rerror("Usage: Normalize({})",g); } root=Gen_to_Dmatrix(ptr); xpnt_normalize(root); Gen_set_next(rptr,Dmatrix_to_Gen(root)); rptr=Gen_next(rptr); ptr=Gen_next(ptr); } free_Gen_list(g); g=Gen_node_to_List(Gen_next(res)); free_Gen_node(res); return g; } /* ** Set_T Command (tested) */ Gen_node G_Set_T(Gen_node g){ Gen_node ptr; double t0; if ( Gen_length(g)!=2|| Can_Be_List(Gen_elt(g,1))!=TRUE || Can_Be_Number(Gen_elt(g,2),Dbl_T)==FALSE) return Rerror("Usage: SetT({},Dbl)",g); ptr=Gen_lval(Gen_elt(g,1)); t0=Gen_To_Dbl(Gen_elt(g,2)); free_Gen_list(Gen_next(g)); while(ptr!=0){ if (Can_Be_Vector(ptr,Dbl_T)<1){ return Rerror("Usage: SetT({},Dbl)",g); } free_Gen_node(*GMref(Gen_Mtx(ptr),1,GMcols(Gen_Mtx(ptr)))); *GMref(Gen_Mtx(ptr),1,GMcols(Gen_Mtx(ptr)))=DBLND(t0); ptr=Gen_next(ptr); } return g; } Gen_node G_Re(Gen_node g){ fcomplex c; if ( Gen_length(g)!=1|| Can_Be_Cpx(Gen_elt(g,1))!=TRUE) return Rerror("Usage: Re(Cpx)",g); c=Gen_To_Cpx(g); free_Gen_list(g); return DBLND(Real(c)); } Gen_node G_Im(Gen_node g){ fcomplex c; if ( Gen_length(g)!=1|| Can_Be_Cpx(Gen_elt(g,1))!=TRUE) return Rerror("Usage: Re(Cpx)",g); c=Gen_To_Cpx(g); free_Gen_list(g); return DBLND(Imag(c)); } gambit-0.2010.09.01/src/tools/enumpoly/pelprgen.h0000644000076500007650000001725311350032206016224 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* This is a header file derived from the file below due to Huber. It was created by transporting all normal header information from that file to here. */ /* ** Proc_Gen.c ** Commands defining Pelican functions ** ** copyright (c) 1995 Birk Huber */ #include "pelclhpk.h" #include "pelclqhl.h" #include "pelpscon.h" #include "peleval.h" #include "pelgennd.h" #include "pelclyal.h" /* node MSD(aset Ast, Ivector T); IN pelutils.h */ Gen_node G_Re(Gen_node g); Gen_node G_Im(Gen_node g); Gen_node G_Help(Gen_node g); /* Gen_node G_Print(Gen_node g); IN gennode.h */ Gen_node G_Save(Gen_node g); Gen_node G_Aset(Gen_node g); Gen_node G_Ctrig(Gen_node g); Gen_node G_Qtrig(Gen_node g); Gen_node G_MSD(Gen_node g); Gen_node G_Extremal(Gen_node g); Gen_node G_RandLift(Gen_node g); Gen_node G_UnLift(Gen_node g); Gen_node G_Set_T(Gen_node g); Gen_node G_Face(Gen_node g); Gen_node G_System(Gen_node g); Gen_node G_Gen_Poly(Gen_node g); Gen_node G_AType(Gen_node g); Gen_node G_Cont(Gen_node g, int tweak); Gen_node G_BinSolve(Gen_node g); Gen_node G_NormSub(Gen_node g); Gen_node G_Lead(Gen_node g); Gen_node G_Solve(Gen_node g, int tweak); Gen_node G_GenSolve(Gen_node g, int tweak); Gen_node G_Verify(Gen_node g); Gen_node G_Eval(Gen_node g); Gen_node G_ParamSet(Gen_node g); Gen_node G_ParamShow(Gen_node g); Gen_node G_Scale(Gen_node g); Gen_node G_UnScale(Gen_node g); Gen_node G_ScaleXPL(Gen_node g); Gen_node G_Affine(Gen_node g); Gen_node G_Normalize(Gen_node g); /* -------------------------------------------------------------- Install_Command(Gen_node (*G)(),char *s) takes a pointer to a Shell Procedure and a string s, installs the pair on the symbol table-- and returns the value of the resulting symbol table entry. Error Conditions: if either G or S are NULL nothing is done and Null is returned if Gen_node() fails NULL is returned. install will return NULL on some error conditions and this will be passed through lock and returned. --------------------------------------------------------------*/ /* Sym_ent Install_Command(Gen_node (*G)(),char *s); */ /*----------------------------------------------------------------- int Install_Gen_Commands() Uses Install_Command to install all Commands On the symbol table. Always returns 1; Error Conditions: None; -----------------------------------------------------------------*/ /* int Install_Gen_Commands(); */ /******************************************************************** Begin Command Definitions ********************************************************************/ /* ** Help Command: */ Gen_node G_Help(Gen_node g); /* ** Aset Command (tested on poly's) */ /* aset psys_to_aset(psys); IN psys.h */ Gen_node G_Aset(Gen_node g); /* ** Cayley Triangulation Command (tested: looses 2 ) ** (problem probably in cly_triangulate) */ Gen_node G_Ctrig(Gen_node g); /* ** Cayley Triangulation Command (tested: looses 2 ) ** (problem probably in cly_triangulate ) */ Gen_node G_GenSolve(Gen_node g, int tweak); /* ** MSD Command (not working, not tested) */ Gen_node G_MSD(Gen_node g); /* ** Qtrig Command (tested) */ Gen_node G_Qtrig(Gen_node g); /* ** Extremal Command (tested) */ Gen_node G_Extremal(Gen_node g); /* ** UnLift Command (tested) */ Gen_node G_UnLift(Gen_node g); /* ** Randlift Command (tested) */ Gen_node G_RandLift(Gen_node g); /* ** Lift Command (??? - AMM) */ /* ** Face Command */ Gen_node G_Face(Gen_node g); /* ** Print Command */ /* Gen_node G_Print(Gen_node g); IN gennode.h */ Gen_node G_Save(Gen_node g); /* ** System Command (tested) */ Gen_node G_System(Gen_node g); /* ** GenPoly Command (tested) */ psys aset_to_psys(aset,Ivector,int); Gen_node G_Gen_Poly(Gen_node g); /* ** Atype command (tested) */ Gen_node G_AType(Gen_node g); /* ** Continuation Command (tested) */ Gen_node G_Cont(Gen_node g, int tweak); /* ** Solve Command (tested) */ Gen_node G_Solve(Gen_node g, int tweak); /* ** ParamSet Command (tested) */ #define SET_D_PARAM(Svar)\ else if (strcmp(ptr->Genval.idval,#Svar)==0){\ if (ptr->next==0||ptr->next->type!=Dbl_T)\ return Rerror(#Svar "requires a floating point argument",g);\ Svar=ptr->next->Genval.dval;\ ptr=ptr->next->next;\ } #define SET_B_PARAM(Svar)\ else if (strcmp(ptr->Genval.idval,#Svar)==0){\ if (ptr->next==0 || ptr->next->type!=Int_T || \ (ptr->next->Genval.ival!=TRUE && ptr->next->Genval.ival!=FALSE))\ return Rerror(#Svar "requires a TRUE/FALSE argument",g);\ Svar=ptr->next->Genval.ival;\ ptr=ptr->next->next;\ } #define SET_I_PARAM(Svar)\ else if (strcmp(ptr->Genval.idval,#Svar)==0){\ if (ptr->next==0 || ptr->next->type!=Int_T)\ return Rerror(#Svar "requires a floating point argument",g);\ Svar=ptr->next->Genval.ival;\ ptr=ptr->next->next;\ } #define SET_S_PARAM(Svar)\ else if (strcmp(ptr->Genval.idval,#Svar)==0){\ if (ptr->next==0 ||\ ( ptr->next->type!=Str_T && ptr->next->Genval.ival!=Idf_T ))\ return Rerror(#Svar "requires a String argument",g);\ strcpy(Svar,ptr->next->Genval.idval);\ ptr=ptr->next->next;\ } Gen_node G_ParamSet(Gen_node g); /* #undef SET_D_PARAM #undef SET_I_PARAM #undef SET_B_PARAM */ /* ** ParamShow Command */ #define SHOW_PARAM(Svar,T)\ else if (strcmp(ptr->Genval.idval,#Svar)==0)\ fprintf(Pel_Out,#Svar T,Svar); #define SHOW_I_PARAM(Svar) SHOW_PARAM(Svar,"=%d") #define SHOW_D_PARAM(Svar) SHOW_PARAM(Svar,"=%g") #define SHOW_S_PARAM(Svar) SHOW_PARAM(Svar,"=%s") #define SHOW_B_PARAM(Svar)\ else if (strcmp(ptr->Genval.idval,#Svar)==0){\ if (Svar==TRUE) fprintf(Pel_Out,#Svar "=TRUE");\ else fprintf(Pel_Out,#Svar "=FALSE");\ } #define DIS_PARAM(Svar,T) fprintf(Pel_Out,#Svar T,Svar); Gen_node G_ParamShow(Gen_node g); #undef SHOW_PARAM #undef SHOW_I_PARAM #undef SHOW_D_PARAM #undef SHOW_B_PARAM #undef DIS_PARAM /* ** NormSub Command (tested) */ Gen_node G_NormSub(Gen_node g); /* ** Lead Command (tested) */ Gen_node G_Lead(Gen_node g); /* ** Verify Command (tested) */ Gen_node G_Verify(Gen_node g); /* ** Eval Command */ Gen_node G_Eval(Gen_node g); /* ** BinSolve Command: (tested) */ Gen_node G_BinSolve(Gen_node g); /* ** Scale Command (tested) */ Gen_node G_Scale(Gen_node g); /* ** UnScale Command (tested) */ Gen_node G_UnScale(Gen_node g); /* ** ScaleXPL Command (tested) */ Gen_node G_ScaleXPL(Gen_node g); /* ** Affine Command */ Gen_node G_Affine(Gen_node g); /* ** Normalize Command */ Gen_node G_Normalize(Gen_node g); /* ** Set_T Command (tested) */ Gen_node G_Set_T(Gen_node g); Gen_node G_Re(Gen_node g); Gen_node G_Im(Gen_node g); gambit-0.2010.09.01/src/tools/enumpoly/pelproc.cc0000644000076500007650000002601111350032206016202 00000000000000/* ** copyright (c) 1995 Birk Huber */ #include "pelproc.h" Gen_node PROC_ADD(Gen_node g){ Gen_node res,g1,g2; int rt; Gmatrix M=0; polynomial1 tp1,tp2; if (Gen_length(g)!=2) return Rerror("wrong number of arguments to PROC_ADD",g); g1=Gen_elt(g,1); g2=Gen_elt(g,2); rt=Common_Type(Gen_type(g1),Gen_type(g2)); switch(rt){ case Int_T: res=INTND(Gen_To_Int(g1)+Gen_To_Int(g2)); break; case Dbl_T: res=DBLND(Gen_To_Dbl(g1)+Gen_To_Dbl(g2)); break; case Cpx_T: res=CPXND(Cadd(Gen_To_Cpx(g1),Gen_To_Cpx(g2))); break; case Ply_T: tp1=Gen_To_Ply(g1); tp2=Gen_To_Ply(g2); res=PLYND(addPPP(tp1,tp2,0)); freeP(tp1); freeP(tp2); break; case Sys_T: case Mtx_T: if ((Gen_type(g1)==Sys_T || Gen_type(g1)==Mtx_T)&& (Gen_type(g2)==Sys_T || Gen_type(g2)==Mtx_T)) M=Gmatrix_Dop(Gen_Mtx(g1),Gen_Mtx(g2),PROC_ADD); if (M==0) return Rerror("Matrices not compatable",g); if (rt==Sys_T) res=SYSND(M); else res=GMND(M); break; default: res=Rerror("PROC_ADD not defined on its arguments",0); break; } free_Gen_list(g); return(res); } Gen_node PROC_SUB(Gen_node g){ Gen_node res,g1,g2; int rt; polynomial1 tp1,tp2; Gmatrix M=0; if (Gen_length(g)!=2) return Rerror("wrong number of arguments to PROC_SUB",g); g1=Gen_elt(g,1); g2=Gen_elt(g,2); rt=Common_Type(Gen_type(g1),Gen_type(g2)); switch(rt){ case Int_T: res=INTND(Gen_To_Int(g1)-Gen_To_Int(g2)); break; case Dbl_T: res=DBLND(Gen_To_Dbl(g1)-Gen_To_Dbl(g2)); break; case Cpx_T: res=CPXND(Csub(Gen_To_Cpx(g1),Gen_To_Cpx(g2))); break; case Ply_T: tp1=Gen_To_Ply(g1); tp2=Gen_To_Ply(g2); res=PLYND(subPPP(tp1,tp2,0)); freeP(tp1); freeP(tp2); break; case Sys_T: case Mtx_T: if ((Gen_type(g1)==Sys_T || Gen_type(g1)==Mtx_T)&& (Gen_type(g2)==Sys_T || Gen_type(g2)==Mtx_T)) M=Gmatrix_Dop(Gen_Mtx(g1),Gen_Mtx(g2),PROC_SUB); if (M==0) return Rerror("Matrices not compatable",g); if (rt==Sys_T) res=SYSND(M); else res=GMND(M); break; default: res=Rerror("PROC_SUB not defined on its arguments",0); break; } free_Gen_list(g); return(res); } Gen_node PROC_SUBM(Gen_node g){ Gen_node res,g1; Gmatrix M=0; polynomial1 tp1; if (Gen_length(g)!=1) return Rerror("wrong number of arguments to PROC_SUBM",g); g1=Gen_elt(g,1); switch (Gen_type(g1)){ case Int_T: res=INTND(-1*Gen_To_Int(g)); break; case Dbl_T: res=DBLND(-1.0*Gen_To_Dbl(g)); break; case Cpx_T: res=CPXND(RCmul(-1.0,Gen_To_Cpx(g))); break; case Ply_T: tp1=Gen_To_Ply(g); res=PLYND(mulCPP(Complex(-1.0,0.0),tp1,tp1)); break; case Sys_T: case Mtx_T: g1=INTND(-1); M=Gmatrix_Sop(g1,Gen_Mtx(g),PROC_MUL); if (M==0) return Rerror("error in unary minus",g); if (Gen_type(g1)==Sys_T) res=SYSND(M); else res=GMND(M); free_Gen_node(g1); break; default: res=Rerror("PROC_SUB not defined on its arguments",0); break; } free_Gen_list(g); return res; } Gen_node PROC_MUL(Gen_node g){ Gen_node res,g1,g2,scal,mtx; int rt,t1,t2; polynomial1 tp1,tp2; Gmatrix M=0; if (Gen_length(g)!=2) return Rerror("wrong number of arguments to PROC_MUL",g); g1=Gen_elt(g,1); g2=Gen_elt(g,2); rt=Common_Type(t1=Gen_type(g1),t2=Gen_type(g2)); switch(rt){ case Int_T: res=INTND(Gen_To_Int(g1)*Gen_To_Int(g2)); break; case Dbl_T: res=DBLND(Gen_To_Dbl(g1)*Gen_To_Dbl(g2)); break; case Cpx_T: res=CPXND(Cmul(Gen_To_Cpx(g1),Gen_To_Cpx(g2))); break; case Ply_T: tp1=Gen_To_Ply(g1); tp2=Gen_To_Ply(g2); res=PLYND(mulPPP(tp1,tp2,0)); freeP(tp1); freeP(tp2); break; case Sys_T: case Mtx_T:if (t1==t2){ M=Gmatrix_Mop(Gen_Mtx(g1),Gen_Mtx(g2), (res=INTND(0)),PROC_ADD,PROC_MUL); free_Gen_node(res); if (M==0) res= Rerror("Incompatible matrices in MUll",0); if (rt==Sys_T) res=SYSND(M); else res=GMND(M); } else { if (t1!=Mtx_T){ scal=copy_Gen_node(g1); mtx=g2; } else { scal=copy_Gen_node(g2); mtx=g1; } M=Gmatrix_Sop(scal,Gen_Mtx(mtx),PROC_MUL); free_Gen_node(scal); if (M==0) res =Rerror("Incompatible matrices in Mull",0); if (rt==Sys_T) res=SYSND(M); else res=GMND(M); } break; default: res=Rerror("PROC_MUL not defined on its arguments",0); break; } free_Gen_list(g); return(res); } Gen_node PROC_DIV(Gen_node g){ Gen_node res,g1,g2; int rt; polynomial1 tp1,tp2; Gmatrix M=0; if (Gen_length(g)!=2) return Rerror("wrong number of arguments to PROC_DIV",g); g1=Gen_elt(g,1); g2=Gen_elt(g,2); rt=Common_Type(Gen_type(g1),Gen_type(g2)); /* should test for zero */ switch(rt){ case Int_T: case Dbl_T: res=DBLND(Gen_To_Dbl(g1)/Gen_To_Dbl(g2)); break; case Cpx_T: res=CPXND(Cdiv(Gen_To_Cpx(g1),Gen_To_Cpx(g2))); break; case Ply_T: tp1=Gen_To_Ply(g1); tp2=Gen_To_Ply(g2); /* should make sure tp2 is a monomial*/ res=PLYND(divMPP(tp2,tp1,0)); freeP(tp1); freeP(tp2); break; case Sys_T: case Mtx_T: if(Gen_type(g2)!=Mtx_T){ res=PROC_DIV(Link(INTND(1),copy_Gen_node(g2))); M=Gmatrix_Sop(res,Gen_Mtx(g1),PROC_MUL); free_Gen_node(res); if (rt==Sys_T) res=SYSND(M); res=GMND(M); } else res=Rerror("PROC_DIV cannot divide matrices",0); break; default: res=Rerror("PROC_DIV not defined on its arguments",0); break; } free_Gen_list(g); return(res); } Gen_node PROC_EXP(Gen_node g) { Gen_node res,g1,g2; int i,ex,ri,ti; double rd,td; polynomial1 tp1,tp2; if ( g==0 || g->next==0 || g->next->next !=0) return Rerror("wrong number of arguments to PROC_EXP",g); if (Gen_length(g)!=2) return Rerror("wrong number of arguments to PROC_DIV",g); g1=Gen_elt(g,1); g2=Gen_elt(g,2); if (Can_Be_Int(g2)==TRUE){ ex=Gen_To_Int(g2); if (Can_Be_Int(g1)==TRUE){ if (ex>=0){ ri=(ti=Gen_To_Int(g1)); for(i=2;i<=ex;i++) ri*=ti; res=Int_To_Gen(ri); } else res=Dbl_To_Gen(pow(Gen_To_Dbl(g1),Gen_To_Dbl(g2))); } else if (Can_Be_Dbl(g1)==TRUE){ rd=(td=Gen_To_Dbl(g1)); for(i=2;i<=ex;i++) rd*=td; res=Dbl_To_Gen(rd); } else if (Can_Be_Cpx(g1)==TRUE){ res=Cpx_To_Gen(Cpow(Gen_To_Cpx(g1),ex)); } else if (Can_Be_Poly(g1)==TRUE){ if (ex<0) res=Rerror("can not divide polynomial1s",0); else { tp1=Gen_To_Ply(g1); tp2=expIPP(ex,tp1,0); res=Ply_To_Gen(tp2); freeP(tp2); freeP(tp1); } } else res=Rerror("Exp not defined on its arguments",0); } else if (Can_Be_Dbl(g2)==TRUE && Can_Be_Dbl(g1)==TRUE){ res=Dbl_To_Gen(pow(Gen_To_Dbl(g1),Gen_To_Dbl(g2))); } else res=Rerror("Exp not defined on its arguments",0); free_Gen_list(g); return(res); } Gen_node PROC_SET(Gen_node g) { Gen_node res,g1,g2; Sym_ent ent; if (Gen_length(g)!=2) return Rerror("wrong number of argument to PROC_SET",g); g1=Gen_elt(g,1); g2=Gen_elt(g,2); if ( Gen_type(g2) == Err_T) { free_Gen_node(g1); g1=IDND("ANS"); } switch(Gen_type(g1)){ case Idf_T: ent=Slookup(Gen_idval(g1)); if (ent!=0){ if (locked(ent)!=0) return Rerror("can not reset reserved word",g); free_Gen_list(ent->def); ent->def=g2; } else ent=install(Gen_idval(g1),g2); free_Gen_node(g1); res=ent->def; break; default: res=Rerror("first arg to PROC_SET must be itentifyer",g); break; } return res; } Gen_node PROC_EXIT(Gen_node g) { empty_symbol_table(); if(Def_Ring!=0) free_Pring(Def_Ring); node_free_store(); exit(0); return g; } Gen_node Set_Ring(Gen_node g) { Pring R; polynomial1 tp; int n=0; Gen_node pt,pt1; pt=g; while(pt!=0) { n++; pt=Gen_next(pt); } R=makePR(n-1); n=0; pt=g; while(nGenval.idval,pt1); ring_set_var(R,n,Gen_idval(pt)); n++; pt=Gen_next(pt); } tp=makeP(R); *poly_coef(tp)=Complex(1.0,0.0); *poly_def(tp)=1; pt1=PLYND(tp); install(pt->Genval.idval,pt1); ring_set_def(R,Gen_idval(pt)); free_Gen_list(g); Def_Ring=R; N=ring_dim(R); return IDND("You have tried to print the Gen_node containing the Default Ring"); } Gen_node PROC_LUP(Gen_node g) { Sym_ent nd; Gen_node res,g1; if (Gen_length(g)!=1||Gen_type(g1=Gen_elt(g,1))!=Idf_T) return Rerror("null or non identifier passed to PROC_LUP",g); nd=Slookup(Gen_idval(g)); if ( nd == 0 ) return g; free_Gen_node(g); res=copy_Gen_list(nd->def); return res; } Gen_node PROC_LAC(Gen_node g) { Gen_node res,g1; int targ; if (Gen_length(g)!=2 || Can_Be_List(Gen_elt(g,1))!=TRUE || Gen_type(Gen_elt(g,2))!=Int_T) return Rerror("PROC_LAC wrong number of arguments",g); g1=Gen_lval(Gen_elt(g,1)); targ=Gen_To_Int(Gen_elt(g,2)); if (targ<1||targ>Gen_length(g1) ) return Rerror("too few elements in list",g); res=copy_Gen_node(Gen_elt(g1,targ)); free_Gen_list(g); return res; } Gen_node PROC_MAC(Gen_node g) { Gmatrix M; Gen_node g1,g2,g3,res; int r,c; if ((Gen_length(g)!=3)|| ((Gen_type(g1=Gen_elt(g,1))!=Mtx_T)&&(Gen_type(g1)!=Sys_T))|| (Gen_type(g2=Gen_elt(g,2))!=Int_T)|| (Gen_type(g3=Gen_elt(g,3))!=Int_T)) return Rerror("bad args PROC_MAC",g); M=Gen_Mtx(g1); r=Gen_To_Int(g2); c=Gen_To_Int(g3); if (1>r || GMrows(M)c || GMcols(M)=1;j--){ ctmp=Cmul(Croot(CV_Read(Sol,row,j),S(j,j)), RootOfOne(Idx(j),S(j,j))); CV_Set(Sol,row,j,ctmp.r,ctmp.i) for(i=j-1;i>=1;i--){ ctmp=Cmul(CV_Read(Sol,row,i), Cpow(CV_Read(Sol,row,j),-1*(S(i,j)))); CV_Set(Sol,row,i,ctmp.r,ctmp.i) } } cid=n; while(cid<=n && cid >=1){ if (Idx(cid) final tol ** sugested strategy seemed to prevent actual completion. ** 2:(planned) try using a history mechanism so that some number ** of consecutive good steps are required before increasing ** dt. (it seems we take a lot of bad steps) ** 3:(planned)use an estimate on the condition number to decide ** when to abort a path which is becomming singular. ** 4:(possible) put some mechanism to stop infinite loops in ** the Newton iteration. ** 4:(possible) put in a mechanism to detect and abort paths ** going to infinity. *****************************************************************/ /* NOW REDUNDANT #include #include "psys.h" */ /* ** Controll Parameters ** ** PN_dt0 initial stepsize ** PN_maxdt maximum stepsize ** PN_mindt minimum stepsize ** PN_scaledt scaling factor for step size ** PN_cfac initial contraction required for approx root ** PN_NYtol Stop Newton when |F(X)|=1; i--){ \ DX(i)=0.0;\ for(j=N;j>i;j--){DX(i)=DX(i)+R(i,j)*DX(j);}\ DX(i)=(QY(i)-DX(i))/(R(i,i));\ } double norm(Dvector X){ int i; double abs=0.0,tmp; for(i=1;i<=DVlength(X);i++){ tmp=X(i); abs+=(tmp*tmp); } return sqrt(abs); } double BGQR(Dmatrix A,Ivector Basis,int N,Dmatrix Q,Dmatrix R){ int i,j,k; double s,s1,s2,t1,t2, max_e=-1,min_e=-1; for (i=1;i<=N;i++){ for (j=1;j<=N;j++) { Q(i,j)=0.0; R(i,j)=A(i,Basis(j)); } Q(i,i)=1.0; } for(i=1;i<=N-1;i++){ for(k=i+1;k<=N;k++){ if (R(k,i)>Zero_Tol || R(k,i)<-Zero_Tol){ s2=R(k,i); s1=R(i,i); s=sqrt(s1*s1+s2*s2); s1=s1/s; s2=s2/s; for(j=1;j<=N;j++){ t1= s1*R(i,j)+s2*R(k,j); t2=-s2*R(i,j)+s1*R(k,j); R(i,j)=t1; R(k,j)=t2; t1= s1*Q(i,j)+s2*Q(k,j); t2=-s2*Q(i,j)+s1*Q(k,j); Q(i,j)=t1; Q(k,j)=t2; } } } s1=fabs(R(i,i)); if (s1>max_e||max_e<0) max_e=s1; else if(s1 PN_tfinal) dt=1-X(T); /* ** Choose Basis: ** A) Find complex coordinate with largest norm */ max_c = X(Z(1))*X(Z(1))+X(Z(2))*X(Z(2)); max_idx=0; for(i=1;i<=N;i=i+2){ new_c=X(Basis(i))*X(Basis(i))+X(Basis(i+1))*X(Basis(i+1)); if (new_c>max_c){ max_c=new_c; max_idx=i; } } /* ** B) If largest coord is not allready homog param make it so. */ if (max_idx>0){ tmp=Basis(max_idx); Basis(max_idx)=Z(1); Z(1)=tmp; tmp=Basis(max_idx+1); Basis(max_idx+1)=Z(2); Z(2)=tmp; } /* ** Store Current Solution: (To allow reset if step is rejected) */ for (i=1;i<=T;i++) XOld(i)=X(i); /* ** Predictor: Euler predictor step ** A) Solve system JC(:,Basis)DX=-JC(:,T) */ JC=psys_jac(P,X,JC); cond_num=BGQR(JC,Basis,N,QT,R); /* ** Form RHS */ for(i=1;i<=N;i++){ QY(i)=0.0; for(j=1;j<=N;j++){ QY(i)=QY(i)-QT(i,j)*JC(j,T); } } /* ** Backsolve */ Backsolve(R,QY,DX,i,j) /* ** B) incriment X(T), and X(Basis). */ X(T)=X(T)+dt; for(i=1;i<=N;i++) X(Basis(i))=X(Basis(i))+dt*DX(i); /* Corrector First Step */ Y=psys_eval(P,X,Y); Nold=norm(Y); JC=psys_jac(P,X,JC); cond_num=BGQR(JC,Basis,N,QT,R); /* form RHS: */ for(i=1;i<=N;i++){ QY(i)=0; for(j=1;j<=N;j++){ QY(i)=QY(i)-QT(i,j)*Y(j); } } /* Back solve */ Backsolve(R,QY,DX,i,j) /* update */ for(i=1; i<=N;i++) X(Basis(i))=X(Basis(i))+DX(i); Y=psys_eval(P,X,Y); Nnew=norm(Y); /*Decide if performance is o.k.*/ if (Nnew>(Nold/PN_cfac)&&(Nnew>PN_NYtol)){ /*if performance is not o.k. decrease step size and try again*/ if (dt>PN_mindt){ dt=dt/PN_scaledt; for(i=1;i<=T;i++)X(i)=XOld(i); } else { fprintf(stdout /* was psys_logfile */,"Minimum Step size reached\n"); printf("Minimum Step size reached\n"); Rval=1; goto cleanup; } fprintf(stdout /* was psys_logfile */,"Stp=%d, T=%g, dt=%g\n", tsteps,X(T),dt); } else{ /* ** if performance is o.k. run Corrector loop ** (Maybe a good idea to limit number of Newton Steps) */ Ndx=norm(DX); while (Nnew>PN_NYtol && Ndx>PN_NDtol && Ndx/Nnew > PN_Nratio){ JC=psys_jac(P,X,JC); cond_num=BGQR(JC,Basis,N,QT,R); /* form RHS*/ for(i=1;i<=N;i++){ QY(i)=0; for(j=1;j<=N;j++) QY(i)=QY(i)-QT(i,j)*Y(j); } Backsolve(R,QY,DX,i,j) for (i=1;i<=N;i++) X(Basis(i))=X(Basis(i))+DX(i); Y=psys_eval(P,X,Y); Nnew=norm(Y); Ndx=norm(DX); } /*add size of current step to arclenth approx*/ arcstep=0.0; for(i=1;i<=T;i++) arcstep+=pow(X(i)-XOld(i),(long)2); arclen=arclen+sqrt(arcstep); /* increase step size if allowed*/ if (dt PN_maxsteps){ printf(" too many steps taken\n"); Rval=1; goto cleanup; } /* RUN NEWTON's METHOD TO FINAL TOLERANCE (IF DESIRED).*/ X(T)=1.0; Y=psys_eval(P,X,Y); Nnew=norm(Y); if (Nnew>PN_FYtol){ fprintf(stdout /* was psys_logfile */, "Starting final Newton iteration: T=%g,Y=%g\n",X(T),Nnew); do { JC=psys_jac(P,X,JC); cond_num=BGQR(JC,Basis,N,QT,R); /* form RHS: */ for(i=1;i<=N;i++){ QY(i)=0; for(j=1;j<=N;j++) QY(i)=QY(i)-QT(i,j)*Y(j); } Backsolve(R,QY,DX,i,j) for(i=1;i<=N;i++) X(Basis(i))=X(Basis(i))+DX(i); Y=psys_eval(P,X,Y); Nnew=norm(Y); Ndx=norm(DX); fprintf(stdout /* was psys_logfile */, " Y=%g, Ndx=%g, Ndx/Y=%g cond=%g\n",Nnew,Ndx,Ndx/Nnew,cond_num); }while (Nnew>PN_FYtol && Ndx >PN_FDtol && Ndx/Nnew > PN_Fratio); } cleanup: printf("Stp=%d, T=%g,Y=%g, arclen=%f, FLAG=%d\n", tsteps,X(T),Nnew,arclen,Rval); Ivector_free(Z); Ivector_free(Basis); Dvector_free(XOld); Dvector_free(DX); Dvector_free(Y); Dvector_free(QY); Dmatrix_free(JC); Dmatrix_free(QT); Dmatrix_free(R); return Rval;} /* end psys_cont.c */ /**************************************************************************/ /******************* implementation code from psys_def.c ******************/ /**************************************************************************/ /* ** Psys class definition. ** - square system of equations, listed by blocks */ struct psys_t{ int N; /* number of variables */ int Neq; /* number of equations -- usually Neq==N*/ int R; /* number of different support sets */ int Mmax; /* Max number of Monomials allowed */ int M; /* total number of monomials used */ int *estart; int *bstart; int *degrees; int *tops; /* a vector of info desribing system */ int *istore; /* an Mx(N+3) matrix of exponents for monomials*/ double *dstore; /* and Mx2 matrix of coeficients for monomials */ int curr_eqn; int curr_mon; int curr_block; int free_mon; void **aux; Dvector Trans; }; /* integer and double and next pointer part of ith monomial*/ #define MonI(P,i) ((P)->istore+(((i)-1)*(((P)->N)+3))) #define MonD(P,i) ((P)->dstore+((i)-1)*2) /* access macroes for ith monomial */ #define Mon_coefR(P,i) ((MonD(P,i))[0]) #define Mon_coefI(P,i) ((MonD(P,i))[1]) #define Mon_homog(P,i) ((MonI(P,i))[0]) #define Mon_defv(P,i) ((MonI(P,i))[1]) #define Mon_next(P,i) ((MonI(P,i))[2]) #define Mon_exp(P,i,d) ((MonI(P,i))[2+(d)]) #define Mon_aux(P,i) (((P)->aux)[i-1]) #define Mon_curr(P) ((P)->curr_mon) /* access macroes for ith equation */ #define Eqn_start(P,i) (((P)->estart)[(i)-1]) #define Eqn_size(P,i) (((P)->tops)[(i)-1]) #define Eqn_curr(P) ((P)->curr_eqn) #define Eqn_deg(P,i) ((P)->degrees[(i)-1]) /* access macroes for the ith block */ #define Blk_start(P,i) (((P)->bstart)[(i)-1]) #define Blk_size(P,i) (Blk_start(sys,i+1)-Blk_start(sys,i)) #define Blk_curr(P) ((P)->curr_block) /* access macroes for system params */ #define Sys_M(P) ((P)->M) #define Sys_Mmax(P) ((P)->Mmax) #define Sys_Neq(P) ((P)->Neq) #define Sys_N(P) ((P)->N) #define Sys_R(P) ((P)->R) #define Sys_Mon_New(P) ((P)->free_mon) /* ** constructor/destructor functions: */ #define MON_SIZE (m*(n+3+4)) #define ISTORE_SIZE ((MON_SIZE+3*n+r+1)) psys psys_new(int n, int m, int r){ int i; psys res; res=(psys)mem_malloc(sizeof(struct psys_t)); res->istore=(int *)mem_malloc(ISTORE_SIZE*sizeof(int)); res->dstore=(double *)mem_malloc(2*m*sizeof(double)); res->aux=(void **)mem_malloc(m*sizeof(void *)); Sys_N(res)=n; Sys_Neq(res)=n; Sys_R(res)=r; Sys_M(res)=0; Sys_Mmax(res)=m; res->estart=res->istore+MON_SIZE; res->tops=res->estart+n; res->degrees=res->tops+n; res->bstart=res->degrees+n; for(i=0;iistore[i]=0; Blk_start(res,r+1)=n+1; /* put all monomials on free list */ Sys_Mon_New(res)=1; for(i=1;i<=m;i++){ Mon_next(res,i)=i+1; Mon_aux(res,i)=0; Mon_coefR(res,i)=0.0; Mon_coefI(res,i)=0.0; } res->curr_mon=0; res->curr_eqn=0; res->curr_block=0; return res; } void psys_free(psys sys){ mem_free((void *)(sys->dstore)); mem_free((void *)(sys->istore)); mem_free((void *)(sys->aux)); mem_free((void *)(sys)); } /* ** two functions for modifying an existing psys by adding ** monomials. ** pysy_new_mon creates a new monomial in the ** new_mon field, and sets curr_mon to point to it. ** It can then be filled with data ** once monomial has been filled with data psys_save_mon ** will add it to a specified equation. (should not be used ** while iterating through monomial list). */ int psys_init_mon(psys sys){ if ((Mon_curr(sys)=(Sys_Mon_New(sys)))!=0) return TRUE; else return FALSE; } void psys_save_mon(psys sys, int i){ int tmp=0,j,idx; /* calculate degree of new monomial */ for(j=1;j<=Sys_N(sys);j++) tmp+=Mon_exp(sys,Sys_Mon_New(sys),j); if (Eqn_start(sys,i)==0){ /* if first monomial set degree */ Eqn_deg(sys,i)=tmp; Mon_homog(sys,Sys_Mon_New(sys))=0; } else if (Eqn_deg(sys,i)>=tmp){ Mon_homog(sys,Sys_Mon_New(sys))=Eqn_deg(sys,i)-tmp; } else { Mon_homog(sys,Sys_Mon_New(sys))=0; idx=Eqn_start(sys,i); while(idx!=0){ Mon_homog(sys,idx)+=tmp-Eqn_deg(sys,i); idx=Mon_next(sys,idx); } Eqn_deg(sys,i)=tmp; } tmp=Mon_next(sys,Sys_Mon_New(sys)); Mon_next(sys,Sys_Mon_New(sys))=Eqn_start(sys,i); Eqn_start(sys,i)=Sys_Mon_New(sys); Sys_Mon_New(sys)=tmp; Sys_M(sys)++; Eqn_size(sys,i)++; } /* ** Display functions */ extern Pring Def_Ring; psys psys_fprint(FILE *fout,psys sys){ int i,pct=0,mct=0; Blk_curr(sys)=1; do { Eqn_curr(sys)=Blk_start(sys,Blk_curr(sys)); do { if (pct++==0) #ifdef LOG_PRINT fprintf(fout,"< ") #endif ; else #ifdef LOG_PRINT fprintf(fout,",\n ") #endif ; Mon_curr(sys)=Eqn_start(sys,Eqn_curr(sys)); mct=0; do { if (mct++!=0) #ifdef LOG_PRINT fprintf(fout," + ") #endif ; if (Mon_coefR(sys,Mon_curr(sys))!=0|| Mon_coefI(sys,Mon_curr(sys))!=0){ if (Mon_coefI(sys,Mon_curr(sys)) != 0.0) fprintf(fout,"("); fprintf(fout,"%g", Mon_coefR(sys,Mon_curr(sys))); if (Mon_coefI(sys,Mon_curr(sys)) != 0.0) { if (Mon_coefI(sys,Mon_curr(sys))>=0.0)fprintf(fout," + "); fprintf(fout,"%g*I)", Mon_coefI(sys,Mon_curr(sys))); } for(i=1;i<=Sys_N(sys);i++){ if (Mon_exp(sys,Mon_curr(sys),i)!=0){ fprintf(fout," %s^%d",ring_var(Def_Ring,i-1), Mon_exp(sys,Mon_curr(sys),i)); } } if (Mon_defv(sys,Mon_curr(sys))!=0){ fprintf(fout," %s^%d",ring_def(Def_Ring), Mon_defv(sys,Mon_curr(sys))); } /* fprintf(fout,"\n"); */ } } while((Mon_curr(sys)=Mon_next(sys,Mon_curr(sys)))!=0); } while(++Eqn_curr(sys)\n"); return sys; } /* ** Accessors */ int psys_d(psys sys) {return sys->N;} double *psys_coef_real(psys sys){ return &(Mon_coefR(sys,Mon_curr(sys))); } double *psys_coef_imag(psys sys){ return &(Mon_coefI(sys,Mon_curr(sys))); } int *psys_exp(psys sys,int d){ return &(Mon_exp(sys,Mon_curr(sys),d)); } int *psys_homog(psys sys){ return &((Mon_homog(sys,Mon_curr(sys)))); } int *psys_def(psys sys){ return &(Mon_defv(sys,Mon_curr(sys))); } /* ** Iteration Functions */ int psys_start_poly(psys sys){ Eqn_curr(sys)=1; return TRUE; } int psys_next_poly(psys sys){ if (++(Eqn_curr(sys))<=Sys_N(sys)) return TRUE; else return FALSE; } int psys_start_block(psys sys){ Blk_curr(sys)=1; return TRUE; } int psys_next_block(psys sys){ if (++Blk_curr(sys)<=Sys_R(sys)) return TRUE; else return FALSE; } int psys_set_eqno(psys sys, int eq){ return (Eqn_curr(sys)=eq); } int psys_eqno(psys sys){ return Eqn_curr(sys); } int psys_bkno(psys sys){ return Blk_curr(sys); } int psys_Bstart_poly(psys sys,int i){ Eqn_curr(sys)=Blk_start(sys,i); return TRUE; } int psys_Bnext_poly(psys sys,int i){ if (++(Eqn_curr(sys))(t=*psys_def(sys))) m=t; } while(psys_next_mon(sys)==TRUE); } FORALL_MONO(sys, if (*psys_def(sys)==m){ psys_init_mon(res); *psys_aux(res)=*psys_aux(sys); *psys_coef_real(res)=*psys_coef_real(sys); *psys_coef_imag(res)=*psys_coef_imag(sys); for(i=1;i<=n;i++) *psys_exp(res,i)=*psys_exp(sys,i); *psys_homog(res) = *psys_homog(sys); *psys_def(res)=0; psys_save_mon(res,psys_eqno(sys)); } ) ) return psys_saturate(res); } /* ** psys_saturate ** input: psys ** output: psys with largest common monomial factor removed. ** side effects: original psys is equal to output psys. ** error contitions: */ #define V(i) (*IVref(V,i)) psys psys_saturate(psys sys) { int i,t,n; Ivector V; n=psys_d(sys); V=Ivector_new(n); FORALL_POLY(sys, /* ** find largest common monomial factor for all ** monomials in res (stored by vector V of exponents) ** WARNING: will also need to check homog variable */ psys_start_mon(sys); for(i=1;i<=n;i++) V(i)=(*psys_exp(sys,i)); if (psys_next_mon(sys)==TRUE){ do{ for(i=1;i<=n;i++){ if ((t=*psys_exp(sys,i))x_i*t^n_i. (and then removing common powers of t) ** sidefects: original system equals output system */ #define norm(i) (*IVref(norm,i)) psys psys_norm_sub(psys sys,Ivector norm) { int i,t,n; int m = 0; int tog = 0; n=psys_d(sys); FORALL_POLY(sys, tog=0; FORALL_MONO(sys, t=(norm(n+1))*(*psys_def(sys)); for(i=1;i<=psys_d(sys);i++) t+=(*psys_exp(sys,i))*norm(i); *psys_def(sys)=t; if (tog==0) { m=t; tog=1;} else if (m>t) m=t; ) FORALL_MONO(sys,*psys_def(sys)-=m;) ) return sys; } #undef norm /* end psys_ops.c */ /**************************************************************************/ /****************** implementation code from psys_scale.c *****************/ /**************************************************************************/ /* ** copyright (c) 1995 Birk Huber */ /* ** scale.c Birk Huber created 4-8-1995 ** All Rights Reserved ** ** Very simple program for polynomial system scaling. ** ** Given a system F_1,...,F_n of polynomial equations ** in variables X_1,...,X_n calculates constants d_i ** and c_i so that the new equations ** 10^{d_i}F_i(10^{c_1}X_1,...,10^{c_n}X_n) ** will have coefitients as close to one as possible (i.e. the ** two norm of the vector of logarithms will be minimized). ** ** The book on continuation by Morgan describes a similar algorithm, ** in which variation among the coeficients is also minimized ** explicitly. This code does not take speciall steps to also ** minimize the diferences -- It is sort of taken care of allready ** by the least squares problem allready. (might add it later need ** only new rows in matrix). */ /* NOW REDUNDANT #include #include #include "psys.h" */ /* ** Array and Polynomial data acces macroes */ #define LHS(i,j) (DMref(LHS,i,j)) #define RHS(i) (DVref(RHS,i)) /* #define X(i) (DVref(X,i)) REDEFINITION */ #define CEXP(i) (*psys_exp(Sys,i)) #define CCR (*psys_coef_real(Sys)) #define CCI (*psys_coef_imag(Sys)) /* ** Scale ** Input: a polynomial system Sys (n-variables n-equations). ** Output: Vector whoose ith coordinate is the inverse 10^{-c_i} ** of the variable scaling factor for the i-th variable ** Side Effect: Sys gets scaled. */ Dvector psys_scale(psys Sys){ int i,j,k,n,row=1,m=0,eqno=0; Dmatrix LHS,RHS,X; double t,t1,t2,s,s1,s2; n=psys_d(Sys); m=psys_size(Sys); /* ** Set up least squares problem: find X minimizing |(LHS)(X)-(RHS)| ** ** Under scaling 10^d_i*F_i(x_1^e_1,...,x_n^e_n) each monomial m=a*x_1^e_1*...*x_n^e_n ** becomes 10^{d_i}*a*10^{c_1*e_1+...+c_n*e_n}x_1^{e_1}*...x_n^{e_n} ** taking logarithms the goal that the new coeficient should be equal to one ** becomes a linear condition d_i+c_1*e_1+...c_n*e_n = -log(a) ** which gets writen out as a matrix equation for the unknown ** X=[d_1,...,d_n,c_1,...,c_n]. */ RHS=Dvector_new(m); LHS=Dmatrix_new(m,2*n); X=Dvector_new(2*n); eqno=0; psys_start_poly(Sys); do { eqno++; psys_start_mon(Sys); do { for(j=1;j<=n;j++) LHS(row,j)=0; LHS(row,eqno)=1.0; for(j=1;j<=n;j++) LHS(row,n+j)=CEXP(j); RHS(row)=-1.0*log10(sqrt(CCR*CCR+CCI*CCI)); row++; } while(psys_next_mon(Sys)==TRUE); } while(psys_next_poly(Sys)==TRUE); /* ** Use Givens rotations to triangularize LHS,i.e.LHS becomes Q*LHS.(triangular) ** and also apply same givens rotations to RHS i.e. RHS becomes Q*RHS. */ for (i=1;i<=2*n;i++){ for (k=i+1;k<=m;k++){ if (LHS(k,i)!=0.0){ /* compute rotation */ s=sqrt(LHS(i,i)*LHS(i,i)+LHS(k,i)*LHS(k,i)); s1=LHS(i,i)/s; s2=LHS(k,i)/s; /* apply rotation to LHS */ for(j=1;j<=2*n;j++) { t1=LHS(i,j); t2=LHS(k,j); LHS(i,j)=s1*t1+s2*t2; LHS(k,j)=-s2*t1+s1*t2; } /* apply rotation to RHS */ t1=RHS(i); t2=RHS(k); RHS(i)=s1*t1+s2*t2; RHS(k)=-s2*t1+s1*t2; } } } /* ** Back solve R*X=Y ** R=top square portion of LHS. (2nx2nupper triangular) ** Y=top 2n entrees of RHS. ** results in X which solves original least squares problem. */ for(j=2*n;j>=1;j--){ t=RHS(j); for(i=j+1;i<=2*n;i++) t-=LHS(j,i)*X(i); t=t/LHS(j,j); X(j)=t; } /* ** Actually perform scaling (X=[d_1,...,d_n,c_1,...,c_n]) ** adjust coeficients to those of new system (exponents remain unchanged) ** 10^{d_i}F_i(10^{c_1}x_1,...,10^{c_n}x_n) */ eqno=0; psys_start_poly(Sys); do { eqno++; psys_start_mon(Sys); do { t=X(eqno); for(j=1;j<=n;j++) t+=(X(n+j)*CEXP(j)); CCR*=pow(10.0,t); CCI*=pow(10.0,t); } while(psys_next_mon(Sys)==TRUE); } while(psys_next_poly(Sys)==TRUE); /* ** clean-up and return vector defining inverse scaling factors ** to be used to get solutions for original problem. */ Dmatrix_free(LHS); Dmatrix_free(RHS); RHS=Dvector_new(n); for(i=1;i<=n;i++) RHS(i)=pow(10.0,X(n+i)); Dmatrix_free(X); return RHS; } /* ** Undefine Array and Polynomial data access macroes */ #undef LHS #undef RHS #undef X #undef CEXP #undef CCR #undef CCI /* end psys_scale.c */ gambit-0.2010.09.01/src/tools/enumpoly/pelpsys.h0000644000076500007650000000607711350032206016111 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* ** copyright (c) 1995 Birk Huber */ /* ** System.h interface to psys class ** requires Dvector. */ #ifndef PSYS_INC #define PSYS_INC 1 #define DMATRIX_FAST 1 #include "pelutils.h" #define psys_outfile stdout #define psys_logfile stdout typedef struct psys_t *psys; /* These declarations are added to get compilation. Linking is another matter... */ int HPK_cont(Dvector, int tweak); int init_hom(psys); /* creator/destructor*/ void psys_free(psys); psys psys_new(int,int,int); int psys_init_mon(psys); void psys_save_mon(psys,int); /* psys psys_block_init(psys); */ psys psys_fprint(FILE *,psys); #define psys_print(p) (psys_fprint(psys_outfile,p)) psys psys_copy(psys); /* access functions */ #define FORALL_POLY(sys,stmts) psys_start_poly(sys); do { stmts } while(psys_next_poly(sys)==TRUE); #define FORALL_MONO(sys,stmts) psys_start_mon(sys); do { stmts } while(psys_next_mon(sys)==TRUE); #define FORALL_BLOCK(sys,stmts) psys_start_block(sys); do { stmts } while(psys_next_block(sys)==TRUE); int psys_d(psys); int psys_r(psys); int psys_eqno(psys); int psys_set_eqno(psys,int); int psys_size(psys); int psys_start_poly(psys); int psys_start_mon(psys); int psys_start_block(psys); int psys_next_poly(psys); int psys_next_block(psys); int psys_Bstart_poly(psys,int); int psys_Bnext_poly(psys,int); int psys_next_mon(psys); double *psys_coef_real(psys); double *psys_coef_imag(psys); void **psys_aux(psys); int *psys_exp(psys,int); int *psys_homog(psys); int *psys_def(psys); int psys_block_size(psys); int *psys_block_start(psys,int); int psys_bkno(psys); int psys_eq_size(psys); Ivector psys_type(psys); /* transformations */ Dvector psys_scale(psys); psys psys_lift(psys,int); psys psys_lead(psys); psys psys_saturate(psys); psys psys_norm_sub(psys,Ivector); aset psys_to_aset(psys P); psys aset_to_psys(aset A,Ivector T, int seed); node psys_binsolve(psys sys); node psys_hom(psys sys, node point_list, int tweak); /* tweaks homotopy */ node psys_solve(psys sys, Imatrix norm, int tweak); /* evaluators */ Dmatrix psys_jac(psys,Dvector,Dmatrix); double psys_abs(psys,Dvector); Dvector psys_eval(psys,Dvector,Dvector); Dvector psys_moment(psys,Dvector,Dvector); /*untried*/ #endif gambit-0.2010.09.01/src/tools/enumpoly/pelqhull.cc0000644000076500007650000107106611351773322016413 00000000000000/* qhull.c - For the Gambit Project This file contains the implementation code taken from qhull and incorporated into the Gambit source code. We have placed all qhull code in qhull.h and qhull.c to avoid adding to the number of files in Gambit, and, more importantly, to express the idea that, from our point of view, this is a blackbox. We are unlikely to be able to answer questions concerning this code, and those who wish to modify it should consider beginning with the version distributed by the Geometry Center. */ #include "pelqhull.h" /*************************************************************************/ /******************* implementation code from mem.c **********************/ /*************************************************************************/ /* mem.c - memory management routines for qhull This is a standalone program. To initialize memory: qh_meminit (stderr); / qh_meminitbuffers (qh IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf); qh_memsize(sizeof(facetT)); qh_memsize(sizeof(facetT)); ... qh_memsetup(); To free up all memory buffers: qh_memfreeshort (&curlong, &totlong); uses Quickfit algorithm (freelists for commonly allocated sizes) assumes small sizes for freelists (it discards the tail of memory buffers) see README and mem.h see global.c (qh_initbuffers) for an example of using mem.c copyright (c) 1993-1994 The Geometry Center */ /* ============ -global data structure ============== see mem.h for definition */ qhmemT qhmem= {0}; /* remove "= {0}" if this causes a compiler error */ /* internal functions */ static int qh_intcompare(const void *i, const void *j); /*========== functions in alphabetical order ======== */ /*------------------------------------------------- -intcompare- used by qsort and bsearch to compare two integers */ static int qh_intcompare(const void *i, const void *j) { return(*((int *)i) - *((int *)j)); } /* intcompare */ /*------------------------------------------------- -memalloc- allocates memory for object from qhmem returns: pointer to allocated memory (errors if insufficient memory) outsize= actual size allocated, may be NULL notes: use qh_memalloc_() for inline code for quick allocations */ void *qh_memalloc(int insize) { void **freelistp, *newbuffer; int index, size; int outsize, bufsize; void *object; if ((unsigned) insize <= (unsigned) qhmem.LASTsize) { index= qhmem.indextable[insize]; freelistp= qhmem.freelists+index; if ((object= *freelistp)) { qhmem.cntquick++; *freelistp= *((void **)*freelistp); /* replace freelist with next object */ return (object); }else { outsize= qhmem.sizetable[index]; qhmem.cntshort++; if (outsize > qhmem .freesize) { if (!qhmem.curbuffer) bufsize= qhmem.BUFinit; else bufsize= qhmem.BUFsize; qhmem.totshort += bufsize; if (!(newbuffer= malloc(bufsize))) qhull_fatal(1); *((void **)newbuffer)= qhmem.curbuffer; /* prepend newbuffer to curbuffer list */ qhmem.curbuffer= newbuffer; size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask; qhmem.freemem= (void *)((char *)newbuffer+size); qhmem.freesize= bufsize - size; } object= qhmem.freemem; qhmem.freemem= (void *)((char *)qhmem.freemem + outsize); qhmem.freesize -= outsize; return object; } }else { /* long allocation */ if (!qhmem.indextable) qhull_fatal(2); outsize= insize; qhmem .cntlong++; qhmem .curlong++; qhmem .totlong += outsize; if (qhmem.maxlong < qhmem.totlong) qhmem.maxlong= qhmem.totlong; if (!(object= malloc(outsize))) qhull_fatal(3); if (qhmem.IStracing >= 5) fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", outsize, object); } return (object); } /* memalloc */ /*------------------------------------------------- -memfree- frees memory object (may be NULL) size is either insize or outsize from qh_memalloc type checking warns if using (void **)object qh_memfree_()- in-line code for quick free's */ void qh_memfree(void *object, int size) { void **freelistp; if (!object) return; if (size <= qhmem.LASTsize) { qhmem .freeshort++; freelistp= qhmem.freelists + qhmem.indextable[size]; *((void **)object)= *freelistp; *freelistp= object; }else { qhmem .freelong++; qhmem .totlong -= size; free (object); if (qhmem.IStracing >= 5) fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object); } } /* memfree */ /*------------------------------------------------- -memfreeshort- frees up all short and qhmem memory allocations returns: number and size of current long allocations */ void qh_memfreeshort (int *curlong, int *totlong) { void *buffer, *nextbuffer; *curlong= qhmem .cntlong - qhmem .freelong; *totlong= qhmem .totlong; for(buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) { nextbuffer= *((void **) buffer); free(buffer); } qhmem.curbuffer= NULL; if (qhmem .LASTsize) { free (qhmem .indextable); free (qhmem .freelists); free (qhmem .sizetable); } memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */ } /* memfreeshort */ /*------------------------------------------------- -meminit- initialize memory (memalloc errors until memsetup) */ void qh_meminit (FILE *ferr) { memset((char *)&qhmem, 0, sizeof qhmem); /* every field is 0, FALSE, NULL */ qhmem.ferr= ferr; #ifndef __BCC55__ // This condition is always false under BCC55 if (sizeof(void*) < sizeof(int)) qhull_fatal(4); #endif // __BCC55__ } /* meminit */ /*------------------------------------------------- -meminitbuffers- initialize memory buffers */ void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) { qhmem.IStracing= tracelevel; qhmem.NUMsizes= numsizes; qhmem.BUFsize= bufsize; qhmem.BUFinit= bufinit; qhmem.ALIGNmask= alignment-1; if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) qhull_fatal(5); qhmem.sizetable= (int *) calloc (numsizes, sizeof(int)); qhmem.freelists= (void **) calloc (numsizes, sizeof(void *)); if (!qhmem.sizetable || !qhmem.freelists) qhull_fatal(6); if (qhmem.IStracing >= 1) fprintf (qhmem.ferr, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment); } /* meminitbuffers */ /*------------------------------------------------- -memsetup- set up memory after running memsize() */ void qh_memsetup (void) { int k,i; qsort(qhmem.sizetable, qhmem.TABLEsize, sizeof(int), qh_intcompare); qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1]; if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) qhull_fatal(7); if (!(qhmem.indextable= (int *)malloc((qhmem.LASTsize+1) * sizeof(int)))) qhull_fatal(8); for(k=qhmem.LASTsize+1; k--; ) qhmem.indextable[k]= k; i= 0; for(k= 0; k <= qhmem.LASTsize; k++) { if (qhmem.indextable[k] <= qhmem.sizetable[i]) qhmem.indextable[k]= i; else qhmem.indextable[k]= ++i; } } /* memsetup */ /*------------------------------------------------- -memsize- define a free list for this size */ void qh_memsize(int size) { int k; if (qhmem .LASTsize) qhull_fatal(9); size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask; for(k= qhmem.TABLEsize; k--; ) { if (qhmem.sizetable[k] == size) return; } if (qhmem.TABLEsize < qhmem.NUMsizes) qhmem.sizetable[qhmem.TABLEsize++]= size; else fprintf(qhmem.ferr, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes); } /* memsize */ /*------------------------------------------------- -memstatistics- print out memory statistics */ void qh_memstatistics (FILE *fp) { int i, count; void *object; fprintf (fp, "\nmemory statistics:\n\ %7d quick allocations\n\ %7d short allocations\n\ %7d long allocations\n\ %7d short frees\n\ %7d long frees\n\ %7d bytes of short memory in use or on freelists\n\ %7d bytes of long memory allocated (except for input)\n\ %7d bytes of long memory in use (in %d pieces)\n\ %7d bytes per memory buffer (initially %d bytes)\n", qhmem .cntquick, qhmem.cntshort, qhmem.cntlong, qhmem .freeshort, qhmem.freelong, qhmem .totshort - qhmem .freesize, qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong, qhmem .BUFsize, qhmem .BUFinit); if (qhmem.cntlarger) { fprintf (fp, "%7d calls to qh_setlarger\n%7.2g average copy size\n", qhmem.cntlarger, ((float) qhmem.totlarger)/ qhmem.cntlarger); fprintf (fp, " freelists (bytes->count):"); } for (i=0; i%d", qhmem.sizetable[i], count); } fprintf (fp, "\n\n"); } /* memstatistics */ /*************************************************************************/ /******************* implementation code from set.c **********************/ /*************************************************************************/ /* set.c -- implements set manipulations needed for quickhull see README and set.h copyright (c) 1993-1994 The Geometry Center */ /*----------- internal macros ------------------- -SETsizeaddr_(set) - return pointer to actual size+1 of set (set CANNOT be NULL!!) *SETsizeaddr==NULL or e[*SETsizeaddr-1]==NULL */ #define SETsizeaddr_(set) ((int *)(&((set)->e[(set)->maxsize]))) /*============ functions in alphabetical order ===================*/ /*---------------------------------------- -setaddnth- adds newelem as n'th element of sorted or unsorted set setp and newelem must be defined set may be a temp set nth=0 is first element errors if nth is out of bounds */ void qh_setaddnth(setT **setp, int nth, void *newelem) { int *sizep, oldsize, i; void **oldp, **newp; if (!*setp || !*(sizep= SETsizeaddr_(*setp))) { qh_setlarger(setp); sizep= SETsizeaddr_(*setp); } oldsize= *sizep - 1; if (nth < 0 || nth > oldsize) qhull_fatal(10); (*sizep)++; oldp= SETelemaddr_(*setp, oldsize, void); /* NULL */ newp= oldp+1; for (i= oldsize-nth+1; i--; ) /* move at least NULL */ *(newp--)= *(oldp--); /* may overwrite *sizep */ *newp= newelem; } /* setaddnth */ /*---------------------------------------- -setaddsorted- adds an element to a sorted set setp and newelem must be defined set may be a temp set nop if newelem already in set */ void qh_setaddsorted(setT **setp, void *newelem) { int newindex=0; void *elem, **elemp; FOREACHelem_(*setp) { /* could use binary search instead */ if (elem < newelem) newindex++; else if (elem == newelem) return; else break; } qh_setaddnth(setp, newindex, newelem); } /* setaddsorted */ /*---------------------------------------- -setappend- appends an element to a set set may be a temp set *setp and newelem may be NULL */ void qh_setappend(setT **setp, void *newelem) { int *sizep; void **endp; if (!newelem) return; if (!*setp || !*(sizep= SETsizeaddr_(*setp))) { qh_setlarger(setp); sizep= SETsizeaddr_(*setp); } *(endp= &((*setp)->e[(*sizep)++ - 1]))= newelem; *(++endp)= NULL; } /* setappend */ /*---------------------------------------- -setappend_set- appends a set to a set *setp and set may be NULL setp can not be a temp set */ void qh_setappend_set(setT **setp, setT *setA) { int *sizep, sizeA, size; setT *oldset; if (!setA) return; SETreturnsize_(setA, sizeA); if (!*setp) *setp= qh_setnew (sizeA); sizep= SETsizeaddr_(*setp); if (!(size= *sizep)) size= (*setp)->maxsize; else size--; if (size + sizeA >(int) (*setp)->maxsize) { oldset= *setp; *setp= qh_setcopy (oldset, sizeA); qh_setfree (&oldset); sizep= SETsizeaddr_(*setp); } *sizep= size+sizeA+1; /* memcpy may overwrite */ if (sizeA > 0) memcpy((char *)&((*setp)->e[size]), (char *)&(setA->e[0]), SETelemsize *(sizeA+1)); } /* setappend_set */ /*---------------------------------------- -setappend2ndlast- makes newelem the next to the last element in set set must have at least one element, newelem must be defined set may be a temp set */ void qh_setappend2ndlast(setT **setp, void *newelem) { int *sizep; void **endp, **lastp; if (!*setp || !*(sizep= SETsizeaddr_(*setp))) { qh_setlarger(setp); sizep= SETsizeaddr_(*setp); } endp= SETelemaddr_(*setp, (*sizep)++ -1, void); /* NULL */ lastp= endp-1; *(endp++)= *lastp; *endp= NULL; /* may overwrite *sizep */ *lastp= newelem; } /* setappend2ndlast */ /*---------------------------------------- -setcheck- check set for validity */ void qh_setcheck(setT *set, char *typenameNEW, int id) { int maxsize, size; int waserr= 0; if (!set) return; SETreturnsize_(set, size); maxsize= set->maxsize; if (size > maxsize || !maxsize) { fprintf (qhmem.ferr, "qhull internal error (setcheck): actual size %d of %s%d is greater than max size %d\n", size, typenameNEW, id, maxsize); waserr= 1; }else if (set->e[size]) { fprintf (qhmem.ferr, "qhull internal error (setcheck): %s%d (size %d max %d) is not null terminated.\n", typenameNEW, id, maxsize, size-1); waserr= 1; } if (waserr) qhull_fatal(11); } /* setcheck */ /*---------------------------------------- -setcopy- copies a sorted or unsorted set into another returns: new set is actual size of old set plus extra */ setT *qh_setcopy(setT *set, int extra) { setT *newset; int size; if (extra < 0) extra= 0; SETreturnsize_(set, size); newset= qh_setnew(size+extra); *SETsizeaddr_(newset)= size+1; /* memcpy may overwrite */ memcpy((char *)&(newset->e[0]), (char *)&(set->e[0]), SETelemsize *(size+1)); return (newset); } /* setcopy */ /*---------------------------------------- -setdel- deletes oldelem from unsorted set. if found, overwrites newlelem with lastelem set may be NULL, oldelem must not be NULL; returns: returns oldelem if it was deleted */ void *qh_setdel(setT *set, void *oldelem) { void **elemp, **lastp; int *sizep; if (!set) return NULL; elemp= SETaddr_(set, void); while (*elemp != oldelem && *elemp) elemp++; if (*elemp) { sizep= SETsizeaddr_(set); if (!(*sizep)--) /* if was a full set */ *sizep= set->maxsize; /* *sizep= (maxsize-1)+ 1 */ lastp= SETelemaddr_(set, *sizep-1, void); *elemp= *lastp; /* may overwrite itself */ *lastp= NULL; return oldelem; } return NULL; } /* setdel */ /*---------------------------------------- -setdellast- return last element of set or NULL delete element from set set may be NULL */ void *qh_setdellast(setT *set) { int setsize; void **last; void *returnvalue; if (!set || !(set->e[0])) return NULL; if ((setsize= (long)*(last= &(set->e[set->maxsize])))) { returnvalue= set->e[setsize - 2]; set->e[setsize - 2]= NULL; *last= (void *)((long)*last - 1); }else { returnvalue= set->e[set->maxsize - 1]; set->e[set->maxsize - 1]= NULL; *last= (void *)(set->maxsize); } return returnvalue; } /* setdellast */ /*---------------------------------------- -setdelnth- deletes nth element from unsorted set errors if nth invalid returns the element */ void *qh_setdelnth(setT *set, int nth) { void **elemp, **lastp, *elem; int *sizep; elemp= SETelemaddr_(set, nth, void); sizep= SETsizeaddr_(set); if (!(*sizep)--) /* if was a full set */ *sizep= set->maxsize; /* *sizep= (maxsize-1)+ 1 */ if (nth < 0 || nth >= *sizep) qhull_fatal(12); lastp= SETelemaddr_(set, *sizep-1, void); elem= *elemp; *elemp= *lastp; /* may overwrite itself */ *lastp= NULL; return elem; } /* setdelnth */ /*---------------------------------------- -setdelnthsorted- deletes nth element from sorted set sort order is undefined errors if nth invalid see also: setnew_delnthsorted */ void *qh_setdelnthsorted(setT *set, int nth) { void **newp, **oldp, *elem; int *sizep; sizep= SETsizeaddr_(set); if ( nth < 0 || (*sizep && nth >= *sizep-1) || nth >= (int)set->maxsize ) qhull_fatal(13); newp= SETelemaddr_(set, nth, void); elem= *newp; oldp= newp+1; while ((*(newp++)= *(oldp++))) ; /* copy remaining elements and NULL */ if (!(*sizep)--) /* if was a full set */ *sizep= set->maxsize; /* *sizep= (max size-1)+ 1 */ return elem; } /* setdelnthsorted */ /*---------------------------------------- -setdelsorted- deletes oldelem from sorted set sort order is undefined set may be NULL returns oldelem if it was deleted */ void *qh_setdelsorted(setT *set, void *oldelem) { void **newp, **oldp; int *sizep; if (!set) return NULL; newp= SETaddr_(set, void); while(*newp != oldelem && *newp) newp++; if (*newp) { oldp= newp+1; while ((*(newp++)= *(oldp++))) ; /* copy remaining elements */ sizep= SETsizeaddr_(set); if (!(*sizep)--) /* if was a full set */ *sizep= set->maxsize; /* *sizep= (max size-1)+ 1 */ return oldelem; } return NULL; } /* setdelsorted */ /*---------------------------------------- -setequal- returns 1 if two sorted sets are equal, otherwise returns 0 either set may be NULL */ int qh_setequal(setT *setA, setT *setB) { void **elemAp, **elemBp; int sizeA, sizeB; SETreturnsize_(setA, sizeA); SETreturnsize_(setB, sizeB); if (sizeA != sizeB) return 0; if (!sizeA) return 1; elemAp= SETaddr_(setA, void); elemBp= SETaddr_(setB, void); if (!memcmp((char *)elemAp, (char *)elemBp, sizeA*SETelemsize)) return 1; return 0; } /* setequal */ /*---------------------------------------- -setequal_except- returns 1 if two sorted sets are equal except for 2 elements neither set may be NULL false if either skip is missing if second skip is NULL, can skip any one element */ int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB) { void **elemA, **elemB; int skip=0; elemA= SETaddr_(setA, void); elemB= SETaddr_(setB, void); while (1) { if (*elemA == skipelemA) { skip++; elemA++; } if (skipelemB) { if (*elemB == skipelemB) { skip++; elemB++; } }else if (*elemA != *elemB) { skip++; if (!(skipelemB= *elemB++)) return 0; } if (!*elemA) break; if (*elemA++ != *elemB++) return 0; } if (skip != 2 || *elemB) return 0; return 1; } /* setequal_except */ /*---------------------------------------- -setequal_skip- returns 1 if two sorted sets are equal except for skips neither set may be NULL false if different size */ int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB) { void **elemA, **elemB, **skipAp, **skipBp; elemA= SETaddr_(setA, void); elemB= SETaddr_(setB, void); skipAp= SETelemaddr_(setA, skipA, void); skipBp= SETelemaddr_(setB, skipB, void); while (1) { if (elemA == skipAp) elemA++; if (elemB == skipBp) elemB++; if (!*elemA) break; if (*elemA++ != *elemB++) return 0; } if (*elemB) return 0; return 1; } /* setequal_skip */ /*---------------------------------------- -setfree- frees the space occupied by a sorted or unsorted set set may be NULL */ void qh_setfree(setT **setp) { int size; void **freelistp; if (*setp) { size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize; if (size <= qhmem.LASTsize) { qh_memfree_(*setp, size, freelistp); }else qh_memfree (*setp, size); *setp= NULL; } } /* setfree */ /*---------------------------------------- -setfreelong- frees a set only if it's in long memory set may be NULL */ void qh_setfreelong(setT **setp) { int size; if (*setp) { size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize; if (size > qhmem.LASTsize) { qh_memfree (*setp, size); *setp= NULL; } } } /* setfreelong */ /*---------------------------------------- -setin- returns 1 if setelem is in a set, 0 otherwise set may be NULL or unsorted */ int qh_setin(setT *set, void *setelem) { void *elem, **elemp; FOREACHelem_(set) { if (elem == setelem) return 1; } return 0; } /* setin */ /*---------------------------------------- -setindex- returns the index of elem in set. If none, returns -1 set may be NULL and may contain nulls. */ int qh_setindex(setT *set, void *atelem) { void **elem; int size, i; SETreturnsize_(set, size); if (size > (int)set->maxsize) return -1; elem= SETaddr_(set, void); for (i=0; imaxsize - 1); else if (size > 1) return SETelem_(set, size - 2); } return NULL; } /* setlast */ /*---------------------------------------- -setnew- creates and allocates space for a set setsize means the number of elements (NOT including the NULL terminator) use qh_settemp/qh_setfreetemp if set is temporary */ setT *qh_setnew(int setsize) { setT *set; int sizereceived, size; void **freelistp; if (!setsize) setsize++; size= sizeof(setT) + setsize * SETelemsize; if ((unsigned) size <= (unsigned) qhmem.LASTsize) { qh_memalloc_(size, freelistp, set); sizereceived= qhmem.sizetable[ qhmem.indextable[size]]; if (sizereceived > size) setsize += (sizereceived - size)/SETelemsize; }else set= (setT *)qh_memalloc ((int)size); set->maxsize= setsize; set->e[setsize]= (void *) 1; set->e[0]= NULL; return (set); } /* setnew */ /*---------------------------------------- -setnew_delnthsorted- creates a sorted set not containing nth element the new set may have prepended undefined entries set must be defined checks nth see also: setdelnthsorted */ setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend) { setT *newset; void **oldp, **newp; int tailsize= size - nth -1, newsize; if (tailsize < 0) qhull_fatal(14); newsize= size-1 + prepend; newset= qh_setnew(newsize); newset->e[newset->maxsize]= (void *)(newsize+1); /* may be overwritten */ oldp= SETaddr_(set, void); newp= SETaddr_(newset, void) + prepend; switch (nth) { case 0: break; case 1: *(newp++)= *oldp++; break; case 2: *(newp++)= *oldp++; *(newp++)= *oldp++; break; case 3: *(newp++)= *oldp++; *(newp++)= *oldp++; *(newp++)= *oldp++; break; case 4: *(newp++)= *oldp++; *(newp++)= *oldp++; *(newp++)= *oldp++; *(newp++)= *oldp++; break; default: memcpy((char *)newp, (char *)oldp, nth * SETelemsize); newp += nth; oldp += nth; break; } oldp++; switch (tailsize) { case 0: break; case 1: *(newp++)= *oldp++; break; case 2: *(newp++)= *oldp++; *(newp++)= *oldp++; break; case 3: *(newp++)= *oldp++; *(newp++)= *oldp++; *(newp++)= *oldp++; break; case 4: *(newp++)= *oldp++; *(newp++)= *oldp++; *(newp++)= *oldp++; *(newp++)= *oldp++; break; default: memcpy((char *)newp, (char *)oldp, tailsize * SETelemsize); newp += tailsize; } *newp= NULL; return(newset); } /* setnew_delnthsorted */ /*---------------------------------------- -setprint- print set elements to fp notes: never errors */ void qh_setprint(FILE *fp, char* string, setT *set) { int size, k; if (!set) fprintf (fp, "%s set is null\n", string); else { SETreturnsize_(set, size); //fprintf (fp, "%s set=%x maxsize=%d size=%d elems=", // string, (unsigned int) set, set->maxsize, size); fprintf (fp, "%s set=%x maxsize=%d size=%d elems=", string, set, set->maxsize, size); if (size > (int)set->maxsize) size= set->maxsize+1; for (k=0; ke[k]); fprintf(fp, "\n"); } } /* setprint */ /*---------------------------------------- -setreplace- replaces oldelem in set with newelem errors if oldelem not in the set if newelem is NULL then FOREACH no longer works */ void qh_setreplace(setT *set, void *oldelem, void *newelem) { void **elemp; elemp= SETaddr_(set, void); while(*elemp != oldelem && *elemp) elemp++; if (*elemp) *elemp= newelem; else qhull_fatal(15); } /* setreplace */ /*---------------------------------------- -setsize- returns the size of a set same as SETreturnsize_(set) */ int qh_setsize(setT *set) { int size, *sizep; if (!set) return (0); sizep= SETsizeaddr_(set); if ((size= *sizep)) { size--; if (size > (int)set->maxsize) qhull_fatal(16); }else size= set->maxsize; return size; } /* setsize */ /*---------------------------------------- -settemp- return a stacked, temporary set use settempfree or settempfree_all to release from qhmem.tempstack see also qh_setnew */ setT *qh_settemp(int setsize) { setT *newset; newset= qh_setnew (setsize); qh_setappend ((setT **)&qhmem.tempstack, newset); if (qhmem.IStracing >= 5) fprintf (qhmem.ferr, "qh_settemp: temp set %p of %d elements, depth %d\n", newset, newset->maxsize, qh_setsize ((setT *)qhmem.tempstack)); return newset; } /* settemp */ /*---------------------------------------- -settempfree- free temporary set at top of qhmem.tempstack nop if NULL errors if set not from previous qh_settemp locate source by T2 and find mis-matching qh_settemp */ void qh_settempfree(setT **set) { setT *stackedset; if (!*set) return; stackedset= qh_settemppop (); if (stackedset != *set) qhull_fatal(17); qh_setfree (set); } /* settempfree */ /*---------------------------------------- -settempfree_all- free all temporary sets in qhmem.tempstack */ void qh_settempfree_all(void) { setT *set, **setp; FOREACHset_((setT *)qhmem.tempstack) qh_setfree(&set); qh_setfree((setT **)&qhmem.tempstack); } /* settempfree_all */ /*---------------------------------------- -settemppop- pop and return temporary set from qhmem.tempstack (makes it permanent) */ setT *qh_settemppop(void) { setT *stackedset; stackedset= (setT *)qh_setdellast((setT *)qhmem.tempstack); if (!stackedset) qhull_fatal(18); if (qhmem.IStracing >= 5) fprintf (qhmem.ferr, "qh_settemppop: depth %d temp set %p of %d elements\n", qh_setsize((setT *)qhmem.tempstack)+1, stackedset, qh_setsize(stackedset)); return stackedset; } /* settemppop */ /*---------------------------------------- -settemppush- push temporary set unto qhmem.tempstack (makes it temporary) duplicates settemp() for tracing */ void qh_settemppush(setT *set) { qh_setappend ((setT**)&qhmem.tempstack, set); if (qhmem.IStracing >= 5) fprintf (qhmem.ferr, "qh_settemppush: depth %d temp set %p of %d elements\n", qh_setsize((setT *)qhmem.tempstack), set, qh_setsize(set)); } /* settemppush */ /*---------------------------------------- -settruncate- truncate set to size elements set must be defined */ void qh_settruncate (setT *set, int size) { if (size < 0 || size > (int)set->maxsize) qhull_fatal(19); set->e[set->maxsize]= (void *) (size+1); /* maybe overwritten */ set->e[size]= NULL; } /* setruncate */ /*---------------------------------------- -setunique- add element if it isn't already returns 1 if it's appended */ int qh_setunique (setT **set, void *elem) { if (!qh_setin (*set, elem)) { qh_setappend (set, elem); return 1; } return 0; } /* setunique */ /*---------------------------------------- -setzero- zero remainder of set and set its size set must be defined */ void qh_setzero (setT *set, int index, int size) { int count; if (index < 0 || index >= size || size > (int)set->maxsize) qhull_fatal(20); (set->e[set->maxsize])= (void *)(size+1); /* may be overwritten */ count= size - index + 1; /* +1 for NULL terminator */ memset ((char *)SETelemaddr_(set, index, void), 0, count * sizeof(void *)); } /* setzero */ /*************************************************************************/ /****************** implementation code from geom.c **********************/ /*************************************************************************/ /* geom.c -- geometric routines of qhull see README and geom.h copyright (c) 1993-1994 The Geometry Center */ /*------------------------------------------------- -backnormal- solve for normal x using back substitution over rows U solves Ux=b where Ax=b and PA=LU b= [0,...,0,sign or 0] (-1 if sign, else +1) last row of A= [0,...,0,1] assumes numrow == numcol-1 returns: normal= x if can't divzero() for later normalization (qh MINdenom_2 and qh MINdenom_1_2), sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...] sets nearzero, unless last row (i.e., hyperplane intersects [0,..,1]) notes: 1) Ly=Pb == y=b since P only permutes the 0's of b see Golub & van Loan 4.4-9 for back substitution */ void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero) { int i, j; coordT *normalp, *normal_tail, *ai, *ak; realT diagonal; boolT waszero; int zerocol=-1; normalp= normal + numcol - 1; *normalp--= (sign ? -1.0 : 1.0); for(i= numrow; i--; ) { *normalp= 0.0; ai= rows[i] + i + 1; ak= normalp+1; for(j= i+1; j < numcol; j++) *normalp -= *ai++ * *ak++; diagonal= (rows[i])[i]; if (fabs_(diagonal) > qh MINdenom_2) *(normalp--) /= diagonal; else { waszero= False; *normalp= qh_divzero (*normalp, diagonal, qh MINdenom_1_2, &waszero); if (waszero) { zerocol= i; *(normalp--)= (sign ? -1.0 : 1.0); for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++) *normal_tail= 0.0; }else normalp--; } } if (zerocol != -1) { zzinc_(Zback0); *nearzero= True; trace4((qh ferr, "qh_backnormal: zero diagonal at column %d.\n", i)); } } /* backnormal */ /*------------------------------------------------- -crossproduct- of 2 dim vectors, C= A x B from Glasner, Graphics Gems I, p. 639 NOTE: only defined for dim==3 */ void qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]){ if (dim == 3) { vecC[0]= det2_(vecA[1], vecA[2], vecB[1], vecB[2]); vecC[1]= - det2_(vecA[0], vecA[2], vecB[0], vecB[2]); vecC[2]= det2_(vecA[0], vecA[1], vecB[0], vecB[1]); } } /* vcross */ /*------------------------------------------------- -determinant- compute the determinant of a square matrix rows= row vectors uses qh NEARzero to test for degenerate matrices this does look right, probably no easy way of doing it returns: determinant overwrites rows and the matrix nearzero set if degenerate */ realT qh_determinant (realT **rows, int dim, boolT *nearzero) { realT det=0; int i; boolT sign= False; *nearzero= False; if (dim < 2) { qhull_fatal(21); } else if (dim == 2) { det= det2_(rows[0][0], rows[0][1], rows[1][0], rows[1][1]); if (fabs_(det) < qh NEARzero[1]) /* not really correct, what should this be? */ *nearzero= True; }else if (dim == 3) { det= det3_(rows[0][0], rows[0][1], rows[0][2], rows[1][0], rows[1][1], rows[1][2], rows[2][0], rows[2][1], rows[2][2]); if (fabs_(det) < qh NEARzero[2]) /* not really correct, what should this be? */ *nearzero= True; }else { qh_gausselim(rows, dim, dim, &sign, nearzero); /* if nearzero, diagonal still ok*/ det= 1.0; for (i= dim; i--; ) det *= (rows[i])[i]; if (sign) det= -det; } return det; } /* determinant */ /*------------------------------------------------- -detsimplex- compute determinant of a simplex with point apex and base points uses qh gm_matrix/qh gm_row (assumes they're big enough) uses dim coordinates of point and vertex->point returns: if dim == 2 or 3 nearzero iff determinant < qh NEARzero[dim-1] (not quite correct) if dim >= 4 nearzero iff diagonal[k] < qh NEARzero[k] */ realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) { pointT *coorda, *coordp, *gmcoord, *point, **pointp; coordT **rows; int k, i=0; realT det= 0.0; zinc_(Zdetsimplex); gmcoord= qh gm_matrix; rows= qh gm_row; FOREACHpoint_(points) { if (i == dim) break; rows[i++]= gmcoord; coordp= point; coorda= apex; for(k= dim; k--; ) *(gmcoord++)= *coordp++ - *coorda++; } if (i < dim) { qhull_fatal(22); } det= qh_determinant (rows, dim, nearzero); trace2((qh ferr, "qh_detsimplex: det=%2.2g for point p%d, dimension %d, nearzero? %d\n", det, qh_pointid(apex), dim, *nearzero)); return det; } /* detsimplex */ /*------------------------------------------- -distplane- get distance from point to facet returns: positive if point is above facet (i.e., outside) can not qhull_fatal (for sortfacets) */ void qh_distplane (pointT *point, facetT *facet, realT *dist) { coordT *normal= facet->normal, *coordp, randr; int k; switch(qh hull_dim){ case 2: *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1]; break; case 3: *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2]; break; case 4: *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]; break; case 5: *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]; break; case 6: *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]; break; case 7: *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]; break; case 8: *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7]; break; default: *dist= facet->offset; coordp= point; for (k= qh hull_dim; k--; ) *dist += *coordp++ * *normal++; break; } zinc_(Zdistplane); if (!qh RANDOMdist && qh IStracing < 4) return; if (qh RANDOMdist) { randr= qh_RANDOMint; *dist += (2.0 * randr / qh_RANDOMmax - 1.0) * qh RANDOMfactor * qh maxmaxcoord; } /* if (qh IStracing >= 4) { fprintf (qh ferr, "qh_distplane: "); fprintf (qh ferr, qh_REAL_1, *dist); fprintf (qh ferr, "from p%d to f%d\n", qh_pointid(point), facet->id); } */ return; } /* distplane */ /*-------------------------------------------------- -divzero -- divide by a number that's nearly zero mindenom1= minimum denominator for dividing into 1.0 returns: zerodiv and 0.0 if it would overflow */ realT qh_divzero (realT numer, realT denom, realT mindenom1, boolT *zerodiv) { realT temp, numerx, denomx; if (numer < mindenom1 && numer > -mindenom1) { numerx= fabs_(numer); denomx= fabs_(denom); if (numerx < denomx) { *zerodiv= False; return numer/denom; }else { *zerodiv= True; return 0.0; } } temp= denom/numer; if (temp > mindenom1 || temp < -mindenom1) { *zerodiv= False; return numer/denom; }else { *zerodiv= True; return 0.0; } } /* divzero */ /*------------------------------------------------- -facetcenter- return Voronoi center for a facet's vertices */ pointT *qh_facetcenter (setT *vertices) { setT *points= qh_settemp (qh_setsize (vertices)); vertexT *vertex, **vertexp; pointT *center; FOREACHvertex_(vertices) qh_setappend (&points, vertex->point); center= qh_voronoi_center (qh hull_dim-1, points); qh_settempfree (&points); return center; } /* facetcenter */ /*------------------------------------------------- -findbest- find best facet for point starting at a facet (not flipped!) if bestoutside, searches all facets else stops at first outside MINoutside is DISTround in precise case if firstid, searches facets with ids >= firstid searches old facets if bestoutside || (not outside and imprecise) searches all neighbors of coplanar and flipped facets searchdist is arbitrarily set to min_vertex+max_outside+DISTround max_outside is needed for setting facet->maxoutside returns: if !firstid, updates facet->maxoutside for good, visited facets distance to facet isoutside true if point is outside of facet bumps visit_id and seen flags notes: uses visitid and seen statistics collected here for partitions, caller does outside/coplanar caller traces the results #2 after setfacetplane in D3, optimized for outside points and !bestoutside #1 when merging in D3 see also partitionall() notes on searchdist: searchdist needed since vertex neighbors can be geometric neighbors of facet if searchdist=DISTround, gets stuck for rbox 50 W1e-3 D7 | qhull A-0.99 W0.2 if !BESToutside and merging, gets stuck for rbox 1000 W8e-6 | qhull C-0 because nearly coplanar widens when the point is outside of the facets searching all new facets does not prevent !BESToutside getting stuck check_maxoutside can also get stuck, should keep coplanars */ facetT *qh_findbest (pointT *point, facetT *facet, boolT bestoutside, unsigned firstid, realT *dist, boolT *isoutside, int *numpart) { realT bestdist, searchdist; facetT *neighbor, **neighborp, *bestfacet; setT *search= NULL; int oldtrace= qh IStracing; boolT checkmax= (boolT)(bestoutside && !firstid && qh_MAXoutside && (qh MERGING || qh APPROXhull)); if (qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point)) { qh IStracing= qh TRACElevel; /* fprintf (qh ferr, "qh_findbest: point p%d starting at f%d bestoutside? %d firstid %d\n", qh TRACEpoint, facet->id, bestoutside, firstid); fprintf (qh ferr, " Last point added to hull was p%d.", qh furthest_id); fprintf(qh ferr, " Last merge was #%d.\n", zzval_(Ztotmerge)); */ } searchdist= - qh min_vertex + qh max_outside + 2* qh DISTround; *isoutside= True; *numpart= 1; qh_distplane (point, facet, dist); bestdist= *dist; bestfacet= facet; if (!bestoutside && *dist >= qh MINoutside) goto LABELreturn_best; #if qh_MAXoutside if (checkmax && (!qh ONLYgood || facet->good) && *dist > facet->maxoutside) facet->maxoutside= *dist; #endif facet->visitid= ++qh visit_id; facet->seen= False; if (True) { /* directed search for bestfacet */ LABELrepeat: /* facet->seen if clearly worse */ trace4((qh ferr, "qh_findbest: neighbors of f%d\n", facet->id)); FOREACHneighbor_(facet) { if ((int)neighbor->visitid == qh visit_id) continue; if (neighbor->id < firstid) { neighbor->seen= True; continue; } neighbor->visitid= qh visit_id; neighbor->seen= False; if (neighbor->flipped) continue; (*numpart)++; qh_distplane (point, neighbor, dist); if (!bestoutside && *dist >= qh MINoutside) { bestfacet= neighbor; goto LABELreturn_best; } #if qh_MAXoutside if (checkmax && (!qh ONLYgood || neighbor->good) && *dist > neighbor->maxoutside) neighbor->maxoutside= *dist; #endif if (*dist >= bestdist) { /* >= for exact coplanar */ bestdist= *dist; bestfacet= neighbor; if (*dist > bestdist + searchdist) facet->seen= True; facet= neighbor; goto LABELrepeat; }else if (*dist < bestdist - searchdist) neighbor->seen= True; } } do { /* search horizon of facet */ FOREACHneighbor_(facet) { if ((int)neighbor->visitid == qh visit_id) { if (!neighbor->seen) { neighbor->seen= True; if (!search) search= qh_settemp (qh TEMPsize); qh_setappend (&search, neighbor); } continue; } neighbor->visitid= qh visit_id; neighbor->seen= True; if (neighbor->flipped) { if (!search) search= qh_settemp (qh TEMPsize); qh_setappend (&search, neighbor); continue; } if (neighbor->id < firstid) { if (!(bestoutside+qh APPROXhull+qh PREmerge)) continue; }else zinc_(Zpartneighbor); (*numpart)++; qh_distplane (point, neighbor, dist); if (!bestoutside && *dist >= qh MINoutside) { bestfacet= neighbor; goto LABELreturn_best; } #if qh_MAXoutside if (checkmax && *dist > neighbor->maxoutside) neighbor->maxoutside= *dist; #endif if (*dist >= bestdist - searchdist) { if (!search) search= qh_settemp (qh TEMPsize); qh_setappend (&search, neighbor); if (*dist > bestdist) { bestdist= *dist; bestfacet= neighbor; } } } }while ((facet= (facetT *)qh_setdellast (search))); *dist= bestdist; if (!bestoutside || bestdist < qh MINoutside) *isoutside= False; LABELreturn_best: if (search) qh_settempfree (&search); qh IStracing= oldtrace; return bestfacet; } /* findbest */ /*------------------------------------------------- -findgooddist- find best good facet visible for point from facetA assumes facetA is visible from point uses qh visit_id and qh visible_list (but doesn't set visible) returns: furthest distance to good facet, if any bumps visit_id and seen flags */ facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp) { realT bestdist= -REALmax, dist; facetT *neighbor, **neighborp, *bestfacet=NULL, *facet; boolT goodseen= False; if (facetA->good) { zinc_(Zverifypart); qh_distplane (point, facetA, &bestdist); bestfacet= facetA; goodseen= True; } qh_removefacet (facetA); qh_appendfacet (facetA); qh visible_list= facetA; facetA->visitid= ++qh visit_id; FORALLfacet_(qh visible_list) { FOREACHneighbor_(facet) { if ((int)neighbor->visitid == qh visit_id) continue; neighbor->visitid= qh visit_id; if (goodseen && !neighbor->good) continue; zinc_(Zverifypart); qh_distplane (point, neighbor, &dist); if (dist > 0) { qh_removefacet (neighbor); qh_appendfacet (neighbor); if (neighbor->good) { goodseen= True; if (dist > bestdist) { bestdist= dist; bestfacet= neighbor; } } } } } if (bestfacet) { *distp= bestdist; trace2((qh ferr, "qh_findgooddist: p%d is %2.2g above good facet f%d\n", qh_pointid(point), bestdist, bestfacet->id)); return bestfacet; } trace4((qh ferr, "qh_findgooddist: no good facet for p%d above f%d\n", qh_pointid(point), facetA->id)); return NULL; } /* findgooddist */ /*------------------------------------------------- -gausselim- Gaussian elimination with partial pivoting coordT data in rows assumes numrow <= numcol returns: rows is upper triangular (includes row exchanges) flips sign for each row exchange sets nearzero if pivot[k] < qh NEARzero[k], else False. if nearzero, the determinant's sign may be incorrect. */ void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) { realT *ai, *ak, *rowp, *pivotrow; realT n, pivot, pivot_abs= 0.0, temp; int i, j, k, pivoti, flip=0, tempint; *nearzero= False; for(k= 0; k < numrow; k++) { pivot_abs= fabs_((rows[k])[k]); pivoti= k; for(i= k+1; i < numrow; i++) { if ((temp= fabs_((rows[i])[k])) > pivot_abs) { pivot_abs= temp; pivoti= i; } } if (pivoti != k) { rowp= rows[pivoti]; rows[pivoti]= rows[k]; rows[k]= rowp; tempint = (int)*sign; tempint ^= 1; *sign = (boolT)tempint; flip ^= 1; } if (pivot_abs <= qh NEARzero[k]) { *nearzero= True; if (pivot_abs == 0.0) { /* remainder of column == 0 */ /* if (qh IStracing >= 4) { fprintf (qh ferr, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround); qh_printmatrix (qh ferr, "Matrix:", rows, numrow, numcol); } */ zzinc_(Zgauss0); goto LABELnextcol; } } pivotrow= rows[k] + k; pivot= *pivotrow++; /* signed value of pivot, and remainder of row */ for(i= k+1; i < numrow; i++) { ai= rows[i] + k; ak= pivotrow; n= (*ai++)/pivot; /* divzero() not needed since |pivot| >= |*ai| */ for(j= numcol - (k+1); j--; ) *ai++ -= n * *ak++; } LABELnextcol: ; } wmin_(Wmindenom, pivot_abs); /* last pivot element */ if (qh IStracing >= 5) qh_printmatrix (qh ferr, "qh_gausselem: result", rows, numrow, numcol); } /* gausselim */ /*---------------------------------------------- -getangle- returns the dot product of two, qh hull_dim vectors may be > 1.0 or < -1.0 */ realT qh_getangle(pointT *vect1, pointT *vect2) { realT angle= 0; int k; for(k= qh hull_dim; k--; ) angle += *vect1++ * *vect2++; trace4((qh ferr, "qh_getangle: %2.2g\n", angle)); return(angle); } /* getangle */ /*---------------------------------------------- -getcenter- gets arithmetic center of a set of vertices as a new point assumes normal_size is in short memory */ pointT *qh_getcenter(setT *vertices) { int k; pointT *center, *coord; vertexT *vertex, **vertexp; int count= qh_setsize(vertices); if (count < 2) qhull_fatal(23); center= (pointT *)qh_memalloc(qh normal_size); for (k=0; k < qh hull_dim; k++) { coord= center+k; *coord= 0.0; FOREACHvertex_(vertices) *coord += vertex->point[k]; *coord /= count; } return(center); } /* getcenter */ /*---------------------------------------------- -getcentrum- returns the centrum for a facet as a new point assumes normal_size is in short memory */ pointT *qh_getcentrum(facetT *facet) { realT dist; pointT *centrum, *point; point= qh_getcenter(facet->vertices); zinc_(Zcentrumtests); qh_distplane (point, facet, &dist); centrum= qh_projectpoint(point, facet, dist); qh_memfree(point, qh normal_size); trace4((qh ferr, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n", facet->id, qh_setsize(facet->vertices), dist)); return centrum; } /* getcentrum */ /*------------------------------------------------- -gram_schmidt- implements Gram-Schmidt orthogonalization by rows overwrites rows[dim][dim] returns: false if gets a zero norm notes: see Golub & van Loan Algorithm 6.2-2 overflow due to small divisors not handled */ boolT qh_gram_schmidt(int dim, realT **row) { realT *rowi, *rowj, norm; int i, j, k; for(i=0; i < dim; i++) { rowi= row[i]; for (norm= 0.0, k= dim; k--; rowi++) norm += *rowi * *rowi; norm= sqrt(norm); wmin_(Wmindenom, norm); if (norm == 0.0) /* either 0 or overflow due to sqrt */ return False; for(k= dim; k--; ) *(--rowi) /= norm; for(j= i+1; j < dim; j++) { rowj= row[j]; for(norm= 0.0, k=dim; k--; ) norm += *rowi++ * *rowj++; for(k=dim; k--; ) *(--rowj) -= *(--rowi) * norm; } } return True; } /* gram_schmidt */ /*-------------------------------------------------- -inthresholds- return True if normal within qh lower_/upper_threshold returns: angle cos to a threshold border (may be NULL, invalid if qh SPLITthresholds) */ boolT qh_inthresholds (coordT *normal, realT *angle) { boolT within= True; int k; if (angle) *angle= 0.0; for(k= 0; k < qh hull_dim; k++) { if (qh lower_threshold[k] > -REALmax/2) { if (normal[k] < qh lower_threshold[k]) within= False; if (angle) *angle += normal[k] * qh lower_threshold[k]; } if (qh upper_threshold[k] < REALmax/2) { if (normal[k] > qh upper_threshold[k]) within= False; if (angle) *angle += normal[k] * qh upper_threshold[k]; } } return within; } /* inthresholds */ /*-------------------------------------------------- -maxabsval -- return pointer to maximum absolute value of a dim vector returns NULL if dim==0 */ realT *qh_maxabsval (realT *normal, int dim) { realT maxval= -REALmax; realT *maxp= NULL, *colp, absval; int k; for (k= dim, colp= normal; k--; colp++) { absval= fabs_(*colp); if (absval > maxval) { maxval= absval; maxp= colp; } } return maxp; } /* maxabsval */ /*------------------------------------------------- -maxmin- collects the maximum and minimum points of input into a set determines maximum roundoff errors returns: returns a temporary set, without qh GOODpoint points are not unique */ setT *qh_maxmin(pointT *points, int numpoints, int dimension) { int k; realT maxsum= 0.0, maxcoord, temp, maxdistsum; realT maxneg= REALmax, maxpos= -REALmax; pointT *minimum, *maximum, *point, *pointtemp; setT *set; set= qh_settemp(2*dimension); for(k= 0; k < dimension; k++) { if (points == qh GOODpointp) minimum= maximum= points + qh hull_dim; else minimum= maximum= points; FORALLpoint_(points, numpoints) { if (point == qh GOODpointp) continue; if (maximum[k] < point[k]) maximum= point; else if (minimum[k] > point[k]) minimum= point; } maxcoord= fmax_(maximum[k], -minimum[k]); if (qh GOODpointp) { temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]); maximize_(maxcoord, temp); } maximize_(qh maxmaxcoord, maxcoord); maxsum += maxcoord; maximize_(maxpos, maximum[k]); minimize_(maxneg, minimum[k]); qh_setappend (&set, maximum); qh_setappend (&set, minimum); /* calculation of qh NEARzero is based on error formula 4.4-13 of Golub & van Loan, authors say n^3 can be ignored and 10 be used in place of rho */ qh NEARzero[k]= 80 * maxsum * REALepsilon; } /* calculate roundoff error according to Lemma 3.2-1 of Golub and van Loan "Matrix Computation" use sqrt(dim) since one vector is normalized */ maxdistsum= sqrt (qh hull_dim) * qh maxmaxcoord; if (!qh SETroundoff) { qh DISTround= REALepsilon * (qh hull_dim * maxdistsum * 1.01 + qh maxmaxcoord); /* for offset */ if (qh RANDOMdist) qh DISTround += qh RANDOMfactor * qh maxmaxcoord; } qh MINdenom= qh MINdenom_1 * qh maxmaxcoord; qh MINdenom_1_2= sqrt (qh MINdenom_1 * qh hull_dim) ; /* if will be normalized */ qh MINdenom_2= qh MINdenom_1_2 * qh maxmaxcoord; if (qh premerge_cos < REALmax/2) /* for inner product */ qh premerge_cos -= 1.01 * qh hull_dim * REALepsilon; if (qh postmerge_cos < REALmax/2) qh postmerge_cos -= 1.01 * qh hull_dim * REALepsilon; qh premerge_centrum += 2 * qh DISTround; /*2 for centrum and distplane()*/ qh postmerge_centrum += 2 * qh DISTround; { /* compute ONEmerge, max vertex offset for merging simplicial facets */ realT maxangle= 1.0, maxrho; minimize_(maxangle, qh premerge_cos); minimize_(maxangle, qh postmerge_cos); /* max diameter * sin theta + DISTround for vertex to its hyperplane */ qh ONEmerge= sqrt (qh hull_dim) * (maxpos - maxneg) * sqrt (1.0 - maxangle * maxangle) + qh DISTround; maxrho= qh hull_dim * qh premerge_centrum + qh DISTround; maximize_(qh ONEmerge, maxrho); maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround; maximize_(qh ONEmerge, maxrho); } if (!qh APPROXhull) { /* user may specify qh MINoutside */ qh MINoutside= qh premerge_centrum - qh DISTround; if (qh premerge_cos < REALmax/2) maximize_(qh MINoutside, (1- qh premerge_cos) * qh maxmaxcoord); } if (qh MINvisible > REALmax/2) qh MINvisible= qh DISTround; /* if (qh MINvisible > qh MINoutside + 3*REALepsilon && !qh BESToutside && !qh FORCEoutput) fprintf (qh ferr, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g. Flipped facets are likely.\n", qh MINvisible, qh MINoutside); */ qh max_vertex= qh DISTround; qh min_vertex= -qh DISTround; /* if (qh IStracing >=1) qh_printpoints (qh ferr, "qh_maxmin: found the max and min points (by dim):", set); */ /* numeric constants reported in printsummary */ return(set); } /* maxmin */ /*------------------------------------------------- -maxsimplex- determines maximum simplex for a set of points assumes at least pointsneeded points in points skips qh GOODpointp (assumes that it isn't in maxpoints) starts from points already in simplex returns: temporary set of dim+1 points notes: maximizes determinate for x,y,z,w, etc. uses maxpoints as long as determinate is clearly non-zero */ void qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) { pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL; boolT nearzero, maxnearzero= False; int k, sizinit; realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax; sizinit= qh_setsize (*simplex); if (sizinit < 2) { if (qh_setsize (maxpoints) >= 2) { FOREACHpoint_(maxpoints) { if (maxcoord < point[0]) { maxcoord= point[0]; maxx= point; } if (mincoord > point[0]) { mincoord= point[0]; minx= point; } } }else { FORALLpoint_(points, numpoints) { if (point == qh GOODpointp) continue; if (maxcoord < point[0]) { maxcoord= point[0]; maxx= point; } if (mincoord > point[0]) { mincoord= point[0]; minx= point; } } } qh_setunique (simplex, minx); if (qh_setsize (*simplex) < 2) qh_setunique (simplex, maxx); sizinit= qh_setsize (*simplex); if (sizinit < 2) qhull_fatal(24); } for(k= sizinit; k < dim+1; k++) { maxpoint= NULL; maxdet= -REALmax; FOREACHpoint_(maxpoints) { if (!qh_setin (*simplex, point)) { det= qh_detsimplex(point, *simplex, k, &nearzero); if ((det= fabs_(det)) > maxdet) { maxdet= det; maxpoint= point; maxnearzero= nearzero; } } } if (!maxpoint || maxnearzero) { zinc_(Zsearchpoints); if (!maxpoint) { trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex\n", k)); }else { trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n", k+1, qh_pointid(maxpoint), maxdet)); } FORALLpoint_(points, numpoints) { if (point == qh GOODpointp) continue; if (!qh_setin (*simplex, point)) { det= qh_detsimplex(point, *simplex, k, &nearzero); if ((det= fabs_(det)) > maxdet) { maxdet= det; maxpoint= point; maxnearzero= nearzero; } } } } /* !maxpoint */ if (!maxpoint) qhull_fatal(25); qh_setappend(simplex, maxpoint); trace1((qh ferr, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n", qh_pointid(maxpoint), k, maxdet)); } } /* maxsimplex */ /*-------------------------------------------------- -minabsval -- return min absolute value of a dim vector */ realT qh_minabsval (realT *normal, int dim) { realT minval= 0; realT maxval= 0; realT *colp; int k; for (k= dim, colp= normal; k--; colp++) { maximize_(maxval, *colp); minimize_(minval, *colp); } return fmax_(maxval, -minval); } /* maxabsval */ /*-------------------------------------------------- -normalize -- normalize a vector qh MINdenom/MINdenom1 upper limits for divide overflow returns: normalized vector flips sign if !toporient if zero norm sets all elements to sqrt(1.0/dim) if divide by zero (divzero ()) sets largest element to +/-1 bumps Znearlysingular */ void qh_normalize (coordT *normal, int dim, boolT toporient) { int k; realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3; boolT zerodiv; norm1= normal+1; norm2= normal+2; norm3= normal+3; if (dim == 2) norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1)); else if (dim == 3) norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)); else if (dim == 4) { norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2) + (*norm3)*(*norm3)); }else if (dim > 4) { norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2) + (*norm3)*(*norm3); for (k= dim-4, colp= normal+4; k--; colp++) norm += (*colp) * (*colp); norm= sqrt(norm); } wmin_(Wmindenom, norm); if (norm > qh MINdenom) { if (!toporient) norm= -norm; *normal /= norm; *norm1 /= norm; if (dim == 2) ; /* all done */ else if (dim == 3) *norm2 /= norm; else if (dim == 4) { *norm2 /= norm; *norm3 /= norm; }else if (dim >4) { *norm2 /= norm; *norm3 /= norm; for (k= dim-4, colp= normal+4; k--; ) *colp++ /= norm; } }else if (norm == 0.0) { temp= sqrt (1.0/dim); for (k= dim, colp= normal; k--; ) *colp++ = temp; }else { if (!toporient) norm= -norm; for (k= dim, colp= normal; k--; colp++) { /* k used below */ temp= qh_divzero (*colp, norm, qh MINdenom_1, &zerodiv); if (!zerodiv) *colp= temp; else { maxp= qh_maxabsval(normal, dim); temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0); for (k= dim, colp= normal; k--; colp++) *colp= 0.0; *maxp= temp; zzinc_(Znearlysingular); trace0((qh ferr, "qh_normalize: norm=%2.2g too small\n", norm)); return; } } } } /* normalize */ /*------------------------------------------- -orientoutside- make facet outside oriented via qh interior_point returns True if reversed orientation. */ boolT qh_orientoutside (facetT *facet) { int k; realT dist; qh_distplane (qh interior_point, facet, &dist); if (dist > 0) { for (k= qh hull_dim; k--; ) facet->normal[k]= -facet->normal[k]; facet->offset= -facet->offset; return True; } return False; } /* orientoutside */ /*------------------------------------------- -pointdist- distance between points */ coordT qh_pointdist(pointT *point1, pointT *point2, int dim) { coordT dist, diff; int k; dist= 0.0; for (k= dim; k--; ) { diff= *point1++ - *point2++; dist += diff * diff; } return(sqrt(dist)); } /* pointdist */ /*------------------------------------------------- -printmatrix- print matrix given by row vectors print a vector by (fp, "", &vect, 1, len) */ void qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol) { realT *rowp; int i,k; fprintf (fp, "%s\n", string); for (i= 0; inormal; for(k= qh hull_dim; k--; ) *(np++)= *point++ - dist * *normal++; return(newpoint); } /* projectpoint */ /*------------------------------------------------- -projectpoints- project along one or more dimensions delete dimension k if project[k] == -1 add dimension k if project[k] == 1 n is size of project points, numpoints, dim is old points newpoints, newdim is buffer for new points (already allocated) newpoints may be points if only adding dimension at end */ void qh_projectpoints (signed char *project, int n, realT *points, int numpoints, int dim, realT *newpoints, int newdim) { int testdim= dim, oldk=0, newk=0, i,j=0,k; realT *newp, *oldp; for (k= 0; k= dim) continue; oldp= points+oldk; }else oldp= points+oldk++; for (i=numpoints; i--; ) { *newp= *oldp; newp += newdim; oldp += dim; } } if (oldk >= dim) break; } trace1((qh ferr, "qh_projectpoints: projected %d points from dim %d to dim %d\n", numpoints, dim, newdim)); } /* projectpoints */ /*------------------------------------------------- -randomfactor- return a random factor within qh RANDOMmax of 1.0 RANDOMa/b definedin global.c */ realT qh_randomfactor (void) { realT randr; randr= qh_RANDOMint; return randr * qh RANDOMa + qh RANDOMb; } /* randomfactor */ /*------------------------------------------------- -randommatrix- generate a random dimXdim matrix in range (-1,1) assumes buffer is dim+1Xdim returns: returns row vector for buffer plus row[dim] for scratch */ void qh_randommatrix (realT *buffer, int dim, realT **row) { int i, k; realT **rowi, *coord, realr; coord= buffer; rowi= row; for (i=0; i REALmax/2 && newlow < -REALmax/2) continue; low= REALmax; high= -REALmax; for (i= numpoints, coord= points+k; i--; coord += dim) { minimize_(low, *coord); maximize_(high, *coord); } if (newhigh > REALmax/2) newhigh= high; if (newlow < -REALmax/2) newlow= low; scale= qh_divzero (newhigh - newlow, high - low, qh MINdenom_1, &nearzero); if (nearzero) qhull_fatal(31); shift= (newlow * high - low * newhigh)/(high-low); coord= points+k; for (i= numpoints; i--; coord += dim) *coord= *coord * scale + shift; coord= points+k; if (newlow < newhigh) { mincoord= newlow; maxcoord= newhigh; }else { mincoord= newhigh; maxcoord= newlow; } for (i= numpoints; i--; coord += dim) { minimize_(*coord, maxcoord); /* because of roundoff error */ maximize_(*coord, mincoord); } trace0((qh ferr, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n", k, low, high, newlow, newhigh, numpoints, scale, shift)); } } /* scalepoints */ /*------------------------------------------------- -setfacetplane- sets the hyperplane for a facet uses global buffers qh gm_matrix and qh gm_row overwrites facet->normal if already defined updates Wnewvertex if PRINTstatistics */ void qh_setfacetplane(facetT *facet) { pointT *point; vertexT *vertex, **vertexp; int k,i=0; int normsize= qh normal_size; int oldtrace = 0; realT dist; void **freelistp; coordT *coord, *gmcoord= qh gm_matrix; pointT *point0= ((vertexT*)SETfirst_(facet->vertices))->point; boolT nearzero; zzinc_(Zsetplane); if (!facet->normal) float_qh_memalloc_(normsize, freelistp, facet->normal); if (facet == qh tracefacet) { oldtrace= qh IStracing; qh IStracing= 5; /* fprintf (qh ferr, "qh_setfacetplane: facet f%d created.\n", facet->id); fprintf (qh ferr, " Last point added to hull was p%d.", qh furthest_id); if (zzval_(Ztotmerge)) fprintf(qh ferr, " Last merge was #%d.", zzval_(Ztotmerge)); fprintf (qh ferr, "\n\nSorry, qh_printsummary no longer supported:\n"); fprintf (qh ferr, "\n\nCurrent summary is:\n"); qh_printsummary (qh ferr); */ } if (qh hull_dim <= 4) { if (qh RANDOMdist) { FOREACHvertex_(facet->vertices) { qh gm_row[i++]= gmcoord; coord= vertex->point; for (k= qh hull_dim; k--; ) *(gmcoord++)= *coord++ * qh_randomfactor(); } }else { FOREACHvertex_(facet->vertices) qh gm_row[i++]= vertex->point; } qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, (boolT)facet->toporient, facet->normal, &facet->offset); }else { FOREACHvertex_(facet->vertices) { if (vertex->point != point0) { qh gm_row[i++]= gmcoord; coord= vertex->point; point= point0; for(k= qh hull_dim; k--; ) *(gmcoord++)= *coord++ - *point++; } } qh gm_row[i]= gmcoord; /* for areasimplex */ if (qh RANDOMdist) { gmcoord= qh gm_matrix; for (i= qh hull_dim-1; i--; ) { for (k= qh hull_dim; k--; ) *(gmcoord++) *= qh_randomfactor(); } } qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, (boolT)facet->toporient, facet->normal, &facet->offset, &nearzero); if (nearzero) { if (qh_orientoutside (facet)) { trace0((qh ferr, "qh_setfacetplane: flipped orientation after testing interior_point\n")); /* this is part of using Gaussian Elimination. For example in 5-d 1 1 1 1 0 1 1 1 1 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 norm= 0.38 0.38 -0.76 0.38 0 has a determinate of 1, but g.e. after subtracting pt. 0 has 0's in the diagonal, even with full pivoting. It does work if you subtract pt. 4 instead. */ } } } if (qh PRINTstatistics) { FOREACHvertex_(facet->vertices) { if (vertex->point != point0) { zinc_(Zdiststat); qh_distplane(vertex->point, facet, &dist); dist= fabs_(dist); zinc_(Znewvertex); wadd_(Wnewvertex, dist); if (dist > wval_(Wnewvertexmax)) { wval_(Wnewvertexmax)= dist; maximize_(qh max_outside, dist); } } } } if (qh IStracing >= 3) { /* fprintf (qh ferr, "qh_setfacetplane: f%d offset %2.2g normal: ", facet->id, facet->offset); for (k=0; knormal[k]); fprintf (qh ferr, "\n"); */ } if (facet == qh tracefacet) qh IStracing= oldtrace; } /* setfacetplane */ /*------------------------------------------------- -sethyperplane_det- set normalized hyperplane equation from oriented simplex dim X dim array indexed by rows[], one row per point, point0 is any row only defined for dim == 2..4 returns: offset, normal bumps Znearlysingular if normalization fails rows[] is not modified notes: solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane offset places point0 on the hyperplane toporient just flips all signs, so orientation is correct see Bower & Woodworth, A programmer's geometry, Butterworths 1983. */ void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, boolT toporient, coordT *normal, realT *offset) { if (dim == 2) { normal[0]= dY(1,0); normal[1]= dX(0,1); qh_normalize (normal, dim, toporient); *offset= -(point0[0]*normal[0]+point0[1]*normal[1]); }else if (dim == 3) { normal[0]= det2_(dY(2,0), dZ(2,0), dY(1,0), dZ(1,0)); normal[1]= det2_(dX(1,0), dZ(1,0), dX(2,0), dZ(2,0)); normal[2]= det2_(dX(2,0), dY(2,0), dX(1,0), dY(1,0)); qh_normalize (normal, dim, toporient); *offset= -(point0[0]*normal[0] + point0[1]*normal[1] + point0[2]*normal[2]); }else if (dim == 4) { normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0), dY(1,0), dZ(1,0), dW(1,0), dY(3,0), dZ(3,0), dW(3,0)); normal[1]= det3_(dX(2,0), dZ(2,0), dW(2,0), dX(1,0), dZ(1,0), dW(1,0), dX(3,0), dZ(3,0), dW(3,0)); normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0), dX(1,0), dY(1,0), dW(1,0), dX(3,0), dY(3,0), dW(3,0)); normal[3]= det3_(dX(2,0), dY(2,0), dZ(2,0), dX(1,0), dY(1,0), dZ(1,0), dX(3,0), dY(3,0), dZ(3,0)); qh_normalize (normal, dim, toporient); *offset= -(point0[0]*normal[0] + point0[1]*normal[1] + point0[2]*normal[2] + point0[3]*normal[3]); } } /* sethyperplane_det */ /*------------------------------------------------- -sethyperplane_gauss- set normalized hyperplane equation from oriented simplex (dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0) returns: offset, normal if nearzero, bumps Znearlysingular orientation may be incorrect because of incorrect sign flips in gausselim notes: solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1] or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0] i.e., N is normal to the hyperplane, and the unnormalized distance to [0 .. 1] is either 1 or 0 offset places point0 on the hyperplane */ void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) { coordT *pointcoord, *normalcoef; int k, tempint; boolT sign= (boolT)!toporient, nearzero2= False; qh_gausselim(rows, dim-1, dim, &sign, nearzero); for(k= dim-1; k--; ) { if ((rows[k])[k] < 0) { tempint = (int)sign; tempint ^= 1; sign = (boolT)tempint; } } if (*nearzero) { zinc_(Znearlysingular); trace0((qh ferr, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane.\n")); qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2); }else { qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2); if (nearzero2) { zinc_(Znearlysingular); trace0((qh ferr, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization\n")); } } if (nearzero2) *nearzero= True; qh_normalize(normal, dim, True); pointcoord= point0; normalcoef= normal; *offset= -(*pointcoord++ * *normalcoef++); for(k= dim-1; k--; ) *offset -= *pointcoord++ * *normalcoef++; } /* sethyperplane_gauss */ /*------------------------------------------- -voronoi_center- return Voronoi center for a set of points dim is the orginal dimension of the points notes: if non-simplicial, returns center for max simplex of points from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65 */ pointT *qh_voronoi_center (int dim, setT *points) { pointT *point, **pointp, *point0; pointT *center= (pointT *)qh_memalloc (qh center_size); setT *simplex; int i, j, k, num, size= qh_setsize(points); coordT *gmcoord; realT *diffp, sum2, *sum2row, *sum2p, det, factor; boolT nearzero, infinite; if (size == dim+1) simplex= points; else if (size < dim+1) qhull_fatal(32); else { simplex= qh_settemp (dim+1); qh_maxsimplex (dim, points, NULL, 0, &simplex); } num= qh_setsize (simplex); point0= (pointT *)SETfirst_(simplex); gmcoord= qh gm_matrix; for (k=0; k= 3) { /* fprintf (qh ferr, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor); qh_printmatrix (qh ferr, "center:", ¢er, 1, dim); if (qh IStracing >= 5) { qh_printpoints (qh ferr, "points", simplex); FOREACHpoint_(simplex) fprintf (qh ferr, "p%d dist %.2g, ", qh_pointid (point), qh_pointdist (point, center, dim)); fprintf (qh ferr, "\n"); } */ } } if (simplex != points) qh_settempfree (&simplex); return center; } /* voronoi_center */ /*************************************************************************/ /****************** implementation code from stat.c **********************/ /*************************************************************************/ /* stat.c - contains all statistics that are collected for qhull see README and stat.h copyright (c) 1993-1994, The Geometry Center */ #if qh_QHpointer qhstatT *qh_qhstat=NULL; /* global data structure */ #else qhstatT qh_qhstat ={0}; /* remove "={0}" if this causes a compiler error */ #endif /*------------------------------------------------- -allstatA -- define statistics in groups of 20 (otherwise, 'gcc -O2' uses too much memory) uses qhstat next */ void qh_allstatA (void) { /* zdef_(type,name,doc,average) */ zzdef_(zdoc, Zdoc2, "precision statistics", -1); zdef_(zinc, Znewvertex, NULL, -1); zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet (not 0s)", Znewvertex); zdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1); zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1); zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1); zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1); qhstat precision= qhstat next; zzdef_(zdoc, Zdoc3, "precision problems", -1); zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1); zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1); zzdef_(zinc, Zflippedfacets, "flipped facets", -1); zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1); zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1); zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1); zzdef_(zinc, Zback0, "zero divisors during back substitute", -1); zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1); zzdef_(zinc, Zmultimatch, "ridges with multiple neighbors (same flip)", -1); zzdef_(zinc, Zmultiflip, "ridges with multiple neighbors (diff flip)", -1); } void qh_allstatB (void) { zzdef_(zdoc, Zdoc1, "summary information", -1); zdef_(zinc, Zvertices, "number of vertices in output", -1); zdef_(zinc, Znumfacets, "number of facets in output", -1); zdef_(zinc, Znumridges, "number of ridges in output", -1); zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets); zdef_(zmax, Zmaxridges, "maximum number of ridges", -1); zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets); zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1); zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets); zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1); zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices); zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1); zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1); zdef_(zinc, Ztotvertices, "vertices created altogether", -1); zzdef_(zinc, Zsetplane, "facets created altogether", -1); zdef_(zinc, Ztotridges, "ridges created altogether", -1); zdef_(zinc, Zpostfacets, "facets before post merge", -1); zdef_(zinc, Zangle, NULL, -1); zdef_(wadd, Wangle, "average angle (cosine) for all ridges", Zangle); zdef_(wmax, Wanglemax, "maximum angle (cosine) of a ridge", -1); zdef_(wmin, Wanglemin, "minimum angle (cosine) of a ridge", -1); zdef_(zdoc, Zdoc9, "build hull statistics", -1); zdef_(zinc, Zdetsimplex, "determinates computed (initial hull)", -1); zzdef_(zinc, Zprocessed, "points processed", -1); zdef_(zinc, Ztotvisible, "visible facets for all new vertices", -1); zdef_(zinc, Zinsidevisible, "visible facets without an horizon neighbor", -1); zdef_(zinc, Ztothorizon, "horizon facets for all new vertices", -1); zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed); zdef_(wadd, Wnewbalance2, " standard deviation", -1); zdef_(wadd, Wpbalance, "average partition balance", Zpbalance); zdef_(wadd, Wpbalance2, " standard deviation", -1); zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1); zdef_(zinc, Znotmax, "points ignored (not above max_outside)", -1); zdef_(zinc, Znotgood, "points ignored (not above a good facet)", -1); zdef_(zinc, Znotgoodnew, "points ignored (didn't create a good new facet)", -1); zdef_(zinc, Zgoodfacet, "good facets found", -1); zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1); zdef_(zinc, Ztotverify, "points verified", -1); zdef_(zinc, Zverifypart, " ave. distance tests per verify", Ztotverify); } void qh_allstatC(void) { zdef_(zdoc, Zdoc4, "partitioning statistics", -1); zdef_(zinc, Zpartinside, "inside points", -1); zdef_(zinc, Zcoplanarinside, " inside points that were coplanar with a facet", -1); zdef_(zinc, Ztotpartition, "partitions of a point", -1); zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1); zzdef_(zinc, Zpartition, "distance tests for other partitions", -1); zdef_(zinc, Zpartneighbor, "extra distance tests for coplanar and flipped neighbors", -1); zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1); zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1); zdef_(zinc, Zdistgood, "distance tests for checking good point", -1); zdef_(zinc, Zdistio, "distance tests for output", -1); zdef_(zinc, Zdiststat, "distance tests for statistics", -1); zdef_(zinc, Zdistplane, "total number of distance tests", -1); zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1); zzdef_(zinc, Zpartcoplanar, " distance tests for these partitions", -1); zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1); } void qh_allstatD(void) { zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1); zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1); zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup); zdef_(zinc, Zhashridge, "total lookups of subridges (duplicates and boundary)", -1); zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge); zdef_(zdoc, Zdoc6, "statistics for determining merges", -1); zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1); zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices", -1); zzdef_(zinc, Zbestdist, "distance tests for best merge", -1); zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1); zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1); zdef_(zinc, Zcoplanarcentrum, "coplanar centrums in getmergeset", -1); zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1); } void qh_allstatE(void) { zdef_(zdoc, Zdoc7, "statistics for merging", -1); zdef_(wmax, Wmaxoutside, "max distance of merged vertex above facet", -1); zdef_(wmin, Wminvertex, "max distance of merged vertex below facet", -1); zzdef_(zinc, Ztotmerge, "total number of facets merged", -1); zdef_(zinc, Zmergenew, "new facets merged", -1); zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1); zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1); zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1); zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1); zdef_(zinc, Zmergeflip, "merges due to flipped neighbors", -1); zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1); zdef_(zinc, Zneighbor, "merges due to redundant neighbors", -1); zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1); zdef_(wadd, Wacoplanartot, " average merge distance", Zacoplanar); zdef_(wmax, Wacoplanarmax, " maximum merge distance", -1); zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1); zdef_(wadd, Wcoplanartot, " average merge distance", Zcoplanar); zdef_(wmax, Wcoplanarmax, " maximum merge distance", -1); zdef_(zinc, Zconcave, "merges due to concave facets", -1); zdef_(wadd, Wconcavetot, " average merge distance", Zconcave); zdef_(wmax, Wconcavemax, " maximum merge distance", -1); zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1); zdef_(wadd, Wavoidoldtot, " average merge distance", Zavoidold); zdef_(wmax, Wavoidoldmax, " maximum merge distance", -1); zdef_(zinc, Zdegen, "merges due to degenerate facets", -1); zdef_(wadd, Wdegentot, " average merge distance", Zdegen); zdef_(wmax, Wdegenmax, " maximum merge distance", -1); zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1); zdef_(wadd, Wflippedtot, " average merge distance", Zflipped); zdef_(wmax, Wflippedmax, " maximum merge distance", -1); zdef_(zinc, Zduplicate, "merges due to duplicated ridges", -1); zdef_(wadd, Wduplicatetot, " average merge distance", Zduplicate); zdef_(wmax, Wduplicatemax, " maximum merge distance", -1); } void qh_allstatF(void) { zdef_(zdoc, Zdoc8, "renamed vertex statistics", -1); zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1); zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1); zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1); zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1); zdef_(zinc, Zdupridge, " duplicate ridges detected", -1); zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1); zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1); zdef_(zinc, Zdropdegen, "degenerate facets due to dropped neighbors", -1); zdef_(zinc, Zdelfacetdup, " facets deleted because of no neighbors", -1); zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1); zdef_(zinc, Zremvertexdel, "vertices deleted due to no ridges", -1); zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1); zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1); zdef_(zinc, Zintersect, "intersections found redundant vertices", -1); zdef_(zadd, Zintersecttot, " ave. number found per vertex", Zintersect); zdef_(zmax, Zintersectmax, " max. found for a vertex", -1); zdef_(zinc, Zvertexridge, NULL, -1); zdef_(zadd, Zvertexridgetot, " ave. number of ridges per tested vertex", Zvertexridge); zdef_(zmax, Zvertexridgemax, " max. number of ridges per tested vertex", -1); zdef_(zdoc, Zdoc10, "memory usage statistics (in bytes)", -1); zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1); zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1); zdef_(zadd, Zmempoints, "for input points and outside and coplanar sets",-1); zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1); } /* allstat */ #if qh_KEEPstatistics /*------------------------------------------------- -collectstatistics- collect statistics for qh facet_list */ void qh_collectstatistics (void) { facetT *facet, *neighbor, **neighborp; vertexT *vertex, **vertexp; realT dotproduct, dist; int sizneighbors, sizridges, sizvertices; zval_(Zmempoints)= qh num_points * qh normal_size + sizeof (qhT) + sizeof (qhstatT); zval_(Zmemfacets)= 0; zval_(Zmemridges)= 0; zval_(Zmemvertices)= 0; zval_(Zangle)= 0; wval_(Wangle)= 0.0; zval_(Znumridges)= 0; zval_(Znumfacets)= 0; zval_(Znumneighbors)= 0; zval_(Znumvertices)= 0; zval_(Znumvneighbors)= 0; zval_(Zvertices)= qh num_vertices - qh_setsize (qh del_vertices); if (qh MERGING || qh APPROXhull) wmax_(Wmaxoutside, qh max_outside); if (qh MERGING) wmin_(Wminvertex, qh min_vertex); FORALLfacets facet->seen= False; if (qh DELAUNAY) { FORALLfacets { if (facet->normal && facet->normal[qh hull_dim - 1] > 0.0) facet->seen= True; } } FORALLfacets { if (facet->visible && qh NEWfacets) continue; sizvertices= qh_setsize (facet->vertices); sizneighbors= qh_setsize (facet->neighbors); sizridges= qh_setsize (facet->ridges); zinc_(Znumfacets); zadd_(Znumvertices, sizvertices); zmax_(Zmaxvertices, sizvertices); zadd_(Znumneighbors, sizneighbors); zmax_(Zmaxneighbors, sizneighbors); if (sizridges) { zadd_(Znumridges, sizridges); zmax_(Zmaxridges, sizridges); } zadd_(Zmemfacets, sizeof (facetT) + qh normal_size + 2*sizeof (setT) + SETelemsize * (sizneighbors + sizvertices)); if (facet->ridges) { zadd_(Zmemridges, sizeof (setT) + SETelemsize * sizridges + sizridges * (sizeof (ridgeT) + sizeof (setT) + SETelemsize * (qh hull_dim-1))/2); } if (facet->outsideset) zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->outsideset)); if (facet->coplanarset) zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->coplanarset)); if (facet->seen) /* Delaunay upper envelope */ continue; facet->seen= True; FOREACHneighbor_(facet) { if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge || neighbor->seen || !facet->normal || !neighbor->normal) continue; dotproduct= qh_getangle(facet->normal, neighbor->normal); zinc_(Zangle); wadd_(Wangle, dotproduct); wmax_(Wanglemax, dotproduct) wmin_(Wanglemin, dotproduct) } FOREACHvertex_(facet->vertices) { zinc_(Zdiststat); qh_distplane(vertex->point, facet, &dist); wmax_(Wvertexmax, dist); wmin_(Wvertexmin, dist); } } FORALLvertices { if (vertex->deleted) continue; zadd_(Zmemvertices, sizeof (vertexT)); if (vertex->neighbors) { sizneighbors= qh_setsize (vertex->neighbors); zadd_(Znumvneighbors, sizneighbors); zmax_(Zmaxvneighbors, sizneighbors); zadd_(Zmemvertices, sizeof (vertexT) + SETelemsize * sizneighbors); } } } /* collectstatistics */ #endif /* qh_KEEPstatistics */ /*------------------------------------------------- -freestatistics- free memory used for statistics */ void qh_freestatistics (void) { #if qh_QHpointer /* duplicated if !KEEPstatistics */ free (qh_qhstat); qh_qhstat= NULL; #endif } /* freestatistics */ /*------------------------------------------------- -initstatistics- allocate and initialize statistics uses malloc instead of memalloc since mem.c not setup yet */ void qh_initstatistics (void) { int i; realT realx; int intx; #if qh_QHpointer /* duplicated if !KEEPstatistics */ if (!(qh_qhstat= (qhstatT *)malloc (sizeof(qhstatT)))) qhull_fatal(33); #endif qhstat next= 0; qh_allstatA(); qh_allstatB(); qh_allstatC(); qh_allstatD(); qh_allstatE(); qh_allstatF(); qhstat init[zinc].i= 0; qhstat init[zadd].i= 0; qhstat init[zmin].i= INT_MAX; qhstat init[zmax].i= INT_MIN; qhstat init[wadd].r= 0; qhstat init[wmin].r= REALmax; qhstat init[wmax].r= -REALmax; for (i=0; i ZTYPEreal) { realx= qhstat init[(unsigned char)(qhstat type[i])].r; qhstat stats[i].r= realx; }else if (qhstat type[i] != zdoc) { intx= qhstat init[(unsigned char)(qhstat type[i])].i; qhstat stats[i].i= intx; } } } /* initstatistics */ /*------------------------------------------- -newstats- returns True if statistics for zdoc returns: next zdoc */ boolT qh_newstats (int index, int *nextindex) { boolT isnew= False; int start, i; if (qhstat type[qhstat id[index]] == zdoc) start= index+1; else start= index; for (i= start; i < qhstat next && qhstat type[qhstat id[i]] != zdoc; i++) { if (!qh_nostatistic(qhstat id[i]) && !qhstat printed[qhstat id[i]]) isnew= True; } *nextindex= i; return isnew; } /* newstats */ /*------------------------------------------- -nostatistic- true if no statistic to print */ boolT qh_nostatistic (int i) { if ((qhstat type[i] > ZTYPEreal &&qhstat stats[i].r == qhstat init[(unsigned char)(qhstat type[i])].r) || (qhstat type[i] < ZTYPEreal &&qhstat stats[i].i == qhstat init[(unsigned char)(qhstat type[i])].i)) return True; return False; } /* nostatistic */ #if qh_KEEPstatistics /*------------------------------------------- -qh_printallstatistics- print all statistics to a file */ void qh_printallstatistics (FILE *fp, char *string) { int i; for (i=ZEND; i--; ) qhstat printed[i]= False; qh_printstatistics (fp, string); } /*------------------------------------------- -printstatistics- print statistics to a file */ void qh_printstatistics (FILE *fp, char *string) { int i, k; realT ave; if (qh num_points != qh num_vertices) { wval_(Wpbalance)= 0; wval_(Wpbalance2)= 0; }else wval_(Wpbalance2)= qh_stddev (zval_(Zpbalance), wval_(Wpbalance), wval_(Wpbalance2), &ave); wval_(Wnewbalance2)= qh_stddev (zval_(Zprocessed), wval_(Wnewbalance), wval_(Wnewbalance2), &ave); fprintf (fp, "\n\ %s\n\ qhull invoked by: %s | %s\n", string, qh rbox_command, qh qhull_command); fprintf (fp, "\nprecision constants:\n\ %6.2g max. coordinate in the input\n\ %6.2g max. roundoff error for distance computation\n\ %6.2g min. distance for outside points\n", qh maxmaxcoord, qh DISTround, qh MINoutside); if (qh premerge_cos < REALmax/2) fprintf (fp, "\ %6.2g max. cosine for pre-merge angle\n", qh premerge_cos); if (qh PREmerge) fprintf (fp, "\ %6.2g radius of pre-merge centrum\n", qh premerge_centrum); if (qh postmerge_cos < REALmax/2) fprintf (fp, "\ %6.2g max. cosine for post-merge angle\n", qh postmerge_cos); if (qh POSTmerge) fprintf (fp, "\ %6.2g radius of post-merge centrum\n", qh postmerge_centrum); fprintf (fp, "\ %6.2g max. distance for merging two simplicial facets\n\ %6.2g max. roundoff error for arithmetic operations\n\ %6.2g min. denominator for divisions\n\ zero diagonal for Gauss: ", qh ONEmerge, REALepsilon, qh MINdenom); for (k=0; k= ZEND, printed, or same as initial value */ void qh_printstatlevel (FILE *fp, int id, int start) { #define NULLfield " " if (id >= ZEND || qhstat printed[id]) return; if (qhstat type[id] == zdoc) { fprintf (fp, "%s\n", qhstat doc[id]); return; } if (qh_nostatistic(id) || !qhstat doc[id]) return; qhstat printed[id]= True; if (qhstat count[id] != -1 && qhstat stats[(unsigned char)(qhstat count[id])].i == 0) fprintf (fp, " *0 cnt*"); else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] == -1) fprintf (fp, " %6.2g", qhstat stats[id].r); else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] != -1) fprintf (fp, " %6.2g", qhstat stats[id].r/ qhstat stats[(unsigned char)(qhstat count[id])].i); else if (qhstat type[id] < ZTYPEreal && qhstat count[id] == -1) fprintf (fp, " %6d", qhstat stats[id].i); else if (qhstat type[id] < ZTYPEreal && qhstat count[id] != -1) fprintf (fp, " %6.2g", (realT) qhstat stats[id].i / qhstat stats[(unsigned char)(qhstat count[id])].i); fprintf (fp, " %s\n", qhstat doc[id]); } /* printstatlevel */ /*------------------------------------------------------- -printstats- print statistics for a zdoc group returns: next zdoc if non-null */ void qh_printstats (FILE *fp, int index, int *nextindex) { int j, nexti; if (qh_newstats (index, &nexti)) { for (j=index; jprevious= tail->previous; facet->next= tail; if (tail->previous) tail->previous->next= facet; else qh facet_list= facet; tail->previous= facet; qh num_facets++; trace4((qh ferr, "qh_appendfacet: append f%d to facet_list\n", facet->id)); } /* appendfacet */ /*------------------------------------------------- -appendvertex- appends vertex to end of qh vertex_list, updates qh vertex_list, vertex_tail, newvertex_list increments qh num_vertices assumes qh vertex_list/vertex_tail is defined (createsimplex) */ void qh_appendvertex (vertexT *vertex) { vertexT *tail= qh vertex_tail; if (tail == qh newvertex_list) qh newvertex_list= vertex; vertex->previous= tail->previous; vertex->next= tail; if (tail->previous) tail->previous->next= vertex; else qh vertex_list= vertex; tail->previous= vertex; qh num_vertices++; trace4((qh ferr, "qh_appendvertex: append v%d to vertex_list\n", vertex->id)); } /* appendvertex */ /*------------------------------------------------- -attachnewfacets- attach horizon facets to new facets in qh newfacet_list if (qh ONLYgood) newfacets have neighbor and ridge links to horizon but not vice versa else newfacets attached to horizon and visible facets attached to new qh visible_list is all visible facets returns: horizon facets linked to new facets ridges changed from visible facets to new facets simplicial ridges deleted for non-simplicial horizon facets, the first neighbor is a new facet qh visible_list, no ridges valid, only newfacet neighbors (if any) sets qh NEWfacets if qh VERTEXneighbors, update neighbors for each vertex interior vertices added to qh del_vertices for later partitioning */ void qh_attachnewfacets (void ) { facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible; ridgeT *ridge, **ridgep; vertexT *vertex, **vertexp; qh NEWfacets= True; if (qh ONLYgood) { trace3((qh ferr, "qh_attachnewfacets: delete interior ridges\n")); qh visit_id++; FORALLvisible_facets { visible->visitid= qh visit_id; if (visible->ridges) { FOREACHridge_(visible->ridges) { neighbor= otherfacet_(ridge, visible); if ((int)neighbor->visitid == qh visit_id || (!neighbor->visible && neighbor->simplicial)) { if (!neighbor->visible) /* delete ridge for simplicial horizon */ qh_setdel (neighbor->ridges, ridge); qh_setfree (&(ridge->vertices)); /* delete on 2nd visit */ qh_memfree (ridge, sizeof(ridgeT)); } } SETfirst_(visible->ridges)= NULL; } SETfirst_(visible->neighbors)= NULL; SETsecond_(visible->neighbors)= NULL; } trace1((qh ferr, "qh_attachnewfacets: attach horizon facets to new facets\n")); FORALLnew_facets { horizon= (facetT *)SETfirst_(newfacet->neighbors); if (horizon->simplicial) { visible= NULL; FOREACHneighbor_(horizon) { /* may have more than one horizon ridge */ if (neighbor->visible) { if (visible) { if (qh_setequal_skip (newfacet->vertices, 0, horizon->vertices, SETindex_(horizon->neighbors, neighbor))) { visible= neighbor; break; } }else visible= neighbor; } } if (visible) { SETfirst_(visible->neighbors)= newfacet; qh_setreplace (horizon->neighbors, visible, newfacet); } else qhull_fatal(34); }else { /* non-simplicial, with a ridge for newfacet */ FOREACHneighbor_(horizon) { /* may hold for many new facets */ if (neighbor->visible) { SETfirst_(neighbor->neighbors)= newfacet; qh_setdelnth (horizon->neighbors, SETindex_(horizon->neighbors, neighbor)); neighborp--; /* repeat */ } } qh_setappend (&horizon->neighbors, newfacet); ridge= (ridgeT *)SETfirst_(newfacet->ridges); if (ridge->top == horizon) ridge->bottom= newfacet; else ridge->top= newfacet; } } /* newfacets */ if (qh PRINTstatistics) { FORALLvisible_facets { if (!SETfirst_(visible->neighbors)) zinc_(Zinsidevisible); } } } trace3((qh ferr, "qh_attachnewfacets: delete interior vertices and update vertex->neighbors\n")); if (qh VERTEXneighbors) { FORALLvisible_facets { FOREACHvertex_(visible->vertices) { if (vertex->newlist) qh_setdel (vertex->neighbors, visible); else if (!vertex->deleted) { FOREACHneighbor_(vertex) { /* this can happen under merging, see checkfacet() */ if (!neighbor->visible) break; } if (neighbor) qh_setdel (vertex->neighbors, visible); else { vertex->deleted= True; qh_setappend (&qh del_vertices, vertex); trace2((qh ferr, "qh_attachnewfacets: delete vertex p%d (v%d) in f%d\n", qh_pointid(vertex->point), vertex->id, visible->id)); } } } } FORALLnew_facets { FOREACHvertex_(newfacet->vertices) qh_setappend (&vertex->neighbors, newfacet); } }else { /* !VERTEXneighbors */ FORALLvisible_facets { FOREACHvertex_(visible->vertices) { if (!vertex->newlist && !vertex->deleted) { vertex->deleted= True; qh_setappend (&qh del_vertices, vertex); trace2((qh ferr, "qh_attachnewfacets: delete vertex p%d (v%d) in f%d\n", qh_pointid(vertex->point), vertex->id, visible->id)); } } } } } /* attachnewfacets */ /*----------------------------------------------- -check_bestdist- check that points are within max_outside of the nearest facet if ONLYgood, ignores !good facets see: check_maxout */ void qh_check_bestdist (void) { boolT waserror= False, isoutside; facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL; realT dist, maxoutside; pointT *point; int numpart, facet_i, facet_n, notgood= 0; setT *facets; maxoutside= fmax_(qh max_outside, qh DISTround); maxoutside += 2 * qh DISTround; /* 1 DISTround to actual point and another DISTround to computed point */ trace1((qh ferr, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside)); facets= qh_pointfacet (/*qh facet_list*/); if (!qh_QUICKhelp && qh PRINTprecision) fprintf (qh ferr, "\n\ qhull output completed. Verifying that %d points are\n\ below %2.2g of the nearest %sfacet.\n", qh_setsize(facets), maxoutside, (qh ONLYgood ? "good " : "")); FOREACHfacet_i_(facets) { zinc_(Ztotverify); if (!facet) facet= qh facet_list; point= qh_point(facet_i); if (point == qh GOODpointp) continue; bestfacet= qh_findbest (point, facet, qh_ALL, 0, &dist, &isoutside, &numpart); zadd_(Zverifypart, numpart); if (dist > maxoutside) { if (qh ONLYgood && !bestfacet->good && !((bestfacet= qh_findgooddist (point, bestfacet, &dist)) && dist > maxoutside)) notgood++; else { waserror= True; fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance = %6.8g maxoutside= %6.8g\n", facet_i, bestfacet->id, dist, maxoutside); errfacet2= errfacet1; errfacet1= bestfacet; } } } qh_settempfree (&facets); if (waserror) qhull_fatal(35); } /* check_bestdist */ /*----------------------------------------------- -check_maxout- updates max_outside by checking all points against bestfacet updates facet->maxoutside via findbest updates facet->coplanarset to qh min_vertex if PRINTnone, updates min_vertex for printsummary() if ONLYgood, ignores !good facets see check_bestdist notes: may not need to check inside points if KEEPcoplanar (since coplanar is now min_vertex instead of -DISTround) */ void qh_check_maxout (void) { boolT isoutside; facetT *facet, *bestfacet, *neighbor, **neighborp; realT dist, maxoutside, minvertex; pointT *point; int numpart, facet_i, facet_n, notgood= 0; setT *facets, *vertices= NULL; vertexT *vertex; maxoutside= minvertex= 0; trace1((qh ferr, "qh_check_maxout: determine actual maxoutside and minoutside\n")); facets= qh_pointfacet (/*qh facet_list*/); if (qh PRINTout[0] == qh_PRINTnone || qh PRINTsummary) { vertices= qh_pointvertex (/*qh facet_list*/); FORALLvertices { FOREACHneighbor_(vertex) { zinc_(Zverifypart); qh_distplane (vertex->point, neighbor, &dist); minimize_(minvertex, dist); if (-dist > qh TRACEdist || neighbor == qh tracefacet || vertex == qh tracevertex) fprintf (qh ferr, "qh_check_maxout: p%d (v%d) is %.2g below f%d\n", qh_pointid (vertex->point), vertex->id, dist, neighbor->id); } } if (qh MERGING) wmin_(Wminvertex, qh min_vertex); qh min_vertex= minvertex; } FOREACHfacet_i_(facets) { if (True) { /* inside points can end up outside after merging */ zinc_(Ztotverify); if (!facet) facet= qh facet_list; point= qh_point(facet_i); if (point == qh GOODpointp) continue; bestfacet= qh_findbest (point, facet, qh_ALL, 0, &dist, &isoutside, &numpart); zadd_(Zverifypart, numpart); if (dist > maxoutside) { if (qh ONLYgood && !bestfacet->good && !((bestfacet= qh_findgooddist (point, bestfacet, &dist)) && dist > maxoutside)) notgood++; else maxoutside= dist; } if (!facet && dist > qh min_vertex) qh_partitioncoplanar (point, bestfacet, &dist); if (dist > qh TRACEdist || bestfacet == qh tracefacet) fprintf (qh ferr, "qh_check_maxout: p%d is %.2g above f%d\n", qh_pointid (point), dist, bestfacet->id); } } qh_settempfree (&vertices); qh_settempfree (&facets); wmax_(Wmaxoutside, qh max_outside); qh max_outside= maxoutside; trace1((qh ferr, "qh_check_maxout: maxoutside %2.2g outside of not good %d\n", maxoutside, notgood)); } /* check_maxout */ /*---------------------------------------- -check_output- performs the checks at the end of qhull algorithm does not check points (may take a long time) */ void qh_check_output (void) { int i; if (qh STOPcone) return; if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) { qh_checkpolygon (qh facet_list); qh_checkflipped_all (qh facet_list); qh_checkconvex(qh facet_list, qh_ALGORITHMfault); }else if (!qh MERGING && qh_newstats (qhstat precision, &i)) { qh_checkflipped_all (qh facet_list); qh_checkconvex (qh facet_list, qh_ALGORITHMfault); } } /* check_output */ /*------------------------------------------------------------- -check_point- check that point is not outside facet if maxerror, doesn't report an error */ void qh_check_point (pointT *point, facetT *facet, realT *maxoutside, facetT **errfacet1, facetT **errfacet2) { realT dist; zinc_(Zverifypart); qh_distplane(point, facet, &dist); if (dist > *maxoutside) { *errfacet2= *errfacet1; *errfacet1= facet; fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance = %6.8g maxoutside= %6.8g\n", qh_pointid(point), facet->id, dist, *maxoutside); } } /* qh_check_point */ /*------------------------------------------------- -check_points- checks that all points are inside all facets uses findbest if lots of points ignores flipped facets */ void qh_check_points (void) { facetT *facet, *errfacet1= NULL, *errfacet2= NULL; realT total, maxoutside; pointT *point, **pointp, *pointtemp; maxoutside= fmax_(qh max_outside, qh DISTround); maxoutside += 2* qh DISTround; /* 1 DISTround to actual point and another DISTround to computed point */ if (qh RANDOMdist) /* repeated computations can differ by 2*distround */ maxoutside += qh DISTround; trace1((qh ferr, "qh_check_points: check all points below %2.2g of all facet planes\n", maxoutside)); if (qh num_good) total= (float) qh num_good * qh num_points; else total= (float) qh num_facets * qh num_points; if (total >= qh_VERIFYdirect && !qh MERGING) /* MERGING qh_check_maxout */ qh_check_bestdist(); else { if (!qh_QUICKhelp && qh PRINTprecision) { /* miss counts other_points and !good facets */ if (qh PREmerge && !qh KEEPcoplanar && zzval_(Zcoplanarpart) > 10) fprintf (qh ferr, "\n\ qhull input warning: pre-merging ('C-n' or 'A-n') without retaining coplanar\n\ points ('Qc'). Verify may report that an outer plane is incorrect.\n"); fprintf (qh ferr, "\n\ Output completed. Verifying that all points are below %2.2g of\n\ all %sfacets. Will make %2.0f distance computations.\n", maxoutside, (qh ONLYgood ? "good " : ""), total); } FORALLfacets { if (!facet->good && qh ONLYgood) continue; if (facet->flipped) continue; #if qh_MAXoutside maxoutside= facet->maxoutside + 2* qh DISTround; /* 1 DISTround to actual point and another DISTround to computed point */ #endif FORALLpoints { if (point != qh GOODpointp) qh_check_point (point, facet, &maxoutside, &errfacet1, &errfacet2); } FOREACHpoint_(qh other_points) { if (point != qh GOODpointp) qh_check_point (point, facet, &maxoutside, &errfacet1, &errfacet2); } } if (errfacet1) qhull_fatal(36); } } /* check_points */ /*------------------------------------------------- -checkconvex- check that each ridge in facetlist is convex returns: counts Zconcaveridges and Zcoplanarridges errors if concaveridge or if merging an coplanar ridge note: optimized for simplicial facets */ void qh_checkconvex(facetT *facetlist, int fault) { facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL; vertexT *vertex; realT dist; pointT *centrum; boolT waserror= False; int neighbor_i; trace1((qh ferr, "qh_checkconvex: check all ridges are convex\n")); zzval_(Zconcaveridges)= 0; zzval_(Zcoplanarridges)= 0; FORALLfacet_(facetlist) { if (facet->flipped) { fprintf (qh ferr, "qhull precision error: f%d is flipped (interior point is outside)\n", facet->id); errfacet1= facet; waserror= True; continue; } if (!qh MERGING) { /* simplicial facet */ neighbor_i= 0; FOREACHneighbor_(facet) { vertex= (vertexT *)SETelem_(facet->vertices, neighbor_i++); zzinc_(Zdistconvex); qh_distplane (vertex->point, neighbor, &dist); if (dist > -qh DISTround) { if (fault == qh_DATAfault) qhull_fatal(37); if (dist > qh DISTround) { zzinc_(Zconcaveridges); fprintf (qh ferr, "qhull precision error: f%d is concave to f%d, since p%d (v%d) is %6.4g above\n", facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist); errfacet1= facet; errfacet2= neighbor; waserror= True; }else { zzinc_(Zcoplanarridges); trace0((qh ferr, "qhull precision error: f%d may be coplanar to f%d, since p%d (v%d) is within %6.4g\n", facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist)); } } } }else { /* qh MERGING */ if (qh CENTERtype == qh_centrum) { if (!facet->center) facet->center= qh_getcentrum (facet); centrum= facet->center; }else centrum= qh_getcentrum(facet); FOREACHneighbor_(facet) { zzinc_(Zdistconvex); qh_distplane (centrum, neighbor, &dist); if (dist > qh DISTround) { zzinc_(Zconcaveridges); fprintf (qh ferr, "qhull precision error: f%d is concave to f%d, since its centrum is %6.4g above\n", facet->id, neighbor->id, dist); errfacet1= facet; errfacet2= neighbor; waserror= True; }else if (dist >= 0.0) { /* if arithmetic always rounds the same, can test against centrum radius instead */ zzinc_(Zcoplanarridges); fprintf (qh ferr, "qhull precision error: f%d is coplanar or concave to f%d, since its centrum is %6.4g above\n", facet->id, neighbor->id, dist); errfacet1= facet; errfacet2= neighbor; waserror= True; } } if (qh CENTERtype != qh_centrum) qh_memfree(centrum, qh normal_size); } } if (waserror && !qh FORCEoutput) qhull_fatal(38); } /* checkconvex */ /*------------------------------------------------- -checkfacet- checks for consistency errors in facet vertex ids are inverse sorted unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial) if non-simplicial, at least as many ridges as neighbors neighbors are not duplicated ridges are not duplicated in 3-d, ridges=verticies (hull_dim-1) ridge vertices neighbors are reciprocated ridge neighbors are facet neighbors and a ridge for every neighbor simplicial neighbors match facetintersect vertex intersection matches vertices of common ridges vertex neighbors and facet vertices agree sets waserror if any error occurs uses neighbor->seen */ void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) { facetT *neighbor, **neighborp, *errother=NULL; ridgeT *ridge, **ridgep, *errridge= NULL; vertexT *vertex, **vertexp; unsigned previousid= INT_MAX; int numneighbors, numvertices, numridges=0, numRvertices=0; boolT waserror= False; int skipA, skipB; setT *intersection; if (facet->visible) qhull_fatal(39); if (!facet->normal) { fprintf (qh ferr, "qhull internal error (checkfacet): facet f%d does not have a normal\n", facet->id); waserror= True; } qh_setcheck (facet->vertices, "vertices for f", facet->id); qh_setcheck (facet->ridges, "ridges for f", facet->id); qh_setcheck (facet->outsideset, "outsideset for f", facet->id); qh_setcheck (facet->coplanarset, "coplanarset for f", facet->id); qh_setcheck (facet->neighbors, "neighbors for f", facet->id); FOREACHvertex_(facet->vertices) { if (vertex->deleted) { fprintf(qh ferr, "qhull internal error (checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id); /* qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex); NO LONGER IN SERVICE */ waserror= True; } if (vertex->id >= previousid) { fprintf(qh ferr, "qhull internal error (checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id); waserror= True; break; } previousid= vertex->id; } numneighbors= qh_setsize(facet->neighbors); numvertices= qh_setsize(facet->vertices); numridges= qh_setsize(facet->ridges); if (facet->simplicial) { if (numvertices+numneighbors != 2*qh hull_dim && !qh_facetdegen(facet)) { fprintf(qh ferr, "qhull internal error (checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n", facet->id, numvertices, numneighbors); qh_setprint (qh ferr, "", facet->neighbors); waserror= True; } }else { /* non-simplicial */ if (!newmerge &&(numvertices < qh hull_dim || numneighbors < qh hull_dim) && !qh_facetdegen(facet)) { fprintf(qh ferr, "qhull internal error (checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n", facet->id, numvertices, numneighbors); waserror= True; } if (numridges < numneighbors ||(qh hull_dim == 3 && !qh NEWmerges && numvertices != numridges) ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) { if (!qh_facetdegen(facet)) { fprintf(qh ferr, "qhull internal error (checkfacet): for facet f%d, #ridges %d < #neighbors %d or (3-d) != #vertices %d or (2-d) not all 2\n", facet->id, numridges, numneighbors, numvertices); waserror= True; } } } FOREACHneighbor_(facet) { if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) qhull_fatal(40); neighbor->seen= True; } FOREACHneighbor_(facet) { if (!qh_setin(neighbor->neighbors, facet)) { fprintf(qh ferr, "qhull internal error (checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n", facet->id, neighbor->id, neighbor->id, facet->id); errother= neighbor; waserror= True; } if (!neighbor->seen) { fprintf(qh ferr, "qhull internal error (checkfacet): facet f%d has a duplicate neighbor f%d\n", facet->id, neighbor->id); errother= neighbor; waserror= True; } neighbor->seen= False; } FOREACHridge_(facet->ridges) { qh_setcheck (ridge->vertices, "vertices for r", ridge->id); ridge->seen= False; if (ridge->mergeridge && !newmerge) { fprintf (qh ferr, "qhull internal error (checkfacet): mergeridge r%d still in facetlist\n", ridge->id); /* qh_errprint ("ERRONEOUS", NULL, NULL, ridge, NULL); NO LONGER IN SERVICE */ waserror= True; } } FOREACHridge_(facet->ridges) { if (ridge->seen) { fprintf(qh ferr, "qhull internal error (checkfacet): facet f%d has a duplicate ridge r%d\n", facet->id, ridge->id); errridge= ridge; waserror= True; } ridge->seen= True; numRvertices= qh_setsize(ridge->vertices); if (numRvertices != qh hull_dim - 1) { fprintf(qh ferr, "qhull internal error (checkfacet): ridge between f%d and f%d has %d vertices\n", ridge->top->id, ridge->bottom->id, numRvertices); errridge= ridge; waserror= True; } neighbor= otherfacet_(ridge, facet); neighbor->seen= True; if (!qh_setin(facet->neighbors, neighbor)) { fprintf(qh ferr, "qhull internal error (checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n", facet->id, neighbor->id, ridge->id); errridge= ridge; waserror= True; } } if (!facet->simplicial) { FOREACHneighbor_(facet) { if (!neighbor->seen) { fprintf(qh ferr, "qhull internal error (checkfacet): facet f%d does not have a ridge for neighbor f%d\n", facet->id, neighbor->id); errother= neighbor; waserror= True; } intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices); qh_settemppush (intersection); FOREACHvertex_(facet->vertices) { vertex->seen= False; vertex->seen2= False; } FOREACHvertex_(intersection) vertex->seen= True; FOREACHridge_(facet->ridges) { if (neighbor != otherfacet_(ridge, facet)) continue; FOREACHvertex_(ridge->vertices) { if (!vertex->seen) qhull_fatal(41); vertex->seen2= True; } } if (!newmerge) { FOREACHvertex_(intersection) { if (!vertex->seen2) { if (qh IStracing >=3 || !qh MERGING) { fprintf (qh ferr, "qhull precision error (checkfacet): vertex v%d in f%d intersect f%d but\n\ not in a ridge. This is ok under merging. Last point was p%d\n", vertex->id, facet->id, neighbor->id, qh furthest_id); if (!qh FORCEoutput && !qh MERGING) qhull_fatal(42); } } } } qh_settempfree (&intersection); } }else { /* simplicial */ FOREACHneighbor_(facet) { if (neighbor->simplicial) { skipA= SETindex_(facet->neighbors, neighbor); skipB= qh_setindex (neighbor->neighbors, facet); if (!qh_setequal_skip (facet->vertices, skipA, neighbor->vertices, skipB)) { fprintf (qh ferr, "qhull internal error (checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n", facet->id, skipA, neighbor->id, skipB); errother= neighbor; waserror= True; } } } } if (waserror) { /* qh_errprint("ERRONEOUS", facet, errother, errridge, NULL); NO LONGER IN SERVICE */ *waserrorp= True; } } /* checkfacet */ /*------------------------------------------------- -checkflipped- checks facet orientation to interior point tests against 0 if !allerror since tested against DISTround before returns: False if flipped orientation (sets facet->flipped) distance if non-NULL */ boolT qh_checkflipped (facetT *facet, realT *distp, boolT allerror) { realT dist; if (facet->flipped && !distp) return False; zzinc_(Zdistcheck); qh_distplane(qh interior_point, facet, &dist); if (distp) *distp= dist; if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) { facet->flipped= True; zzinc_(Zflippedfacets); trace0((qh ferr, "qh_checkflipped: facet f%d is flipped, distance= %6.12g\n", facet->id, dist)); return False; } return True; } /* checkflipped */ /*------------------------------------------------- -checkflipped_all- checks orientation of facets in list against interior point */ void qh_checkflipped_all (facetT *facetlist) { facetT *facet; boolT waserror= False; realT dist; if (facetlist == qh facet_list) zzval_(Zflippedfacets)= 0; FORALLfacet_(facetlist) { if (!qh_checkflipped (facet, &dist, (boolT)!qh_ALL)) { fprintf(qh ferr, "qhull precision error: facet f%d is flipped, distance= %6.12g\n", facet->id, dist); if (!qh FORCEoutput) { /* qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL); NO LONGER IN SERVICE */ waserror= True; } } } if (waserror) qhull_fatal(43); } /* checkflipped_all */ /*------------------------------------------------- -checkpolygon- checks the correctness of the structure check num_facets and num_vertices if qh facet_list call with either qh facet_list or qh newfacet_list */ void qh_checkpolygon(facetT *facetlist) { facetT *facet; vertexT *vertex, **vertexp, *vertexlist; int numfacets= 0, numvertices= 0, numridges= 0; boolT waserror= False, nextseen= False, visibleseen= False; trace1((qh ferr, "qh_checkpolygon: check all facets from f%d\n", facetlist->id)); if (facetlist != qh facet_list || qh ONLYgood) nextseen= True; FORALLfacet_(facetlist) { if (facet == qh visible_list) visibleseen= True; if (!facet->visible) { if (!nextseen) { if (facet == qh facet_next) nextseen= True; else if (qh_setsize (facet->outsideset)) qhull_fatal(44); } numfacets++; qh_checkfacet(facet, False, &waserror); } } if (qh visible_list && !visibleseen && facetlist == qh facet_list) qhull_fatal(45); if (facetlist == qh facet_list) vertexlist= qh vertex_list; else if (facetlist == qh newfacet_list) vertexlist= qh newvertex_list; else vertexlist= NULL; FORALLvertex_(vertexlist) { vertex->seen= False; vertex->visitid= 0; } FORALLfacet_(facetlist) { if (facet->visible) continue; if (facet->simplicial) numridges += qh hull_dim; else numridges += qh_setsize (facet->ridges); FOREACHvertex_(facet->vertices) { vertex->visitid++; if (!vertex->seen) { vertex->seen= True; numvertices++; if (qh_pointid (vertex->point) == -1) { fprintf (qh ferr, "qhull internal error (checkpolygon): unknown point %p for vertex v%d first_point %p\n", vertex->point, vertex->id, qh first_point); waserror= True; } } } } qh vertex_visit += numfacets; if (facetlist == qh facet_list) { if (numfacets != qh num_facets - qh num_visible) { fprintf(qh ferr, "qhull internal error (checkpolygon): actual number of facets is %d, cumulative facet count is %d\n", numfacets, qh num_facets- qh num_visible); waserror= True; } qh vertex_visit++; if (qh VERTEXneighbors) { FORALLvertices { qh_setcheck (vertex->neighbors, "neighbors for v", vertex->id); if ((int)vertex->visitid != qh vertex_visit && !vertex->deleted) { if ((int)vertex->visitid != qh_setsize (vertex->neighbors)) { fprintf (qh ferr, "qhull internal error (checkpolygon): v%d neighbors is wrong, actually in %d facets\n", vertex->id, vertex->visitid); /* qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex); NO LONGER IN SERVICE */ waserror= True; } } } } if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) { fprintf(qh ferr, "qhull internal error (checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n", numvertices, qh num_vertices - qh_setsize(qh del_vertices)); waserror= True; } if (qh hull_dim == 2 && numvertices != numfacets) { fprintf (qh ferr, "qhull internal error (checkpolygon): #vertices %d != #facets %d\n", numvertices, numfacets); waserror= True; } if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) { fprintf (qh ferr, "qhull internal error (checkpolygon): #vertices %d + #facets %d - #edges %d != 2\n", numvertices, numfacets, numridges/2); waserror= True; } } if (waserror) qhull_fatal(46); } /* checkpolygon */ /*------------------------------------------------- -checkvertex- check vertex for consistency notes: neighbors checked efficiently in checkpolygon */ void qh_checkvertex (vertexT *vertex) { boolT waserror= False; facetT *neighbor, **neighborp, *errfacet=NULL; if (qh_pointid (vertex->point) == -1) { fprintf (qh ferr, "qhull internal error (checkvertex): unknown point id %p\n", vertex->point); waserror= True; } if (vertex->id >= qh vertex_id) { fprintf (qh ferr, "qhull internal error (checkvertex): unknown vertex id %d\n", vertex->id); waserror= True; } if (!waserror && !vertex->deleted) { FOREACHneighbor_(vertex) { if (!qh_setin (neighbor->vertices, vertex)) { fprintf (qh ferr, "qhull internal error (checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id); errfacet= neighbor; waserror= True; } } } if (waserror) qhull_fatal(47); } /* checkvertex */ /*------------------------------------------------- -clearcenters- clear old data from facet->center sets new centertype nop if CENTERtype is the same */ void qh_clearcenters (int type) { facetT *facet; if (qh CENTERtype != type) { FORALLfacets { if (facet->center) { if (qh CENTERtype == qh_voronoi) qh_memfree (facet->center, qh center_size); else qh_memfree (facet->center, qh normal_size); facet->center= NULL; } } qh CENTERtype= type; } trace2((qh ferr, "clearcenters: switched to center type %d\n", type)); } /* clearcenters */ /*------------------------------------------------- -clearnewvertices- clear vertices from newvertex_list */ void qh_clearnewvertices (void /*qh newvertex_list*/) { vertexT *vertex; FORALLvertex_(qh newvertex_list) vertex->newlist= False; qh newvertex_list= NULL; } /* clearnewvertices */ /*------------------------------------------------- -clearvisible- clear facets from visible list resets NEWfacets */ void qh_clearvisible (void /*qh visible_list*/) { facetT *visible; FORALLvisible_facets visible->visible= False; qh num_visible= 0; qh visible_list= NULL; qh NEWfacets= False; } /* clearvisible */ /*---------------------------------------- -createsimplex- creates a simplex from a set of vertices returns: initializes qh facet_list to the simplex */ void qh_createsimplex(setT *vertices) { facetT *facet= NULL, *newfacet; boolT toporient= True; int vertex_i, vertex_n, nth, tempint; setT *newfacets= qh_settemp (qh hull_dim+1); vertexT *vertex; qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet(); qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL); FOREACHvertex_i_(vertices) { newfacet= qh_newfacet(); newfacet->vertices= qh_setnew_delnthsorted (vertices, vertex_n, vertex_i, 0); newfacet->toporient= toporient; qh_appendfacet(newfacet); qh_appendvertex (vertex); qh_setappend (&newfacets, newfacet); tempint = (int)toporient; tempint ^= True; toporient = (boolT)tempint; } FORALLnew_facets { nth= 0; FORALLfacet_(qh newfacet_list) { if (facet != newfacet) SETelem_(newfacet->neighbors, nth++)= facet; } qh_settruncate (newfacet->neighbors, qh hull_dim); } qh_settempfree (&newfacets); trace1((qh ferr, "qh_createsimplex: created simplex\n")); } /* createsimplex */ /*------------------------------------------------- -deletevisible- delete visible facets ridges and vertices already deleted horizon facets do not reference facets on qh visible_list new facets in qh newfacet_list returns: deletes each facet and removes from facetlist calls qh_clearvisible() uses qh visit_id; */ void qh_deletevisible (/*qh visible_list*/) { facetT *visible, *nextfacet; vertexT *vertex, **vertexp; int numvisible= 0; trace1((qh ferr, "qh_deletevisible: delete visible facets\n")); for (visible= qh visible_list; visible && visible->visible; visible= nextfacet) { /* deleting current */ nextfacet= visible->next; numvisible++; qh_delfacet(visible); } if (numvisible != qh num_visible) qhull_fatal(48); FOREACHvertex_(qh del_vertices) qh_delvertex (vertex); qh_settruncate (qh del_vertices, 0); qh_clearvisible(); } /* deletevisible */ /*------------------------------------------------- -delfacet- removes facet from facet_list and frees up its memory assumes vertices and ridges already freed */ void qh_delfacet(facetT *facet) { void **freelistp; trace5((qh ferr, "qh_delfacet: delete f%d\n", facet->id)); if (facet == qh tracefacet) qh tracefacet= NULL; qh_removefacet(facet); qh_memfree_(facet->normal, qh normal_size, freelistp); if (qh CENTERtype == qh_voronoi) { qh_memfree_(facet->center, qh center_size, freelistp); }else { qh_memfree_(facet->center, qh normal_size, freelistp); } qh_setfree(&(facet->neighbors)); if (facet->ridges) qh_setfree(&(facet->ridges)); qh_setfree(&(facet->vertices)); if (facet->outsideset) qh_setfree(&(facet->outsideset)); if (facet->coplanarset) qh_setfree(&(facet->coplanarset)); qh_memfree_(facet, sizeof(facetT), freelistp); } /* delfacet */ /*------------------------------------------------- -delridge- deletes ridge from data structures it belongs to and frees up the memory occupied by it notes: in merge.c, caller sets vertex->delridge for each vertex also freed in qh_freeqhull */ void qh_delridge(ridgeT *ridge) { void **freelistp; qh_setdel(ridge->top->ridges, ridge); qh_setdel(ridge->bottom->ridges, ridge); qh_setfree(&(ridge->vertices)); qh_memfree_(ridge, sizeof(ridgeT), freelistp); } /* delridge */ /*------------------------------------------------- -delvertex- deletes a vertex and frees its memory assumes vertex->adjacencies have been updated if needed unlinks for vertex_list */ void qh_delvertex (vertexT *vertex) { if (vertex == qh tracevertex) qh tracevertex= NULL; qh_removevertex (vertex); qh_setfree (&vertex->neighbors); qh_memfree(vertex, sizeof(vertexT)); } /* delvertex */ /*---------------------------------------- -facet3vertex- return temporary set of 3-d vertices in qh_ORIENTclock order */ setT *qh_facet3vertex (facetT *facet) { ridgeT *ridge, *firstridge; vertexT *vertex; int cntvertices, cntprojected=0; setT *vertices; cntvertices= qh_setsize(facet->vertices); vertices= qh_settemp (cntvertices); if (facet->simplicial) { if (cntvertices != 3) qhull_fatal(49); qh_setappend (&vertices, SETfirst_(facet->vertices)); if (facet->toporient ^ qh_ORIENTclock) qh_setappend (&vertices, SETsecond_(facet->vertices)); else qh_setaddnth (&vertices, 0, SETsecond_(facet->vertices)); qh_setappend (&vertices, SETelem_(facet->vertices, 2)); }else { ridge= firstridge= (ridgeT *)SETfirst_(facet->ridges); /* no infinite */ while ((ridge= qh_nextridge3d (ridge, facet, &vertex))) { qh_setappend (&vertices, vertex); if (++cntprojected > cntvertices || ridge == firstridge) break; } if (!ridge || cntprojected != cntvertices) qhull_fatal(50); } return vertices; } /* facet3vertex */ /*------------------------------------------------- -facetintersect- return vertices for intersection of two simplicial facets may include 1 prepended entry (if more, need to settemppush) returns: returns set of hull_dim-1 + optional extra returns skipped index for each test and checks for exactly one notes: does not need settemp since set in quick memory see also qh_vertexintersect and qh_vertexintersect_new use qh_setnew_delnthsorted to get nth ridge (no skip information) */ setT *qh_facetintersect (facetT *facetA, facetT *facetB, int *skipA,int *skipB, int prepend) { setT *intersect; int dim= qh hull_dim, i, j; facetT **neighborsA, **neighborsB; neighborsA= SETaddr_(facetA->neighbors, facetT); neighborsB= SETaddr_(facetB->neighbors, facetT); i= j= 0; if (facetB == *neighborsA++) *skipA= 0; else if (facetB == *neighborsA++) *skipA= 1; else if (facetB == *neighborsA++) *skipA= 2; else { for (i= 3; i < dim; i++) { if (facetB == *neighborsA++) { *skipA= i; break; } } } if (facetA == *neighborsB++) *skipB= 0; else if (facetA == *neighborsB++) *skipB= 1; else if (facetA == *neighborsB++) *skipB= 2; else { for (j= 3; j < dim; j++) { if (facetA == *neighborsB++) { *skipB= j; break; } } } if (i >= dim || j >= dim) qhull_fatal(51); intersect= qh_setnew_delnthsorted (facetA->vertices, qh hull_dim, *skipA, prepend); trace4((qh ferr, "qh_facetintersect: f%d skip %d matches f%d skip %d\n", facetA->id, *skipA, facetB->id, *skipB)); return(intersect); } /* facetintersect */ /*---------------------------------------- -gethash- return hashvalue for a set with firstindex and skipelem assumes at least firstindex+1 elements sum of elements does badly in high d assumes skipelem is NULL, in set, or part of hash */ unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem) { void **elemp= SETelemaddr_(set, firstindex, void); unsigned hash, elem; int i; switch (size-firstindex) { case 1: hash= (unsigned long)(*elemp) - (unsigned long) skipelem; break; case 2: hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] - (unsigned long) skipelem; break; case 3: hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] + (unsigned long)elemp[2] - (unsigned long) skipelem; break; case 4: hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] + (unsigned long)elemp[2] + (unsigned long)elemp[3] - (unsigned long) skipelem; break; case 5: hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] + (unsigned long)elemp[2] + (unsigned long)elemp[3] + (unsigned long)elemp[4] - (unsigned long) skipelem; break; case 6: hash= (unsigned long)(*elemp) + (unsigned long)elemp[1] + (unsigned long)elemp[2] + (unsigned long)elemp[3] + (unsigned long)elemp[4]+ (unsigned long)elemp[5] - (unsigned long) skipelem; break; default: hash= 0; i= 3; do { /* this is about 10% in 10-d */ if ((elem= (unsigned long)*elemp++) != (unsigned long)skipelem) { hash ^= (elem << i) + (elem >> (32-i)); i += 3; if (i >= 32) i -= 32; } }while(*elemp); break; } hash %= (unsigned) hashsize; /* hash= 0; for debugging purposes */ return hash; } /* gethash */ /*------------------------------------------------- -isvertex- returns vertex if point is in vertex set, else returns NULL */ vertexT *qh_isvertex (pointT *point, setT *vertices) { vertexT *vertex, **vertexp; FOREACHvertex_(vertices) { if (vertex->point == point) return vertex; } return NULL; } /* isvertex */ /*------------------------------------------------- -makenewfacet- creates a toporient? facet from vertices and apex modifies vertices returns: adds newfacet to qh facet_list facet->neighbor= horizon, but not vice versa facet->vertices= vertices= apex+vertices facet->hyperplane defined newvertex_list updated */ facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) { facetT *newfacet; vertexT *vertex, **vertexp; FOREACHvertex_(vertices) { if (!vertex->newlist) { vertex->newlist= True; qh_removevertex (vertex); qh_appendvertex (vertex); } } newfacet= qh_newfacet(); newfacet->vertices= vertices; newfacet->toporient= toporient; qh_setfacetplane (newfacet); qh_setappend(&(newfacet->neighbors), horizon); qh_appendfacet(newfacet); return(newfacet); } /* makenewfacet */ /*------------------------------------------------- -makenewfacets- make new facets from point and qh visible_list returns: qh newfacet_list= list of new facets with hyperplanes and id >= newfacet_id qh newvertex_list= list of vertices in new facets with 'new' set if (qh ONLYgood) newfacets reference horizon facets, but not vice versa ridges reference non-simplicial horizon ridges, but not vice versa does not change existing facets otherwise newfacets attached to horizon facets and ridges first neighbor of visible facet is corresponding new facet */ vertexT *qh_makenewfacets (pointT *point /*visible_list*/) { facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp; vertexT *apex; int numnew=0; qh newfacet_list= qh facet_tail; qh newvertex_list= qh vertex_tail; qh newfacet_id= qh facet_id; apex= qh_newvertex(point); apex->newlist= True; qh_appendvertex (apex); qh visit_id++; if (!qh ONLYgood) qh NEWfacets= True; FORALLvisible_facets { FOREACHneighbor_(visible) neighbor->seen= False; if (visible->ridges) { visible->visitid= qh visit_id; newfacet2= qh_makenew_nonsimplicial (visible, apex, &numnew); } if (visible->simplicial) newfacet= qh_makenew_simplicial (visible, apex, &numnew); if (!qh ONLYgood) { if (newfacet2) newfacet= newfacet2; if (!newfacet) zinc_(Zinsidevisible); SETfirst_(visible->neighbors)= newfacet; SETsecond_(visible->neighbors)= NULL; } } trace1((qh ferr, "qh_makenewfacets: created %d new facets from point p%d to horizon\n", numnew, qh_pointid(point))); /* if (qh IStracing >= 4) qh_printfacetlist (qh newfacet_list, NULL, qh_ALL); THIS IS NO LONGER IN SERVICE */ return apex; } /* makenewfacets */ /*--------------------------------------------- -makenew_nonsimplicial- make new facets for ridges of visible facets qh visit_id if visible has already been seen attaches new facets if !qh ONLY good assumes all 'seen' flags false returns: newfacet or NULL, bumps numnew as needed marks ridge neighbors for simplicial visible if (qh ONLYgood) ridges on newfacet, horizon, and visible else ridge and neighbors between newfacet and horizon visible facet's ridges are deleted */ facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew) { void **freelistp; ridgeT *ridge, **ridgep; facetT *neighbor, *newfacet= NULL; setT *vertices; boolT toporient = False; FOREACHridge_(visible->ridges) { neighbor= otherfacet_(ridge, visible); if (neighbor->visible) { if (!qh ONLYgood) { if ((int)neighbor->visitid == qh visit_id) { qh_setfree (&(ridge->vertices)); /* delete on 2nd visit */ qh_memfree_(ridge, sizeof(ridgeT), freelistp); } } }else { /* neighbor is an horizon facet */ toporient= (boolT)(ridge->top == visible); vertices= qh_setnew (qh hull_dim); /* makes sure this is quick */ qh_setappend (&vertices, apex); qh_setappend_set (&vertices, ridge->vertices); newfacet= qh_makenewfacet(vertices, toporient, neighbor); (*numnew)++; if (qh ONLYgood) { if (!neighbor->simplicial) qh_setappend(&(newfacet->ridges), ridge); }else { /* qh_attachnewfacets */ if (neighbor->seen) { if (neighbor->simplicial) qhull_fatal(52); qh_setappend (&(neighbor->neighbors), newfacet); }else qh_setreplace (neighbor->neighbors, visible, newfacet); if (neighbor->simplicial) { qh_setdel (neighbor->ridges, ridge); qh_setfree (&(ridge->vertices)); qh_memfree (ridge, sizeof(ridgeT)); }else { qh_setappend(&(newfacet->ridges), ridge); if (toporient) ridge->top= newfacet; else ridge->bottom= newfacet; } trace4((qh ferr, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n", newfacet->id, apex->id, ridge->id, neighbor->id)); } } neighbor->seen= True; } /* for each ridge */ if (!qh ONLYgood) SETfirst_(visible->ridges)= NULL; return newfacet; } /* makenew_nonsimplicial */ /*--------------------------------------------- -makenew_simplicial- make new facets for simplicial facet uses 'seen' flag attaches new facets if !qh ONLY good returns: newfacet or NULL, bumps numnew as needed if (!qh ONLYgood) neighbors between newfacet and horizon */ facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew) { facetT *neighbor, **neighborp, *newfacet= NULL; setT *vertices; boolT flip, toporient; int horizonskip, visibleskip; FOREACHneighbor_(visible) { if (!neighbor->seen && !neighbor->visible) { vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1); SETfirst_(vertices)= apex; flip= (boolT) ((horizonskip & 0x1) ^ (visibleskip & 0x1)); toporient=(boolT)( neighbor->toporient ^ !(horizonskip & 0x1) ); newfacet= qh_makenewfacet(vertices, toporient, neighbor); (*numnew)++; if (!qh ONLYgood) SETelem_(neighbor->neighbors, horizonskip)= newfacet; trace4((qh ferr, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n", newfacet->id, toporient, apex->id, neighbor->id, horizonskip, neighbor->toporient, visible->id, visibleskip, flip)); } } return newfacet; } /* makenew_simplicial */ /*------------------------------------------------- -matchduplicate- try to match an unmatched duplicated ridge returns: True if a match was made notes: found matching facet for a duplicate ridge. 1) if keep already found, merge this pair 2) if !flip&!flip, keep this 3) if flip & flip, merge this pair 4) otherwise, return False and continue */ boolT qh_matchduplicate (facetT *facet, int skip, facetT *newfacet, int newskip, boolT keepfound) { boolT ismatched= False; trace2((qh ferr, "qh_matchduplicate: duplicated f%d skip %d matches new f%d skip %d. ", facet->id, skip, newfacet->id, newskip)); if (keepfound) { SETelem_(facet->neighbors, skip)= newfacet; if (qh PREmerge) SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge; else SETelem_(newfacet->neighbors, newskip)= facet; trace2((qh ferr, "Merge this pair.\n")); ismatched= True; }else if (!facet->flipped && !newfacet->flipped) { SETelem_(facet->neighbors, skip)= newfacet; SETelem_(newfacet->neighbors, newskip)= facet; trace2((qh ferr, "Match good pair\n")); ismatched= True; }else if (facet->flipped && newfacet->flipped) { SETelem_(facet->neighbors, skip)= newfacet; if (qh PREmerge) SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge; else SETelem_(newfacet->neighbors, newskip)= facet; trace2((qh ferr, "Merge flipped pair\n")); ismatched= True; }else trace2((qh ferr, "No match, continue\n")); if (qh IStracing >= 4) { /* qh_errprint ("OLD/NEW", facet, newfacet, NULL, NULL); NO LONGER IN SERVICE */ qh_setprint (qh ferr, "facet's neighbors", facet->neighbors); qh_setprint (qh ferr, "newfacet's", newfacet->neighbors); } return ismatched; } /* matchduplicate */ /*-------------------------------------------- -matchmatch- try to match duplicate matching pair and newfacet returns: True if existing match is ok and continue with newfacet False if need to place matchfacet newmatched set if newfacet matched notes: 1) if pair is !flip&!flip, keep is found and continue 2) if pair is flip&flip, merge them and continue 3) otherwise, replace matchfacet if new pair is !flip&!flip, keep is found if new pair is flip&flip, merge them otherwise, mark duplicated and continue */ boolT qh_matchmatch (facetT *facet, int skip, facetT *matchfacet, facetT *newfacet, int newskip, boolT ismatch, boolT *keepfound, boolT *newmatched) { int matchskip; boolT ismatched= False; matchskip= qh_setindex (matchfacet->neighbors, facet); trace2((qh ferr, "qh_matchmatch: duplicated f%d skip %d matches f%d skip %d and new f%d skip %d. ", facet->id, skip, matchfacet->id, matchskip, newfacet->id, newskip)); if (!facet->flipped && !matchfacet->flipped) { *keepfound= True; trace2((qh ferr, "Keep good match\n")); ismatched= True; }else if (facet->flipped && matchfacet->flipped) { if (matchskip >= 0 && qh PREmerge) SETelem_(matchfacet->neighbors, matchskip)= qh_MERGEridge; trace2((qh ferr, "Both flipped, merge\n")); ismatched= True; }else { /* matched facets have opposite orientations, undo matchfacet */ SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge; if (ismatch && (facet->flipped == newfacet->flipped)) { SETelem_(facet->neighbors, skip)= newfacet; if (newfacet->flipped && qh PREmerge) SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge; else SETelem_(newfacet->neighbors, newskip)= facet; trace2((qh ferr, "Substitute new\n")); *newmatched= True; }else { SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge; *newmatched= False; trace2((qh ferr, "Undo match\n")); } } if (qh IStracing >= 4) { /* qh_errprint ("OLD/MATCH", facet, matchfacet, NULL, NULL); qh_errprint ("NEW", newfacet, NULL, NULL, NULL); NO LONGER IN SERVICE */ qh_setprint (qh ferr, "facet's neighbors", facet->neighbors); qh_setprint (qh ferr, "matchfacet's", matchfacet->neighbors); qh_setprint (qh ferr, "newfacet's", newfacet->neighbors); } return ismatched; } /* qh_matchmatch */ /*------------------------------------------------- -matchneighbor- match subridge of newfacet with neighbor or add to hash_table ridge is newfacet->vertices w/o newskip vertex flipped tested if PREmerge or FORCEoutput use matchall to match unmatched duplicates returns: at end of matching duplicate ridges, one !flipped,!flipped matched flipped,flipped matched with MERGEridge back pointers rest are unmatched, with a DUPLICATEridge link all facets involved have seen set and flip tested notes: do not allocate memory (need to free hash_table cleanly) matches flipped,flipped since these get merged anyway uses linear hash chains */ void qh_matchneighbor (facetT *newfacet, int newskip, int hashsize, int *hashcount, boolT matchall) { boolT keepfound= False; /* True, if !flip,!flip duplicate ridge found */ boolT duplicated= False; /* True, if duplicate ridge detected */ boolT newfound= False; /* True, if new facet is already in hash chain */ boolT same, ismatch, newmatched; unsigned hash, scan; facetT *facet, *matchfacet; int skip; hash= qh_gethash (hashsize, newfacet->vertices, qh hull_dim, 1, SETelem_(newfacet->vertices, newskip)); trace4((qh ferr, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n", newfacet->id, newskip, hash, *hashcount)); zinc_(Zhashlookup); while ((facet= (facetT *)SETelem_(qh hash_table, hash))) { if (facet == newfacet) { newfound= True; goto LABELnexthash; } zinc_(Zhashtests); if (qh_matchvertices (1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) { if (SETelem_(newfacet->vertices, newskip) == SETelem_(facet->vertices, skip)) qhull_fatal(53); ismatch= (boolT) (same == (int)(newfacet->toporient ^ facet->toporient)); matchfacet= (facetT *)SETelem_(facet->neighbors, skip); if (matchfacet == qh_MERGEridge) goto LABELnexthash; else if (matchfacet == qh_DUPLICATEridge) { duplicated= True; matchfacet= NULL; }else if (ismatch && !matchfacet && !duplicated) { SETelem_(facet->neighbors, skip)= newfacet; SETelem_(newfacet->neighbors, newskip)= facet; (*hashcount)--; trace4((qh ferr, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n", facet->id, skip, newfacet->id, newskip)); return; } if (!qh PREmerge) qhull_fatal(54); if (matchall) { if (matchfacet || !ismatch) goto LABELnexthash; SETelem_(facet->neighbors, skip)= newfacet; SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge; /* this may merge one more ridge than necessary, but hard to detect */ (*hashcount) -= 2; /* removed two unmatched facets */ zzinc_(Zmultiflip); trace2((qh ferr, "qh_matchneighbor: duplicate f%d skip %d matched with new f%d skip %d\n", facet->id, skip, newfacet->id, newskip)); return; } duplicated= True; newfacet->seen= True; facet->seen= True; if (matchfacet) matchfacet->seen= True; if (!matchfacet && ismatch) { if (qh_matchduplicate (facet, skip, newfacet, newskip, keepfound)) { zzinc_(Zmultimatch); (*hashcount)--; return; } }else if (matchfacet && !keepfound) { if (!qh_matchmatch (facet, skip, matchfacet, newfacet, newskip, ismatch, &keepfound, &newmatched)) { scan= hash; while ((facet= (facetT *)SETelem_(qh hash_table, scan))) { if (facet == matchfacet) break; if ((int)(++scan) >= hashsize) scan= 0; } if (!facet) SETelem_(qh hash_table, scan)= matchfacet; (*hashcount)++; if (newmatched) return; else (*hashcount)++; } } } LABELnexthash: if ((int)(++hash) >= hashsize) hash= 0; /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */ } (*hashcount)++; if (!newfound) SETelem_(qh hash_table, hash)= newfacet; if (duplicated) { SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge; trace4((qh ferr, "qh_matchneighbor: no match for duplicated f%d skip %d at hash %d\n", newfacet->id, newskip, hash)); }else trace4((qh ferr, "qh_matchneighbor: no match for f%d skip %d at hash %d\n", newfacet->id, newskip, hash)); } /* matchneighbor */ /*------------------------------------------------- -matchnewfacets- match newfacets in qh newfacet_list to their newfacet neighbors newfacets already have neighbor[0] (horizon facet) assumes qh hash_table is NULL returns: qh newfacet_list with full neighbor sets get vertices with nth neighbor by deleting nth vertex if PREmerge or FORCEoutput all facets check for flipped (also prevents point partitioning) if duplicate ridges and PREmerge facet->seen set missing neighbor links identifies extra ridges to be merging notes: do not allocate memory after hash_table (need to free it cleanly) */ void qh_matchnewfacets (void) { int numnew=0, numfree= 0, hashcount=0, newskip, nth=0; facetT *newfacet, *neighbor, **neighborp, *facet; int facet_i, facet_n, dim= qh hull_dim, hashsize; setT *neighbors; trace1((qh ferr, "qh_matchnewfacets: match neighbors for new facets.\n")); FORALLnew_facets { numnew++; { /* qh_setzero (newfacet->neighbors, 1, qh hull_dim); */ neighbors= newfacet->neighbors; neighbors->e[neighbors->maxsize]= (void *)(dim+1); /*may be overwritten*/ memset ((char *)&neighbors->e[1], 0, dim * sizeof(void *)); } if (qh MERGING) qh_checkflipped (newfacet, NULL, qh_ALL); } if (qh FORCEoutput && !qh MERGING) qh_checkflipped_all (qh newfacet_list); /* prints warnings for flipped */ qh_newhashtable (numnew*(qh hull_dim-1)); /* twice what is normally needed, but every ridge could be DUPLICATEridge */ hashsize= qh_setsize (qh hash_table); FORALLnew_facets { newfacet->seen= False; for (newskip=1; newskipneighbors, k); if (!neighbor || neighbor == qh_DUPLICATEridge) count++; } if (facet == newfacet) break; } if (count != hashcount) qhull_fatal(55); } #endif /* end of trap code */ } if (hashcount) { FORALLnew_facets { if (newfacet->seen) { nth= 0; FOREACHneighbor_(newfacet) { if (neighbor == qh_DUPLICATEridge) { trace2((qh ferr, "qh_matchnewfacets: find good/flip match for duplicated f%d skip %d\n", newfacet->id, nth)); qh_matchneighbor (newfacet, nth, hashsize, &hashcount, qh_ALL); /* if (qh IStracing >= 4) qh_errprint ("DUPLICATED/MATCH", newfacet, (facetT*)SETelem_(newfacet->neighbors, nth), NULL, NULL); NO LONGER IN SERVICE */ /* this may report MERGEfacet */ } nth++; } } } } if (hashcount) qhull_fatal(56); if (qh IStracing >= 2) { FOREACHfacet_i_(qh hash_table) { if (!facet) numfree++; } fprintf (qh ferr, "qh_matchnewfacets: %d new facets, %d unused hash entries . hashsize %d\n", numnew, numfree, qh_setsize (qh hash_table)); } qh_setfree (&qh hash_table); /* if (qh IStracing >= 4 && qh PREmerge) qh_printfacetlist (qh newfacet_list, NULL, qh_ALL); THIS IS NO LONGER IN SERVICE */ } /* matchnewfacets */ /*---------------------------------------- -matchvertices- tests whether vertices match with a single skip starts match at firstindex since all new facets have a common vertex assumes skipA is in A and both sets are the same size returns: skip index sets same iff vertices have the same orientation */ boolT qh_matchvertices (int firstindex, setT *verticesA, int skipA, setT *verticesB, int *skipB, boolT *same) { vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp; elemAp= SETelemaddr_(verticesA, firstindex, vertexT); elemBp= SETelemaddr_(verticesB, firstindex, vertexT); skipAp= SETelemaddr_(verticesA, skipA, vertexT); do if (elemAp != skipAp) { while (*elemAp != *elemBp++) { if (skipBp) return False; skipBp= elemBp; /* one extra like FOREACH */ } }while(*(++elemAp)); if (!skipBp) skipBp= ++elemBp; *skipB= (int)SETindex_(verticesB, skipB); *same= (boolT)(!(((unsigned)skipA & 0x1) ^ ((unsigned)*skipB & 0x1))); trace4((qh ferr, "qh_matchvertices: matched by skip %d (v%d) and skip %d (v%d) same? %d\n", skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same)); return (True); } /* matchvertices */ /*---------------------------------------- -nextridge3d- return next ridge and vertex for a 3d facet in qh_ORIENTclock order n^2 implementation to trace all ridges be sure to stop on any 2nd visit */ ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) { vertexT *atvertex, *vertex, *othervertex; ridgeT *ridge, **ridgep; if ((atridge->top == facet) ^ qh_ORIENTclock) atvertex= (vertexT *)SETsecond_(atridge->vertices); else atvertex= (vertexT *)SETfirst_(atridge->vertices); FOREACHridge_(facet->ridges) { if (ridge == atridge) continue; if ((ridge->top == facet) ^ qh_ORIENTclock) { othervertex= (vertexT *)SETsecond_(ridge->vertices); vertex= (vertexT *)SETfirst_(ridge->vertices); }else { vertex= (vertexT *)SETsecond_(ridge->vertices); othervertex= (vertexT *)SETfirst_(ridge->vertices); } if (vertex == atvertex) { if (vertexp) *vertexp= othervertex; return ridge; } } return NULL; } /* nextridge3d */ /*---------------------------------------- -newfacet- creates and allocates space for a facet returns: all fields initialized or cleared (NULL) preallocates neighbors */ facetT *qh_newfacet(void) { facetT *facet = NULL; void **freelistp; facetT_qh_memalloc_(sizeof(facetT), freelistp, facet); memset ((char *)facet, 0, sizeof(facetT)); if (qh facet_id == 0xFFFFFF) { fprintf(qh ferr, "\ qhull warning: more than %d facets. Id field overflows and two facets\n\ may have the same identifier. Otherwise output ok.\n", 0xFFFFFF); } if (qh facet_id == (int)qh tracefacet_id) qh tracefacet= facet; facet->id= qh facet_id++; facet->neighbors= qh_setnew(qh hull_dim); #if !qh_COMPUTEfurthest facet->furthestdist= 0.0; #endif #if qh_MAXoutside if (qh FORCEoutput && qh APPROXhull) facet->maxoutside= qh MINoutside; else facet->maxoutside= qh DISTround; #endif facet->simplicial= True; facet->good= True; trace4((qh ferr, "qh_newfacet: created facet f%d\n", facet->id)); return (facet); } /* newfacet */ /*------------------------------------------------- -newhashtable- returns size of qh hash_table of at least newsize slots assumes qh hash_table is NULL qh_HASHfactor determines the number of extra slots */ int qh_newhashtable(int newsize) { int size; size= ((newsize+1)*qh_HASHfactor) | 0x1; /* odd number */ while (True) { if ((size%3) && (size%5)) break; size += 2; /* loop terminates because there is an infinite number of primes */ } qh hash_table= qh_setnew (size); qh_setzero (qh hash_table, 0, size); return size; } /* newhashtable */ /*---------------------------------------- -newridge- creates and allocates space for a ridge */ ridgeT *qh_newridge(void) { ridgeT *ridge = NULL; void **freelistp; ridgeT_qh_memalloc_(sizeof(ridgeT), freelistp, ridge); memset ((char *)ridge, 0, sizeof(ridgeT)); zinc_(Ztotridges); if (qh ridge_id == 0xFFFFFF) { fprintf(qh ferr, "\ qhull warning: more than %d ridges. Id field overflows and two ridges\n\ may have the same identifier. Otherwise output ok.\n", 0xFFFFFF); } ridge->id= qh ridge_id++; trace4((qh ferr, "qh_newridge: created ridge r%d\n", ridge->id)); return (ridge); } /* newridge */ /*---------------------------------------- -newvertex- creates and allocates space for a vertex */ vertexT *qh_newvertex(pointT *point) { vertexT *vertex; zinc_(Ztotvertices); vertex= (vertexT *)qh_memalloc(sizeof(vertexT)); memset ((char *) vertex, 0, sizeof (vertexT)); if (qh vertex_id == 0xFFFFFF) qhull_fatal(57); if (qh vertex_id == qh tracevertex_id) qh tracevertex= vertex; vertex->id= qh vertex_id++; vertex->point= point; trace4((qh ferr, "qh_newvertex: vertex p%d (v%d) created\n", qh_pointid(vertex->point), vertex->id)); return (vertex); } /* newvertex */ /*------------------------------------------------- -point- return point for a point id, or NULL if unknown */ pointT *qh_point (int id) { if (id < 0) return NULL; if (id < qh num_points) return ((pointT *)((unsigned long)qh first_point+(unsigned long)((id)*qh normal_size))); id -= qh num_points; if (id < qh_setsize (qh other_points)) return (pointT *)SETelem_(qh other_points, id); return NULL; } /* point */ /*------------------------------------------------- -point_add- access function for pointfacet and pointvertex */ void qh_point_add (setT *set, pointT *point, void *elem) { int id; if ((id= qh_pointid(point)) == -1) fprintf (qh ferr, "qhull internal warning (pointfacet,pointvertex): unknown point %p\n", point); else SETelem_(set, id)= elem; } /* point_add */ /*------------------------------------------------- -pointfacet- return temporary set of facets indexed by point id for vertices, coplanarset, and outsideset access with FOREACHfacet_i_(facets) and SETelem_(facets, i) NULL if no facet for point (inside) this will include qh GOODpointp */ setT *qh_pointfacet (void /*qh facet_list*/) { int numpoints= qh num_points + qh_setsize (qh other_points); setT *facets; facetT *facet; vertexT *vertex, **vertexp; pointT *point, **pointp; facets= qh_settemp (numpoints); qh_setzero (facets, 0, numpoints); qh vertex_visit++; FORALLfacets { FOREACHvertex_(facet->vertices) { if ((int)vertex->visitid != qh vertex_visit) { vertex->visitid= qh vertex_visit; qh_point_add (facets, vertex->point, facet); } } FOREACHpoint_(facet->coplanarset) qh_point_add (facets, point, facet); FOREACHpoint_(facet->outsideset) qh_point_add (facets, point, facet); } return facets; } /* pointfacet */ /*------------------------------------------------- -pointid- return id for a point, -3 if null, -2 if interior, or -1 if not known */ int qh_pointid (pointT *point) { unsigned id; if (!point) return -3; id= ((unsigned long) point - (unsigned long) qh first_point)/qh normal_size; if ((int)id >= qh num_points) { if (point == qh interior_point) id= (unsigned int) -2; else if ((int)(id= qh_setindex (qh other_points, point)) != -1) id += qh num_points; } return (int) id; } /* pointid */ /*------------------------------------------------- -pointvertex- return temporary set of vertices indexed by point id access with FOREACHvertex_i_(vertices) and SETelem_(vertices, i) NULL if no vertex for point this will include qh GOODpointp */ setT *qh_pointvertex (void /*qh facet_list*/) { int numpoints= qh num_points + qh_setsize (qh other_points); setT *vertices; vertexT *vertex; vertices= qh_settemp (numpoints); qh_setzero (vertices, 0, numpoints); FORALLvertices qh_point_add (vertices, vertex->point, vertex); return vertices; } /* pointvertex */ /*------------------------------------------------- -prependfacet- prepend facet to the start of a facetlist increments qh numfacets updates facetlist, qh facet_list, facet_next notes: be careful of prepending since it can lose a pointer. e.g., can lose _next by deleting and then prepending before _next */ void qh_prependfacet(facetT *facet, facetT **facetlist) { facetT *prevfacet, *list= *facetlist; trace4((qh ferr, "qh_prependfacet: prepend f%d before f%d\n", facet->id, list->id)); prevfacet= list->previous; facet->previous= prevfacet; if (prevfacet) prevfacet->next= facet; list->previous= facet; facet->next= *facetlist; if (qh facet_list == list) /* this may change *facetlist */ qh facet_list= facet; if (qh facet_next == list) qh facet_next= facet; *facetlist= facet; qh num_facets++; } /* prependfacet */ /*----------------------------------------- -printhashtable- print hash table not in I/O to avoid bringing io.c in */ void qh_printhashtable(FILE *fp) { facetT *facet, *neighbor; int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0; vertexT *vertex, **vertexp; FOREACHfacet_i_(qh hash_table) { if (facet) { FOREACHneighbor_i_(facet) { if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) break; } if (neighbor_i == neighbor_n) continue; fprintf (fp, "hash %d f%d ", facet_i, facet->id); FOREACHvertex_(facet->vertices) fprintf (fp, "v%d ", vertex->id); fprintf (fp, "\n neighbors:"); FOREACHneighbor_i_(facet) { if (neighbor == qh_MERGEridge) id= -3; else if (neighbor == qh_DUPLICATEridge) id= -2; else id= getid_(neighbor); fprintf (fp, " %d", id); } fprintf (fp, "\n"); } } } /* printhashtable */ /*------------------------------------------------- -printlists- print out facet and vertex list for debugging (without 'f/v' tags) */ void qh_printlists (void) { facetT *facet; vertexT *vertex; fprintf (qh ferr, "qh_printlists: facets:"); FORALLfacets fprintf (qh ferr, " %d", facet->id); fprintf (qh ferr, "\n new facets %d visible facets %d next facet for addpoint %d\n vertices (new %d):", getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next), getid_(qh newvertex_list)); FORALLvertices fprintf (qh ferr, " %d", vertex->id); fprintf (qh ferr, "\n"); } /* printlists */ /*------------------------------------------------- -removefacet- unlinks facet from qh facet_list, updates qh facet_list .newfacet_list .facet_next visible_list decrements qh num_facets */ void qh_removefacet(facetT *facet) { facetT *next= facet->next, *previous= facet->previous; if (facet == qh newfacet_list) qh newfacet_list= next; if (facet == qh facet_next) qh facet_next= next; if (facet == qh visible_list) qh visible_list= next; if (previous) { previous->next= next; next->previous= previous; }else { /* 1st facet in qh facet_list */ qh facet_list= next; qh facet_list->previous= NULL; } qh num_facets--; trace4((qh ferr, "qh_removefacet: remove f%d from facet_list\n", facet->id)); } /* removefacet */ /*------------------------------------------------- -removevertex- unlinks vertex from qh vertex_list, updates qh vertex_list .newvertex_list decrements qh num_vertices */ void qh_removevertex(vertexT *vertex) { vertexT *next= vertex->next, *previous= vertex->previous; if (vertex == qh newvertex_list) qh newvertex_list= next; if (previous) { previous->next= next; next->previous= previous; }else { /* 1st vertex in qh vertex_list */ qh vertex_list= vertex->next; qh vertex_list->previous= NULL; } qh num_vertices--; trace4((qh ferr, "qh_removevertex: remove v%d from vertex_list\n", vertex->id)); } /* removevertex */ /*------------------------------------------------- -vertexintersect- intersects two vertex sets (inverse id ordered) temporary set vertexsetA is replaced by the intersection must be at top of stack could overwrite vertexsetA if currently too slow */ void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) { setT *intersection; intersection= qh_vertexintersect_new (*vertexsetA, vertexsetB); qh_settempfree (vertexsetA); *vertexsetA= intersection; qh_settemppush (intersection); } /* vertexintersect */ /*------------------------------------------------- -vertexintersect_new- intersects two vertex sets (inverse id ordered) returns: a new set */ setT *qh_vertexintersect_new (setT *vertexsetA,setT *vertexsetB) { setT *intersection= qh_setnew (qh hull_dim - 1); vertexT **vertexA= SETaddr_(vertexsetA, vertexT); vertexT **vertexB= SETaddr_(vertexsetB, vertexT); while (*vertexA && *vertexB) { if (*vertexA == *vertexB) { qh_setappend(&intersection, *vertexA); vertexA++; vertexB++; }else { if ((*vertexA)->id > (*vertexB)->id) vertexA++; else vertexB++; } } return intersection; } /* vertexintersect_new */ /*------------------------------------------- -vertexneighhbors- for each vertex in hull, determine facet neighbors nop if VERTEXneighbors assumes all vertex->neighbors are NULL returns: sets qh VERTEXneighbors, qh_addpoint() will maintain them */ void qh_vertexneighbors (void /*qh facet_list*/) { facetT *facet; vertexT *vertex, **vertexp; if (qh VERTEXneighbors) return; trace1((qh ferr, "qh_vertexneighbors: determing neighboring facets for each vertex\n")); qh vertex_visit++; FORALLfacets { FOREACHvertex_(facet->vertices) { if ((int)vertex->visitid != qh vertex_visit) { vertex->visitid= qh vertex_visit; vertex->neighbors= qh_setnew (qh hull_dim); } qh_setappend (&vertex->neighbors, facet); } } qh VERTEXneighbors= True; } /* vertexneighbors */ /*------------------------------------------------- -vertexsubset- returns True if vertexsetA is a subset of vertexsetB, False otherwise; relies on vertexsets being sorted; an empty set is a subset of any other set */ boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) { vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT); vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT); while (True) { if (!*vertexA) return True; if (!*vertexB) return False; if ((*vertexA)->id > (*vertexB)->id) return False; if (*vertexA == *vertexB) vertexA++; vertexB++; } } /* vertexsubset */ /*************************************************************************/ /****************** implementation code from merge.c *********************/ /*************************************************************************/ /* merge.c - merges non-convex facets see README and merge.h other modules call qh_merge_nonconvex() and facetdegen() to avoid loading merge.o, redefine them to null procedures (user.c) assumes neighbor sets for each vertex (qh VERTEXneighbors) assumes qh CENTERtype= centrum copyright (c) 1993-1994 The Geometry Center */ static int qh_compareangle(const void *p1, const void *p2); static int qh_comparevisit (const void *p1, const void *p2); /*------------------------------------------------- -appendmergeset- appends an entry to facet_mergeset, angle is optional all other fields 0 returns: merge notes: see test_appendmerge() */ mergeT *qh_appendmergeset(facetT *facet, facetT *neighbor, realT *angle) { mergeT *merge; void **freelistp; mergeT_qh_memalloc_(sizeof(mergeT), freelistp, merge); memset ((char*) merge, 0, sizeof(mergeT)); merge->facet1= facet; merge->facet2= neighbor; if (angle) merge->angle= *angle; qh_setappend(&(qh facet_mergeset), merge); return merge; } /* appendmergeset */ /*------------------------------------------------- -checkridge_boundary- checks that ridges of a facet are boundaryless, nop if qh hull_dim < 3 or simplicial may miss a few errors if pinched facets */ void qh_checkridge_boundary (facetT *facet) { #if 0 ridgeT *ridge, **ridgep, *ridgeA, *errridge= NULL; vertexT *vertex, **vertexp; int unmatched= 0, matches=0, hashsize, hashslot; /* this code doesn't work because hash buckets can coalesce */ if (qh hull_dim < 3 || facet->simplicial) return; trace3((qh ferr, "qh_checkridge_boundary: check subridges for f%d\n", facet->id)); hashsize= qh_newhashtable (qh_setsize (facet->ridges)); FOREACHridge_(facet->ridges) ridge->seen= False; FOREACHridge_(facet->ridges) { FOREACHvertex_(ridge->vertices) { if ((ridgeA= qh_hashridge_find (qh hash_table, hashsize, ridge, vertex, NULL, &hashslot))) { matches++; ridgeA->seen ^= True; }else { unmatched++; ridge->seen ^= True; if (hashslot != -1) SETelem_(qh hash_table, hashslot)= ridge; } } } FOREACHridge_(facet->ridges) { if (ridge->seen) { fprintf(qh ferr, "qhull internal error (checkridge_boundary): subridges of r%d in f%d don't match up\n", ridge->id, facet->id); errridge= ridge; } } if (errridge || unmatched > matches || ((matches-unmatched) ^ 0x1)) qhull_fatal(58); qh_settempfree (&qh hash_table); #endif } /* checkridge_boundary */ /*------------------------------------------------- -compareangle- used by qsort() to order merges by the angle between them */ static int qh_compareangle(const void *p1, const void *p2) { mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2); return ((a->angle > b->angle) ? 1 : -1); } /* compareangle */ /*------------------------------------------------- -comparevisit- used by qsort() to order vertices by their visitid */ static int qh_comparevisit (const void *p1, const void *p2) { vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2); return (a->visitid - b->visitid); } /* comparevisit */ /*------------------------------------------------ -copynonconvex- copy non-convex flag to all ridges between same neighbors */ void qh_copynonconvex (ridgeT *atridge) { boolT nonconvex = False; facetT *facet, *otherfacet; ridgeT *ridge, **ridgep; nonconvex= (boolT) atridge->nonconvex; facet= atridge->top; otherfacet= atridge->bottom; FOREACHridge_(facet->ridges) { if (otherfacet == otherfacet_(ridge, facet)) ridge->nonconvex= nonconvex; } } /* copynonconvex */ /*------------------------------------------------ -degen_redundant_neighbors- append degen. and redundant neighbors to facet_mergeset also checks current facet for degeneracy bumps visitid called for each mergefacet(), merge and statistics occur in merge_nonconvex redundant facets will be merged before degenerate ones notes: a degenerate facet doesn't have enough neighbors a redundant facet's vertices is a subset of its neighbor's vertices */ void qh_degen_redundant_neighbors (facetT *facet) { vertexT *vertex, **vertexp; facetT *neighbor, **neighborp; int size; realT angledegen= qh_ANGLEdegen, angleredundant= qh_ANGLEredundant; trace3((qh ferr, "qh_degen_redundant_neighbors: test neighbors of f%d\n", facet->id)); if ((size= qh_setsize (facet->neighbors)) < qh hull_dim) { qh_appendmergeset (facet, facet, &angledegen); trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate.\n", facet->id)); } FOREACHneighbor_(facet) { /* first so that redundant merges occur first */ if ((size= qh_setsize (neighbor->neighbors)) < qh hull_dim) { qh_appendmergeset (neighbor, neighbor, &angledegen); trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate. Neighbor of f%d.\n", neighbor->id, facet->id)); } } qh vertex_visit++; FOREACHvertex_(facet->vertices) vertex->visitid= qh vertex_visit; FOREACHneighbor_(facet) { FOREACHvertex_(neighbor->vertices) { if ((int)vertex->visitid != qh vertex_visit) break; } if (!vertex) { qh_appendmergeset (neighbor, facet, &angleredundant); trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is contained in f%d. merge\n", neighbor->id, facet->id)); } } } /* degen_redundant_neighbors */ /*------------------------------------------------- -facetdegen- true if facet already in mergeset as a degenerate */ boolT qh_facetdegen (facetT *facet) { mergeT *merge, **mergep; FOREACHmerge_(qh facet_mergeset) { if (merge->facet1 == facet && merge->angle == qh_ANGLEdegen) return True; } return False; } /* facetdegen */ /*----------------------------------------- -find_newvertex - locate new vertex for renaming old vertex each ridge includes oldvertex vertices consists of possible new vertices returns: newvertex or NULL vertices sorted by number of deleted ridges notes: new vertex is in one of the ridges renaming will not cause a duplicate ridge renaming will minimize the number of deleted ridges newvertex may not be adjacent in the dual (though unlikely) */ vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges) { vertexT *vertex, **vertexp; setT *newridges; ridgeT *ridge, **ridgep, *dupridge; int size, hashsize; int hash; if (qh IStracing >= 4) { fprintf (qh ferr, "qh_find_newvertex: find new vertex for v%d from ", oldvertex->id); FOREACHvertex_(vertices) fprintf (qh ferr, "v%d ", vertex->id); FOREACHridge_(ridges) fprintf (qh ferr, "r%d ", ridge->id); fprintf (qh ferr, "\n"); } FOREACHvertex_(vertices) vertex->visitid= 0; FOREACHridge_(ridges) { FOREACHvertex_(ridge->vertices) vertex->visitid++; } FOREACHvertex_(vertices) { if (!vertex->visitid) { qh_setdelnth (vertices, SETindex_(vertices,vertex)); vertexp--; /* repeat since deleted this vertex */ } } qh vertex_visit += qh_setsize (ridges); if (!qh_setsize (vertices)) { trace4((qh ferr, "qh_find_newvertex: vertices not in ridges for v%d\n", oldvertex->id)); return NULL; } qsort (SETaddr_(vertices, vertexT), qh_setsize (vertices), sizeof (vertexT *), qh_comparevisit); /* can now use qh vertex_visit */ if (qh PRINTstatistics) { size= qh_setsize (vertices); zinc_(Zintersect); zadd_(Zintersecttot, size); zmax_(Zintersectmax, size); } hashsize= qh_newhashtable (qh_setsize (ridges)); FOREACHridge_(ridges) qh_hashridge (qh hash_table, hashsize, ridge, oldvertex); FOREACHvertex_(vertices) { newridges= qh_vertexridges (vertex); FOREACHridge_(newridges) { if ((dupridge= qh_hashridge_find (qh hash_table, hashsize, ridge, vertex, oldvertex, &hash))) { zinc_(Zdupridge); break; } } qh_settempfree (&newridges); if (!ridge) break; /* found a rename */ } if (vertex) { zinc_(Zfindvertex); trace2((qh ferr, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n", vertex->id, oldvertex->id, qh_setsize (vertices), qh_setsize (ridges))); }else { zinc_(Zfindfail); trace0((qh ferr, "qh_find_newvertex: no vertex for renaming v%d (all duplicated ridges)\n", oldvertex->id)); } qh_setfree (&qh hash_table); return vertex; } /* find_newvertex */ /*------------------------------------------------- -findbest_test- test neighbor for findbestneighbor() either test centrum or vertices */ void qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor, facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) { realT dist, mindist, maxdist; if (testcentrum) { zzinc_(Zbestdist); qh_distplane(facet->center, neighbor, &dist); dist *= qh hull_dim; /* estimate furthest vertex */ if (dist < 0) { maxdist= 0; mindist= dist; dist= -dist; }else maxdist= dist; }else dist= qh_getdistance (facet, neighbor, &mindist, &maxdist); if (dist < *distp) { *bestfacet= neighbor; *mindistp= mindist; *maxdistp= maxdist; *distp= dist; } } /* findbest_test */ /*------------------------------------------------- -findbestneighbor- finds best neighbor (least dist) of a facet for merging returns min and max distances and their max absolute value avoids merging old into new */ facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) { facetT *neighbor, **neighborp, *bestfacet= NULL; ridgeT *ridge, **ridgep; boolT nonconvex= True, testcentrum= False; int size= qh_setsize (facet->vertices); *distp= REALmax; if (size > qh hull_dim + qh_BESTcentrum) { testcentrum= True; zinc_(Zbestcentrum); if (!facet->center) facet->center= qh_getcentrum (facet); } if (size > qh hull_dim * qh_BESTnonconvex) { FOREACHridge_(facet->ridges) { if (ridge->nonconvex) { neighbor= otherfacet_(ridge, facet); qh_findbest_test (testcentrum, facet, neighbor, &bestfacet, distp, mindistp, maxdistp); } } } if (!bestfacet) { nonconvex= False; FOREACHneighbor_(facet) qh_findbest_test (testcentrum, facet, neighbor, &bestfacet, distp, mindistp, maxdistp); } if (!bestfacet) qhull_fatal(59); trace4((qh ferr, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n", bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp)); return(bestfacet); } /* findbestneighbor */ /*------------------------------------------------- -flippedmerges- merge flipped facets into best neighbor facet_mergeset may have degen/redundant from forced merges assumes facet_mergeset at top of temp stack returns: no flipped facets on facetlist degen/redundant merges passed through */ void qh_flippedmerges(facetT *facetlist) { facetT *facet, *neighbor, *facet1, *facet2; realT dist, mindist, maxdist; mergeT *merge; setT *othermerges= qh_settemp (qh TEMPsize); int nummerge=0; trace2((qh ferr, "qh_flippedmerges: begin\n")); FORALLfacet_(facetlist) { if (facet->flipped) qh_appendmergeset (facet, facet, NULL); } while ((merge= (mergeT *)qh_setdellast (qh facet_mergeset))) { if (merge->angle >= qh_ANGLEdegen) { /* and qh_ANGLEredundant */ qh_setappend (&othermerges, merge); continue; } facet1= merge->facet1; facet2= merge->facet2; qh_memfree (merge, sizeof(mergeT)); if (facet1->visible || facet2->visible) continue; if (qh TRACEmerge-1 == zzval_(Ztotmerge)) qhmem.IStracing= qh IStracing= qh TRACElevel; neighbor= qh_findbestneighbor (facet1, &dist, &mindist, &maxdist); trace0((qh ferr, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g\n", facet1->id, neighbor->id, dist)); qh_mergefacet (facet1, neighbor, &mindist, &maxdist, NULL); nummerge++; if (qh PRINTstatistics) { zinc_(Zflipped); wadd_(Wflippedtot, dist); wmax_(Wflippedmax, dist); } } if (qh_setsize (othermerges)) { qh_settemppop(); /* othermerges, errors here will leave memory */ qh_settempfree (&qh facet_mergeset); qh facet_mergeset= othermerges; qh_settemppush (othermerges); }else qh_settempfree (&othermerges); trace1((qh ferr, "qh_flippedmerges: merged %d flipped facets into a good neighbor\n", nummerge)); } /* flippedmerges */ /*------------------------------------------------- -forcedmerges- merge across duplicated ridges and mutually flipped facets duplicate ridges marked by MERGEridge and both sides facet->seen bumps visit_id assumes no merge has merge->newmerge returns: all neighboring, flipped facets merged together no duplicate ridges facet_mergeset includes any degen/redundant merges uses facet-tested notes: duplicate ridges occur when the horizon is pinched, i.e. a subridge occurs in more than two horizon ridges. could rename vertices that pinch the horizon */ void qh_forcedmerges(facetT *facetlist) { facetT *facet, *neighbor, **neighborp, *facet1, *facet2; mergeT *merge, **mergep; realT dist1, dist2, mindist1, mindist2, maxdist1, maxdist2; int nummerge=0, numflip=0; if (qh TRACEmerge-1 == zzval_(Ztotmerge)) qhmem.IStracing= qh IStracing= qh TRACElevel; trace2((qh ferr, "qh_forcedmerges: begin\n")); qh visit_id++; FORALLfacet_(facetlist) { facet->tested= True; if (facet->seen || facet->flipped) { facet->visitid= qh visit_id; FOREACHneighbor_(facet) { if (neighbor == qh_MERGEridge) { facet->tested= False; continue; } if (neighbor->seen && facet->seen && !qh_setin (neighbor->neighbors, facet)) { /* qh_MERGEridge */ merge= qh_appendmergeset (facet, neighbor, NULL); merge->mergeridge= True; } if ((int)neighbor->visitid == qh visit_id) continue; if (neighbor->flipped && facet->flipped) qh_appendmergeset (facet, neighbor, NULL); } } } FORALLfacet_(facetlist) { /* gets rid of qh_MERGEridge */ if (!facet->tested) qh_makeridges (facet); } FOREACHmerge_(qh facet_mergeset) { /* restore the missing neighbors */ if (merge->mergeridge) { qh_setappend (&merge->facet2->neighbors, merge->facet1); qh_makeridges (merge->facet1); /* and the missing ridges */ } } LABELrestart_merges: FOREACHmerge_(qh facet_mergeset) { /* do duplicates first */ if (!merge->mergeridge) continue; facet1= merge->facet1; facet2= merge->facet2; while (facet1->visible) facet1= (facetT *)SETfirst_(facet1->neighbors); while (facet2->visible) facet2= (facetT *)SETfirst_(facet2->neighbors); if (facet1 == facet2) continue; if (!qh_setin (facet2->neighbors, facet1)) qhull_fatal(60); if (qh TRACEmerge-1 == zzval_(Ztotmerge)) qhmem.IStracing= qh IStracing= qh TRACElevel; if (facet1->flipped || facet2->flipped) { zinc_(Zmergeflipdup); numflip++; trace0((qh ferr, "qh_forcedmerges: duplicate ridge with a flipped facet for f%d and f%d\n", facet1->id, facet2->id)); if (facet1->flipped) /* delay until qh_flippedmerges */ qh_mergefacet (facet2, facet1, NULL, NULL, NULL); else qh_mergefacet (facet1, facet2, NULL, NULL, NULL); zinc_(Zmergeflip); }else { dist1= qh_getdistance (facet1, facet2, &mindist1, &maxdist1); dist2= qh_getdistance (facet2, facet1, &mindist2, &maxdist2); trace0((qh ferr, "qh_forcedmerges: duplicate ridge between f%d and f%d, dist %2.2g and reverse dist %2.2g\n", facet1->id, facet2->id, dist1, dist2)); if (dist1 < dist2) qh_mergefacet (facet1, facet2, &mindist1, &maxdist1, NULL); else { dist1= dist2; qh_mergefacet (facet2, facet1, &mindist2, &maxdist2, NULL); } nummerge++; if (qh PRINTstatistics) { zinc_(Zduplicate); wadd_(Wduplicatetot, dist1); wmax_(Wduplicatemax, dist1); } } goto LABELrestart_merges; /* facet_mergeset may have changed */ } while ((merge= (mergeT *)qh_setdellast (qh facet_mergeset))) { if (merge->newmerge) break; facet1= merge->facet1; facet2= merge->facet2; if (merge->mergeridge || facet1->visible || facet2->visible) qh_memfree (merge, sizeof(mergeT)); else if (facet1 == facet2 || !facet1->flipped || !facet2->flipped) { merge->newmerge= True; qh_setaddnth (&qh facet_mergeset, 0, merge); }else { if (qh TRACEmerge-1 == zzval_(Ztotmerge)) qhmem.IStracing= qh IStracing= qh TRACElevel; qh_memfree (merge, sizeof(mergeT)); zinc_(Zmergeflip); trace3((qh ferr, "qh_forcedmerges: merge flipped facets f%d and f%d\n", facet1->id, facet2->id)); qh_mergefacet (facet1, facet2, NULL, NULL, NULL); numflip++; } } trace1((qh ferr, "qh_forcedmerges: merged %d facets across duplicated ridges and %d flipped facets\n", nummerge, numflip)); } /* forcedmerges */ /*------------------------------------------------- -getdistance- returns the max and min distance of any vertex from neighbor returns the max absolute value */ realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) { vertexT *vertex, **vertexp; realT dist; FOREACHvertex_(facet->vertices) vertex->seen= False; FOREACHvertex_(neighbor->vertices) vertex->seen= True; *mindist= 0.0; *maxdist= 0.0; FOREACHvertex_(facet->vertices) { if (!vertex->seen) { zzinc_(Zbestdist); qh_distplane(vertex->point, neighbor, &dist); if (dist > *maxdist) *maxdist= dist; else if (dist < *mindist) *mindist= dist; } } return fmax_(*maxdist, -(*mindist)); } /* getdistance */ /*------------------------------------------------- -getmergeset- returns facet_mergeset of facet-neighbor pairs to be merged only tests !tested ridges of !tested facets returns: sorted mergeset all ridges tested notes: uses ridge->tested to prevent duplicate tests resets ridge->tested if !facet->center can not limit tests to modified ridges since the centrum changed */ void qh_getmergeset(facetT *facetlist) { facetT *facet, *neighbor, **neighborp; ridgeT *ridge, **ridgep; int nummerges; nummerges= qh_setsize (qh facet_mergeset); trace2((qh ferr, "qh_getmergeset: started.\n")); FORALLfacet_(facetlist) { if (!facet->center) { facet->tested= False; FOREACHridge_(facet->ridges) ridge->tested= False; } if (facet->tested) continue; facet->tested= True; /* must be non-simplicial */ FOREACHneighbor_(facet) neighbor->seen= False; FOREACHridge_(facet->ridges) { if (ridge->tested && !ridge->nonconvex) continue; ridge->tested= True; ridge->nonconvex= False; neighbor= otherfacet_(ridge, facet); if (!neighbor->seen) { neighbor->seen= True; if (qh_test_appendmerge (facet, neighbor)) ridge->nonconvex= True; } } } nummerges= qh_setsize (qh facet_mergeset); qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle); trace2((qh ferr, "qh_getmergeset: %d merges found\n", nummerges)); } /* getmergeset */ /*------------------------------------------------ -getmergeset_initial- initial mergeset for facets tests all facet/neighbor pairs on facetlist uses visit_id facet_mergeset may have degen/redundant from flipped and forced merges returns: sorted mergeset sets facet->tested and ridge->tested */ void qh_getmergeset_initial (facetT *facetlist) { facetT *facet, *neighbor, **neighborp; ridgeT *ridge, **ridgep; int nummerges; qh visit_id++; FORALLfacet_(facetlist) { facet->visitid= qh visit_id; facet->tested= True; FOREACHneighbor_(facet) { if ((int)neighbor->visitid != qh visit_id) { if (qh_test_appendmerge (facet, neighbor)) { if (!neighbor->simplicial) { FOREACHridge_(neighbor->ridges) { if (facet == otherfacet_(ridge, neighbor)) { ridge->nonconvex= True; break; } } } } } } FOREACHridge_(facet->ridges) ridge->tested= True; } nummerges= qh_setsize (qh facet_mergeset); qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle); trace2((qh ferr, "qh_getmergeset_initial: %d merges found\n", nummerges)); } /* getmergeset_initial */ /*----------------------------------------- -hashridge- add ridge to hashtable without oldvertex assumes hashtable is large enough */ void qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) { unsigned hash; ridgeT *ridgeA; hash= qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex); while (True) { if (!(ridgeA= (ridgeT *)SETelem_(hashtable, hash))) { SETelem_(hashtable, hash)= ridge; break; }else if (ridgeA == ridge) break; if ((int)(++hash) == hashsize) hash= 0; } } /* hashridge */ /*----------------------------------------- -hashridge_find- returns matching ridge in hashtable without oldvertex assumes hashtable is large enough can't match ridge to itself if oldvertex is NULL matches with one skip returns: returns matching ridge; if no match, hashslot= -1 if ridge already in table else next NULL index */ ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *vertex, vertexT *oldvertex, int *hashslot) { unsigned hash; ridgeT *ridgeA; *hashslot= 0; zinc_(Zhashridge); hash= qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, vertex); while ((ridgeA= (ridgeT *)SETelem_(hashtable, hash))) { if (ridgeA == ridge) *hashslot= -1; else { zinc_(Zhashridgetest); if (qh_setequal_except (ridge->vertices, vertex, ridgeA->vertices, oldvertex)) return ridgeA; } if ((int)(++hash) == hashsize) hash= 0; } if (!*hashslot) *hashslot= hash; return NULL; } /* hashridge_find */ /*------------------------------------------------- -makeridges- creates explicit ridges between simplicial facets allows qh_MERGEridge flag uses existing ridges returns: facet with ridges and without qh_MERGEridge */ void qh_makeridges(facetT *facet) { facetT *neighbor, **neighborp; ridgeT *ridge, **ridgep; int neighbor_i, neighbor_n; boolT toporient=False, mergeridge= False; if (!facet->simplicial) return; trace4((qh ferr, "qh_makeridges: make ridges for f%d\n", facet->id)); facet->simplicial= False; FOREACHneighbor_(facet) { if (neighbor == qh_MERGEridge) mergeridge= True; else neighbor->seen= False; } FOREACHridge_(facet->ridges) otherfacet_(ridge, facet)->seen= True; FOREACHneighbor_i_(facet) { if (neighbor == qh_MERGEridge) { FOREACHridge_(facet->ridges) { if (!qh_setin (facet->neighbors, otherfacet_(ridge, facet))) ridge->mergeridge= True; } }else if (!neighbor->seen) { ridge= qh_newridge(); if (!neighbor->simplicial) /* only in forced merges, checkfacet */ ridge->mergeridge= True; ridge->vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim, neighbor_i, 0); toporient= (boolT)( facet->toporient ^ (neighbor_i & 0x1) ); if (toporient) { ridge->top= facet; ridge->bottom= neighbor; }else { ridge->top= neighbor; ridge->bottom= facet; } #if 0 /* this also works */ flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1); if (facet->toporient ^ (skip1 & 0x1) ^ flip) { ridge->top= neighbor; ridge->bottom= facet; }else { ridge->top= facet; ridge->bottom= neighbor; } #endif qh_setappend(&(facet->ridges), ridge); qh_setappend(&(neighbor->ridges), ridge); } } if (mergeridge) { while (qh_setdel (facet->neighbors, qh_MERGEridge)) ; /* delete each one */ } } /* makeridges */ /*------------------------------------------- -maydropneighbor -- drop neighbor relationship if no ridge between facet and neighbor bumps qh visit_id returns: appends degenerate facets to facet_mergeset won't cause redundant facets since vertex inclusion is the same may drop vertex and neighbor if no ridge */ void qh_maydropneighbor (facetT *facet) { ridgeT *ridge, **ridgep; realT angledegen= qh_ANGLEdegen; facetT *neighbor, **neighborp; qh visit_id++; trace4((qh ferr, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n", facet->id)); FOREACHridge_(facet->ridges) { ridge->top->visitid= qh visit_id; ridge->bottom->visitid= qh visit_id; } FOREACHneighbor_(facet) { if ((int)neighbor->visitid != qh visit_id) { trace0((qh ferr, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors\n", facet->id, neighbor->id)); zinc_(Zdropneighbor); qh_setdel (facet->neighbors, neighbor); neighborp--; /* repeat, deleted a neighbor */ qh_setdel (neighbor->neighbors, facet); if (qh_setsize (neighbor->neighbors) < qh hull_dim) { zinc_(Zdropdegen); qh_appendmergeset (neighbor, neighbor, &angledegen); trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id)); } } } if (qh_setsize (facet->neighbors) < qh hull_dim) { zinc_(Zdropdegen); qh_appendmergeset (facet, facet, &angledegen); trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", facet->id)); } } /* maydropneighbor */ /*--------------------------------------- -merge_degenredundant- merge degenerate and redundant facets if facet1 undefined, tests last merge on facet_mergeset and sets angle returns: True if merge performed or degen merge not needed notes: need this since renaming vertices can result in degen/redundant facets any merge can also result in degen/redundant facets */ boolT qh_merge_degenredundant (facetT *facet1, facetT *facet2, realT *angle) { int numnewmerges= 0, size; mergeT *merge; facetT *bestneighbor; realT dist, mindist, maxdist; vertexT *vertex, **vertexp; if (qh TRACEmerge-1 == zzval_(Ztotmerge)) qhmem.IStracing= qh IStracing= qh TRACElevel; while (!facet1 && (merge= (mergeT *)qh_setlast (qh facet_mergeset)) && merge->angle >= qh_ANGLEdegen) { merge= (mergeT *)qh_setdellast (qh facet_mergeset); facet1= merge->facet1; facet2= merge->facet2; *angle= merge->angle; qh_memfree (merge, sizeof(mergeT)); if (facet1->visible || facet2->visible) facet1= NULL; } if (!facet1) return False; if (*angle == qh_ANGLEredundant) { trace2((qh ferr, "qh_merge_degenredundant: facet f%d is contained in f%d, will merge\n", facet1->id, facet2->id)); qh_mergefacet(facet1, facet2, NULL, NULL, angle); qh_newmerge_(facet2); zinc_(Zneighbor); }else if (*angle == qh_ANGLEdegen) { /* other merges may have fixed */ if (!(size= qh_setsize (facet1->neighbors))) { trace2((qh ferr, "qh_merge_degenredundant: facet f%d has no neighbors. Deleted\n", facet1->id)); zinc_(Zdelfacetdup); qh_removefacet(facet1); qh_prependfacet (facet1, &qh visible_list); qh num_visible++; facet1->visible= True; /* SETfirst_(facet1->neighbors) == NULL */ FOREACHvertex_(facet1->vertices) { qh_setdel (vertex->neighbors, facet1); if (!SETfirst_(vertex->neighbors)) { zinc_(Zdegenvertex); trace2((qh ferr, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n", vertex->id, facet1->id)); vertex->deleted= True; qh_setappend (&qh del_vertices, vertex); } } numnewmerges++; /* needed since cleared this merge */ }else if (size < qh hull_dim) { bestneighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist); trace2((qh ferr, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n", facet1->id, size, bestneighbor->id, dist)); qh_mergefacet(facet1, bestneighbor, &mindist, &maxdist, angle); qh_newmerge_(bestneighbor); if (qh PRINTstatistics) { zinc_(Zdegen); wadd_(Wdegentot, dist); wmax_(Wdegenmax, dist); } }else numnewmerges++; /* needed since cleared this merge */ } return (boolT)numnewmerges; } /* merge_degenredundant */ /*------------------------------------------------- -merge_nonconvex- merges all nonconvex facets assumes qh_vertexneighbors() already called need to use qh newfacet_list since merge calls removefacet() returns: deleted facets added to visible_list notes: numdegenredun also counts degen facets that become ok */ void qh_merge_nonconvex (void /*qh newfacet_list*/) { facetT *bestfacet, *neighbor, *facet1, *facet2; facetT *bestneighbor; mergeT *merge; realT dist, dist2, mindist, mindist2, maxdist, maxdist2, angle; boolT wasmerge= True, ismodified=False, anglecoplanar = False; void **freelistp; vertexT *vertex; int nummerge=0, numconcave=0, numdegenredun= 0, numnewmerges= 0; trace2((qh ferr, "qh_merge_nonconvex: starting to merge facets beginning from f%d\n", getid_(qh newfacet_list))); if (qh IStracing >= 4 && qh num_facets < 50) qh_printlists(); qh facet_mergeset= qh_settemp (qh TEMPsize); qh_forcedmerges (qh newfacet_list); /* also sets tested */ qh_flippedmerges (qh newfacet_list); qh NEWmerges= True; if (qh POSTmerging) qh_tracemerging ("after flipped merges"); qh_getmergeset_initial (qh newfacet_list); /* facet_mergeset */ while (wasmerge) { wasmerge= False; while (qh_setsize (qh facet_mergeset)) { while ((merge= (mergeT *)qh_setdellast(qh facet_mergeset))) { facet1= merge->facet1; facet2= merge->facet2; angle= merge->angle; anglecoplanar= (boolT)merge->anglecoplanar; qh_memfree_(merge, sizeof(mergeT), freelistp); if ((facet1->id >= qh newfacet_id && !facet1->tested) || (facet2->id >= qh newfacet_id && !facet2->tested)) ismodified= True; else ismodified= False; if (facet1->visible || facet2->visible) /*deleted facet*/ continue; if (ismodified && angle < qh_ANGLEconcave) continue; if (qh TRACEmerge-1 == zzval_(Ztotmerge)) qhmem.IStracing= qh IStracing= qh TRACElevel; trace4((qh ferr, "qh_merge_nonconvex: merge #%d for f%d and f%d angle %2.2g modified? %d\n", zzval_(Ztotmerge)+1, facet1->id, facet2->id, angle, ismodified)); if (qh_merge_degenredundant (facet1, facet2, &angle)) { numdegenredun++; wasmerge= True; continue; }else { /* ANGLEconcave or coplanar */ if (facet1->id < qh newfacet_id) { bestfacet= facet2; /* avoid merging old facet if new is ok */ facet2= facet1; facet1= bestfacet; }else bestfacet= facet1; bestneighbor= qh_findbestneighbor(bestfacet, &dist, &mindist, &maxdist); neighbor= qh_findbestneighbor(facet2, &dist2, &mindist2, &maxdist2); wasmerge= True; if (dist < dist2) { qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, &angle); qh_newmerge_(bestneighbor); }else if (facet2->id < qh newfacet_id && ((mindist >= qh min_vertex && maxdist <= qh max_outside) || dist * 1.5 < dist2)) { zinc_(Zavoidold); wadd_(Wavoidoldtot, dist); wmax_(Wavoidoldmax, dist); trace2((qh ferr, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g. Use f%d dist %2.2g insted\n", facet2->id, dist2, facet1->id, dist2)); qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, &angle); qh_newmerge_(bestneighbor); }else { qh_mergefacet(facet2, neighbor, &mindist2, &maxdist2, &angle); qh_newmerge_(neighbor); dist= dist2; } if (qh PRINTstatistics) { if (anglecoplanar) { nummerge++; zinc_(Zacoplanar); wadd_(Wacoplanartot, dist); wmax_(Wacoplanarmax, dist); }else if (angle > qh_ANGLEconcave) { numconcave++; zinc_(Zconcave); wadd_(Wconcavetot, dist); wmax_(Wconcavemax, dist); }else { nummerge++; zinc_(Zcoplanar); wadd_(Wcoplanartot, dist); wmax_(Wcoplanarmax, dist); } }else if (angle > qh_ANGLEconcave) numconcave++; else nummerge++; } /* reducing vertices here in 5-d, 50% more time, maybe fewer vertices, and better bounds */ } /* while setdellast */ if (qh POSTmerging) qh_tracemerging ("after a merge set"); if (numnewmerges > qh_MAXnewmerges) { /* needed for large post merges */ numnewmerges= 0; qh_reducevertices_centrums(); } qh_getmergeset (qh newfacet_list); /* facet_mergeset */ } /* while mergeset */ if (wasmerge || (qh hull_dim >=4 && qh POSTmerging)) { if (qh hull_dim >=4 && qh POSTmerging) { /*duplicate ridges may changed*/ FORALLvertices vertex->delridge= True; } if (qh_reducevertices_centrums()) qh_getmergeset (qh newfacet_list); /* facet_mergeset */ else wasmerge= False; } } /* while (wasmerge) */ qh NEWmerges= False; if (qh CHECKfrequently) qh_checkconvex (qh newfacet_list, qh_ALGORITHMfault); qh_settempfree(&qh facet_mergeset); trace1((qh ferr, "qh_merge_nonconvex: merged %d coplanar facets %d concave facets and %d degen or redundant facets.\n", nummerge, numconcave, numdegenredun)); if (qh IStracing >= 4 && qh num_facets < 50) qh_printlists (); } /* merge_nonconvex */ /*------------------------------------------------- -mergefacet- merges facet1 into facet2 traces merge if fmax_(maxdist,-mindist) > TRACEdist mindist/maxdist and angle may be NULL max_outside and min_vertex updated returns: facet1 prepended to visible_list for later deletion and partitioning qh num_visible updated. SETfirst_(facet1->neighbors) == facet2 facet2 moved to end of qh facet_list facet2 is new (get's facet1->id if it was old) adds neighboring facets to facet_mergeset if redundant or degenerate clears facet->tested and ridge->tested ffrom facet1 */ void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, realT *angle) { boolT traceonce= False, waserror= False; vertexT *vertex, **vertexp; ridgeT *ridge, **ridgep; int tracerestore=0; zzinc_(Ztotmerge); if ((mindist && (-*mindist > qh TRACEdist || *maxdist > qh TRACEdist)) || facet1 == qh tracefacet || facet2 == qh tracefacet) { if (facet1 == qh tracefacet || facet2 == qh tracefacet) { tracerestore= qh IStracing; qh IStracing= 4; fprintf (qh ferr, "qh_mergefacet: ========= trace merge %d involving f%d, furthest is p%d\n", zzval_(Ztotmerge), qh tracefacet_id, qh furthest_id); }else { tracerestore= 0; qh IStracing= qh TRACElevel; fprintf (qh ferr, "qh_mergefacet: ========= trace wide merge %d (%2.2g) for f%d into f%d, last point was p%d\n", zzval_(Ztotmerge), fmax_(-*mindist, *maxdist), facet1->id, facet2->id, qh furthest_id); } traceonce= True; } if (qh IStracing >= 2) { realT mergemin= -2; realT mergemax= -2; realT mergeangle= -2; if (mindist) { mergemin= *mindist; mergemax= *maxdist; } if (angle) mergeangle= *angle; fprintf (qh ferr, "qh_mergefacet: #%d merge f%d into f%d, mindist= %2.2g, maxdist= %2.2g, angle = %2.2g\n", zzval_(Ztotmerge), facet1->id, facet2->id, mergemin, mergemax, mergeangle); } if (facet1 == facet2 || facet1->visible || facet2->visible) qhull_fatal(61); if (qh num_facets -qh num_visible <= qh hull_dim + 1) qhull_fatal(62); if (mindist) { maximize_(qh max_outside, *maxdist); maximize_(qh max_vertex, *maxdist); #if qh_MAXoutside maximize_(facet2->maxoutside, *maxdist); #endif minimize_(qh min_vertex, *mindist); } qh_makeridges(facet1); qh_makeridges(facet2); /* if (qh IStracing >=4) qh_errprint ("MERGING", facet1, facet2, NULL, NULL); NO LONGER IN SERVICE */ if (facet2->center && qh hull_dim == 2) { /* only two vertices */ qh_memfree (facet2->center, qh center_size); facet2->center= NULL; } qh_mergeneighbors(facet1, facet2); FOREACHridge_(facet1->ridges) ridge->tested= False; qh_mergeridges(facet1, facet2); qh vertex_visit++; FOREACHvertex_(facet2->vertices) vertex->visitid= qh vertex_visit; if (qh hull_dim == 2) qh_mergevertices2d(facet1->vertices, facet2->vertices); else qh_mergevertices(facet1->vertices, &facet2->vertices); qh_mergevertex_neighbors(facet1, facet2); if (facet1->id < qh newfacet_id && facet2->id >= qh newfacet_id) { zinc_(Zmergehorizon); }else if (facet2->id >= qh newfacet_id) zinc_(Zmergenew); qh_removefacet(facet1); qh_prependfacet (facet1, &qh visible_list); qh num_visible++; facet1->visible= True; SETfirst_(facet1->neighbors)= facet2; qh_settruncate (facet1->neighbors, 1); qh_removefacet(facet2); /* append as a newfacet to end of qh facet_list */ qh_appendfacet(facet2); if (facet2->id < qh newfacet_id) { zinc_(Zmergeintohorizon); trace3((qh ferr, "qh_mergefacet: RENAME - f%d as new facet f%d\n", facet2->id, qh facet_id)); if (qh facet_id == (int)qh tracefacet_id) { qh tracefacet= facet2; fprintf (qh ferr, "qh_mergefacet: RENAME f%d as trace facet f%d. Current furthest is p%d\n", facet2->id, qh facet_id, qh furthest_id); } facet2->id= qh facet_id++; } qh_degen_redundant_neighbors (facet2); facet2->tested= False; /* if (qh IStracing >= 4) qh_errprint ("MERGED", facet2, NULL, NULL, NULL); NO LONGER IN SERVICE */ if (facet2 == qh tracefacet || (qh tracevertex && qh tracevertex->newlist)) { fprintf (qh ferr, "qh_mergefacets: trace facet and vertex after merge of f%d and f%d, furthest p%d\n", facet1->id, facet2->id, qh furthest_id); /* if (facet2 != qh tracefacet) qh_errprint ("TRACE", qh tracefacet, (qh tracevertex ? (facetT *)SETfirst_(qh tracevertex->neighbors):NULL), NULL, qh tracevertex); NO LONGER IN SERVICE */ } if (qh CHECKfrequently || qh IStracing >= 4) { /* can't check polygon here */ qh_checkfacet (facet2, True, &waserror); if (waserror) qhull_fatal(63); qh_checkridge_boundary (facet2); } if (qh tracevertex) { if (qh tracevertex->deleted) fprintf (qh ferr, "qh_mergefacet: trace vertex deleted at furthest p%d\n", qh furthest_id); else qh_checkvertex (qh tracevertex); } if (qh tracefacet) { qh_checkfacet (qh tracefacet, True, &waserror); if (waserror) qhull_fatal(64); } if (traceonce) { fprintf (qh ferr, "qh_mergefacet: end of wide tracing\n"); qh IStracing= tracerestore; } } /* mergefacet */ /*------------------------------------------------- -mergeneighbors- merges the neighbors of facet1 into facet2 */ void qh_mergeneighbors(facetT *facet1, facetT *facet2) { facetT *neighbor, **neighborp; trace4((qh ferr, "qh_mergeneighbors: merge neighbors of f%d and f%d\n", facet1->id, facet2->id)); qh visit_id++; FOREACHneighbor_(facet2) { neighbor->visitid= qh visit_id; } FOREACHneighbor_(facet1) { if ((int)neighbor->visitid == qh visit_id) { if (neighbor->simplicial) /* is degen, needs ridges */ qh_makeridges (neighbor); if (SETfirst_(neighbor->neighbors) != facet1) /*keep horizon->newfacet*/ qh_setdel (neighbor->neighbors, facet1); else { qh_setdel(neighbor->neighbors, facet2); qh_setreplace(neighbor->neighbors, facet1, facet2); } }else if (neighbor != facet2) { qh_setappend(&(facet2->neighbors), neighbor); qh_setreplace(neighbor->neighbors, facet1, facet2); } } qh_setdel(facet1->neighbors, facet2); /* here for makeridges */ qh_setdel(facet2->neighbors, facet1); } /* mergeneighbors */ /*------------------------------------------------- -mergeridges- merges the ridge set of facet1 into facet2 may delete all ridges for a vertex */ void qh_mergeridges(facetT *facet1, facetT *facet2) { ridgeT *ridge, **ridgep; vertexT *vertex, **vertexp; trace4((qh ferr, "qh_mergeridges: merge ridges of f%d and f%d\n", facet1->id, facet2->id)); FOREACHridge_(facet2->ridges) { if ((ridge->top == facet1) || (ridge->bottom == facet1)) { FOREACHvertex_(ridge->vertices) vertex->delridge= True; qh_delridge(ridge); ridgep--; /*repeat*/ } } FOREACHridge_(facet1->ridges) { if (ridge->top == facet1) ridge->top= facet2; else ridge->bottom= facet2; qh_setappend(&(facet2->ridges), ridge); } } /* mergeridges */ /*------------------------------------------------- -mergevertex_neighbors- merge the vertex neighbors of facet1 to facet2 deletes vertices if only one neighbor assumes neighbor sets are good */ void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2) { vertexT *vertex, **vertexp; trace4((qh ferr, "qh_mergevertex_neighbors: merge vertex neighbors of f%d and f%d\n", facet1->id, facet2->id)); if (qh tracevertex) { fprintf (qh ferr, "qh_mergevertex_neighbors: of f%d and f%d at furthest p%d f0= %p\n", facet1->id, facet2->id, qh furthest_id, qh tracevertex->neighbors->e[0]); /* qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex); NO LONGER IN SERVICE */ } FOREACHvertex_(facet1->vertices) { if ((int)vertex->visitid != qh vertex_visit) { qh_setreplace(vertex->neighbors, facet1, facet2); }else { qh_setdel(vertex->neighbors, facet1); if (!SETsecond_(vertex->neighbors)) { zinc_(Zmergevertex); trace2((qh ferr, "qh_mergevertex_neighbors: deleted v%d when merging f%d into f%d\n", vertex->id, facet1->id, facet2->id)); qh_setdelsorted (facet2->vertices, vertex); vertex->deleted= True; qh_setappend (&qh del_vertices, vertex); } } } /* if (qh tracevertex) qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex); NO LONGER IN SERVICE */ } /* mergevertex_neighbors */ /*------------------------------------------------- -mergevertices- merges the vertex set of facet1 into facet2 preserves vertex_visit for qh_mergevertex_neighbors updates qh newvertex_list */ void qh_mergevertices(setT *vertices1, setT **vertices2) { int newsize= qh_setsize(vertices1)+qh_setsize(*vertices2) - qh hull_dim + 1; setT *mergedvertices; vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT); mergedvertices= qh_settemp (newsize); FOREACHvertex_(vertices1) { if (!*vertex2 || vertex->id > (*vertex2)->id) qh_setappend (&mergedvertices, vertex); else { while (*vertex2 && (*vertex2)->id > vertex->id) qh_setappend (&mergedvertices, *vertex2++); if (!*vertex2 || (*vertex2)->id < vertex->id) qh_setappend (&mergedvertices, vertex); else qh_setappend (&mergedvertices, *vertex2++); } } while (*vertex2) qh_setappend (&mergedvertices, *vertex2++); FOREACHvertex_(mergedvertices) { if (!vertex->newlist) { vertex->newlist= True; qh_removevertex (vertex); qh_appendvertex (vertex); } } if (newsize < qh_setsize (mergedvertices)) qhull_fatal(65); qh_setfree(vertices2); *vertices2= mergedvertices; qh_settemppop (); } /* mergevertices */ /*------------------------------------------------- -mergevertices2d- merges vertices1 into vertices2 in 2-d case preserves vertex_visit for qh_mergevertex_neighbors */ void qh_mergevertices2d(setT *vertices1, setT *vertices2) { vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB; vertex1A= (vertexT *)SETfirst_(vertices1); vertex1B= (vertexT *)SETsecond_(vertices1); vertex2A= (vertexT *)SETfirst_(vertices2); vertex2B= (vertexT *)SETsecond_(vertices2); if (vertex1A == vertex2A) { vertexA= vertex1B; vertexB= vertex2B; }else if (vertex1A == vertex2B) { vertexA= vertex1B; vertexB= vertex2A; }else if (vertex1B == vertex2A) { vertexA= vertex1A; vertexB= vertex2B; }else { /* 1B == 2B */ vertexA= vertex1A; vertexB= vertex2A; } if (vertexA->id > vertexB->id) { SETfirst_(vertices2)= vertexA; SETsecond_(vertices2)= vertexB; }else { SETfirst_(vertices2)= vertexB; SETsecond_(vertices2)= vertexA; } } /* mergevertices2d */ /*------------------------------------------------- -neighbor_intersections- return intersection for vertex->neighbors returns temporary set of vertices does not include vertex NULL if an neighbor is simplicial NULL if empty set */ setT *qh_neighbor_intersections (vertexT *vertex) { facetT *neighbor, **neighborp, *neighborA, *neighborB; setT *intersect; int neighbor_i, neighbor_n; FOREACHneighbor_(vertex) { if (neighbor->simplicial) return NULL; } neighborA= (facetT *)SETfirst_(vertex->neighbors); neighborB= (facetT *)SETsecond_(vertex->neighbors); zinc_(Zintersectnum); if (!neighborA) return NULL; if (!neighborB) intersect= qh_setcopy (neighborA->vertices, 0); else intersect= qh_vertexintersect_new (neighborA->vertices, neighborB->vertices); qh_settemppush (intersect); qh_setdelsorted (intersect, vertex); FOREACHneighbor_i_(vertex) { if (neighbor_i >= 2) { zinc_(Zintersectnum); qh_vertexintersect (&intersect, neighbor->vertices); if (!SETfirst_(intersect)) { zinc_(Zintersectfail); qh_settempfree (&intersect); return NULL; } } } trace3((qh ferr, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n", qh_setsize (intersect), vertex->id)); return intersect; } /* neighbor_intersections */ /*------------------------------------------------- -reducevertices_centrums reduce vertex sets and reset centrums qh_isnewmerge_(facet) [i.e., flipped] true if merged since last call if 2-d, just clears newmerge flags returns: True if degen_redundant facets or redefined centrums vertices are renamed if possible centrum's reset for small (qh_MAXnewcentrum), newly merged or renamed facets */ boolT qh_reducevertices_centrums (void) { int numshare=0, numrename= 0, numcentrums= 0; int numdegenredun= 0; facetT *newfacet; vertexT *vertex, **vertexp; realT angle; ridgeT *ridge, **ridgep; if (qh hull_dim == 2) { FORALLnew_facets qh_clearnewmerge_(newfacet); return False; } LABELrestart: while (qh_merge_degenredundant (NULL, NULL, &angle)) numdegenredun++; FORALLnew_facets { if (qh_isnewmerge_(newfacet)) /* this is seldom needed */ qh_remove_extravertices (newfacet); } FORALLnew_facets { if (qh_isnewmerge_(newfacet)) { FOREACHvertex_(newfacet->vertices) { if (vertex->delridge) { if (qh_rename_sharedvertex (vertex, newfacet)) { numshare++; vertexp--; /* repeat since deleted vertex */ } } } } } FORALLvertex_(qh newvertex_list) { if (vertex->delridge && !vertex->deleted) { vertex->delridge= False; if (qh hull_dim >= 4 && qh_redundant_vertex (vertex)) { numrename++; if (qh_merge_degenredundant (NULL, NULL, &angle)) { numdegenredun++; goto LABELrestart; } } } } FORALLnew_facets { if (qh_isnewmerge_(newfacet)) { qh_clearnewmerge_(newfacet); if (newfacet->center && qh_setsize (newfacet->vertices) <= qh hull_dim + qh_MAXnewcentrum) { qh_memfree (newfacet->center, qh center_size); newfacet->center= NULL; newfacet->tested= False; FOREACHridge_(newfacet->ridges) ridge->tested= False; numcentrums++; } } } trace1((qh ferr, "qh_reducevertices_centrums: renamed %d shared vertices and %d redundant\nvertices. Redefined %d centrums and merged %d degen, redundant facets\n", numshare, numrename, numcentrums, numdegenredun)); if (numdegenredun + numcentrums) return True; return False; } /* reducevertices_centrums */ /*------------------------------------------------- -redundant_vertex- returns true if detect and rename redundant vertex vertices have full ->neighbors only needed if vertex->delridge and hull_dim >= 4 returns: may add degen facets to facet_mergeset doesn't change vertex->neighbors or create redundant facets */ vertexT *qh_redundant_vertex (vertexT *vertex) { vertexT *newvertex= NULL; setT *vertices, *ridges; trace3((qh ferr, "qh_redundant_vertex: check if v%d can be renamed\n", vertex->id)); if ((vertices= qh_neighbor_intersections (vertex))) { ridges= qh_vertexridges (vertex); if ((newvertex= qh_find_newvertex (vertex, vertices, ridges))) qh_renamevertex (vertex, newvertex, ridges, NULL, NULL); qh_settempfree (&ridges); qh_settempfree (&vertices); } return newvertex; } /* redundant_vertex */ /*------------------------------------------------- -remove_extravertices in non-simplicial facets returns True if it finds them */ boolT qh_remove_extravertices (facetT *facet) { ridgeT *ridge, **ridgep; vertexT *vertex, **vertexp, *vertexA, **vertexAp; boolT foundrem= False; trace4((qh ferr, "qh_remove_extravertices: test f%d for extra vertices\n", facet->id)); FOREACHvertex_(facet->vertices) vertex->seen= False; FOREACHridge_(facet->ridges) { FOREACHvertexA_(ridge->vertices) vertexA->seen= True; } FOREACHvertex_(facet->vertices) { if (!vertex->seen) { foundrem= True; zinc_(Zremvertex); qh_setdelsorted (facet->vertices, vertex); qh_setdel (vertex->neighbors, facet); if (!qh_setsize (vertex->neighbors)) { vertex->deleted= True; qh_setappend (&qh del_vertices, vertex); zinc_(Zremvertexdel); trace2((qh ferr, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id)); }else trace3((qh ferr, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id)); vertexp--; /*repeat*/ } } return foundrem; } /* remove_extravertices */ /*------------------------------------------------- -rename_sharedvertex- detect and rename if shared vertex in facet vertices have full ->neighbors returns: newvertex or NULL the vertex may still exist in other facets (i.e., a neighbor was pinched) does not change facet->neighbors, updates vertex->neighbors notes: a shared vertex for a facet is only in ridges to one neighbor this may undo a pinched facet it does not catch pinches involving multiple facets. These appear to be difficult to detect, since an exhaustive search is too expensive. */ vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet) { facetT *neighbor, **neighborp, *neighborA= NULL; setT *vertices, *ridges; vertexT *newvertex; if (qh_setsize (vertex->neighbors) == 2) { neighborA= (facetT *)SETfirst_(vertex->neighbors); if (neighborA == facet) neighborA= (facetT *)SETsecond_(vertex->neighbors); }else if (qh hull_dim == 3) return NULL; else { qh visit_id++; FOREACHneighbor_(facet) neighbor->visitid= qh visit_id; FOREACHneighbor_(vertex) { if ((int)neighbor->visitid == qh visit_id) { if (neighborA) return NULL; neighborA= neighbor; } } if (!neighborA) qhull_fatal(66); } /* the vertex is shared by facet and neighborA */ ridges= qh_settemp (qh TEMPsize); neighborA->visitid= ++qh visit_id; qh_vertexridges_facet (vertex, facet, &ridges); trace2((qh ferr, "qh_rename_sharedvertex: p%d (v%d) is shared by f%d (%d ridges) and f%d\n", qh_pointid(vertex->point), vertex->id, facet->id, qh_setsize (ridges), neighborA->id)); zinc_(Zintersectnum); vertices= qh_vertexintersect_new (facet->vertices, neighborA->vertices); qh_setdel (vertices, vertex); qh_settemppush (vertices); if ((newvertex= qh_find_newvertex (vertex, vertices, ridges))) qh_renamevertex (vertex, newvertex, ridges, facet, neighborA); qh_settempfree (&vertices); qh_settempfree (&ridges); return newvertex; } /* rename_sharedvertex */ /*------------------------------------------------- -renameridgevertex- renames oldvertex as newvertex in ridge */ void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) { int nth= 0, oldnth; facetT *temp; vertexT *vertex, **vertexp; oldnth= qh_setindex (ridge->vertices, oldvertex); qh_setdelnthsorted (ridge->vertices, oldnth); FOREACHvertex_(ridge->vertices) { if (vertex == newvertex) { zinc_(Zdelridge); if (ridge->tested && ridge->nonconvex) qh_copynonconvex (ridge); qh_delridge (ridge); trace2((qh ferr, "qh_renameridgevertex: ridge r%d deleted. It contained both v%d and v%d\n", ridge->id, oldvertex->id, newvertex->id)); return; } if (vertex->id < newvertex->id) break; nth++; } qh_setaddnth(&ridge->vertices, nth, newvertex); if (abs(oldnth - nth)%2) { trace3((qh ferr, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n", ridge->id)); temp= ridge->top; ridge->top= ridge->bottom; ridge->bottom= temp; } } /* renameridgevertex */ /*------------------------------------------------- -renamevertex- renames oldvertex as newvertex in ridges oldvertex may still exist afterwards gives oldfacet/neighborA if shared between facets notes: can not change neighbors of newvertex (since it's a subset) */ void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) { facetT *neighbor, **neighborp; ridgeT *ridge, **ridgep; boolT istrace= False; if (qh IStracing >= 2 || oldvertex->id == qh tracevertex_id || newvertex->id == qh tracevertex_id) istrace= True; FOREACHridge_(ridges) qh_renameridgevertex (ridge, oldvertex, newvertex); if (qh CHECKfrequently) { FOREACHneighbor_(oldvertex) { qh_checkridge_boundary (neighbor); } } if (!oldfacet) { zinc_(Zrenameall); if (istrace) fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in several facets\n", oldvertex->id, newvertex->id); FOREACHneighbor_(oldvertex) { qh_maydropneighbor (neighbor); qh_setdelsorted (neighbor->vertices, oldvertex); if (qh_remove_extravertices (neighbor)) neighborp--; /* neighbor may be deleted */ } if (!oldvertex->deleted) { oldvertex->deleted= True; qh_setappend (&qh del_vertices, oldvertex); } }else if (qh_setsize (oldvertex->neighbors) == 2) { zinc_(Zrenameshare); if (istrace) fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in oldfacet f%d\n", oldvertex->id, newvertex->id, oldfacet->id); FOREACHneighbor_(oldvertex) qh_setdelsorted (neighbor->vertices, oldvertex); oldvertex->deleted= True; qh_setappend (&qh del_vertices, oldvertex); }else { zinc_(Zrenamepinch); if (istrace || qh IStracing) fprintf (qh ferr, "qh_renamevertex: renamed pinched v%d to v%d between f%d and f%d\n", oldvertex->id, newvertex->id, oldfacet->id, neighborA->id); qh_setdelsorted (oldfacet->vertices, oldvertex); qh_setdel (oldvertex->neighbors, oldfacet); qh_remove_extravertices (neighborA); } } /* renamevertex */ /*----------------------------------------- -test_appendmerge- tests facet/neighbor and appends to mergeset if nonconvex sets facet->center as needed returns: true if appends to mergeset sets 'acoplanar' if angle coplanar */ boolT qh_test_appendmerge (facetT *facet, facetT *neighbor) { realT dist, dist2= -REALmax, angle; boolT isconcave= False, iscoplanar= False; mergeT *merge; angle= qh_getangle(facet->normal, neighbor->normal); zinc_(Zangletests); if (angle > qh cos_max) { zinc_(Zcoplanarangle); merge= qh_appendmergeset(facet, neighbor, &angle); merge->anglecoplanar= True; trace2((qh ferr, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n", angle, facet->id, neighbor->id)); return True; }else { if (!facet->center) facet->center= qh_getcentrum (facet); zzinc_(Zcentrumtests); qh_distplane(facet->center, neighbor, &dist); if (dist > qh centrum_radius) isconcave= True; else { if (dist > -qh centrum_radius) iscoplanar= True; if (!neighbor->center) neighbor->center= qh_getcentrum (neighbor); zinc_(Zcentrumtests); qh_distplane(neighbor->center, facet, &dist2); if (dist2 > qh centrum_radius) isconcave= True; else if (dist2 > -qh centrum_radius) iscoplanar= True; } if (isconcave) { zinc_(Zconcaveridge); angle += qh_ANGLEconcave + 0.5; qh_appendmergeset(facet, neighbor, &angle); trace0((qh ferr, "qh_test_appendmerge: concave f%d to f%d dist %4.4g and reverse dist %4.4g angle %4.4g\n", facet->id, neighbor->id, dist, dist2, angle)); return True; }else if (iscoplanar) { zinc_(Zcoplanarcentrum); qh_appendmergeset(facet, neighbor, &angle); trace2((qh ferr, "qh_test_appendmerge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n", facet->id, neighbor->id, dist, dist2, angle)); return True; } } return False; } /* test_appendmerge */ /*------------------------------------------ -tracemerging- print trace message if active */ void qh_tracemerging (char *string) { realT cpu; time_t timedata; struct tm *tp; if (qh REPORTfreq && (zzval_(Ztotmerge) > qh mergereport+qh REPORTfreq/2)) { qh mergereport= zzval_(Ztotmerge); time (&timedata); tp= localtime (&timedata); cpu= clock(); cpu /= qh_SECticks; zinc_(Zdistio); fprintf (qh ferr, "\n\ At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets. The hull\n\ contains %d facets and %d vertices. p%d was the last point.\n", tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, zzval_(Ztotmerge), qh num_facets - qh num_visible, qh num_vertices-qh_setsize (qh del_vertices), qh furthest_id); } } /* tracemerging */ /*------------------------------------------ -vertexridges- return temporary set of ridges adjacent to a vertex vertex->neighbors defined uses qh visit_id does not include implicit ridges for simplicial facets */ setT *qh_vertexridges (vertexT *vertex) { facetT *neighbor, **neighborp; setT *ridges= qh_settemp (qh TEMPsize); int size; qh visit_id++; FOREACHneighbor_(vertex) neighbor->visitid= qh visit_id; FOREACHneighbor_(vertex) { if (*neighborp) /* no new ridges in last neighbor */ qh_vertexridges_facet (vertex, neighbor, &ridges); } if (qh PRINTstatistics || qh IStracing) { size= qh_setsize (ridges); zinc_(Zvertexridge); zadd_(Zvertexridgetot, size); zmax_(Zvertexridgemax, size); trace3((qh ferr, "qh_vertexridges: found %d ridges for v%d\n", size, vertex->id)); } return ridges; } /* vertexridges */ /*------------------------------------------ -vertexridges_facet- add adjacent ridges for vertex in facet skips ridges if neighbor->visitid< visit_id returns: sets facet->visitid to visit_id-1 */ void qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges) { ridgeT *ridge, **ridgep; facetT *neighbor; FOREACHridge_(facet->ridges) { neighbor= otherfacet_(ridge, facet); if ((int)neighbor->visitid == qh visit_id && qh_setin (ridge->vertices, vertex)) qh_setappend (ridges, ridge); } facet->visitid= qh visit_id-1; } /* vertexridges_facet */ /*************************************************************************/ /****************** implementation code from global.c ********************/ /*************************************************************************/ /* global.c -- contains all the globals of the qhull application see README see qhull.h for qh globals and function prototypes see qhull_a.h for internal functions copyright (c) 1993-1994, The Geometry Center */ #if qh_QHpointer qhT *qh_qh= NULL; #else qhT qh_qh; /*= {0};*/ /* remove "= {0}" if this causes a compiler error. Also qh_qhstat in stat.c and qhmem in mem.c. */ #endif /* ------------Simple all purpose error report-------------*/ #ifdef GAMBIT_EXCEPTIONS ErrorInQhull::~ErrorInQhull() { } std::string ErrorInQhull::GetDescription(void) const { return "Error somewhere in Qhull"; } #endif void qhull_fatal(int errorno) { #ifdef GAMBIT_EXCEPTIONS throw ErrorInQhull(); #endif printf("\nError number %d in qhull.\n", errorno); exit(0); } /*------------------------------------------- -appendprint- append output format to qh PRINTout unless already defined */ void qh_appendprint (int format) { int i; for (i=0; i < qh_PRINTEND; i++) { if (qh PRINTout[i] == format) break; if (!qh PRINTout[i]) { qh PRINTout[i]= format; break; } } } /* appendprint */ /*------------------------------------------- -freebuffers- free up global memory buffers must match initbuffers() */ void qh_freebuffers (void) { trace5((qh ferr, "qh_freebuffers: freeing up global memory buffers\n")); qh_memfree (qh NEARzero, qh hull_dim * sizeof(realT)); qh_memfree (qh lower_threshold, (qh input_dim+1) * sizeof(realT)); qh_memfree (qh upper_threshold, (qh input_dim+1) * sizeof(realT)); qh_memfree (qh lower_bound, (qh input_dim+1) * sizeof(realT)); qh_memfree (qh upper_bound, (qh input_dim+1) * sizeof(realT)); qh_memfree (qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT)); qh_memfree (qh gm_row, (qh hull_dim+1) * sizeof(coordT *)); qh_setfree (&qh hash_table); qh_setfree (&qh other_points); qh_setfree (&qh del_vertices); /* qh facet_mergeset is a temp */ qh NEARzero= qh lower_threshold= qh upper_threshold= NULL; qh lower_bound= qh upper_bound= NULL; qh gm_matrix= NULL; qh gm_row= NULL; if (qh line) free (qh line); if (qh first_point && qh POINTSmalloc) free(qh first_point); trace5((qh ferr, "qh_freebuffers: finished\n")); } /* freebuffers */ /*------------------------------------------- -freeqhull- free global memory if allmem, frees all allocated data structures else, frees all long memory rest of memory freed by qh_memfreeshort(); */ void qh_freeqhull (boolT allmem) { facetT *facet; vertexT *vertex; ridgeT *ridge, **ridgep; mergeT *merge, **mergep; trace1((qh ferr, "qh_freeqhull: free global memory\n")); qh NOerrexit= True; /* no more setjmp */ if (allmem) { qh_clearcenters (qh_none); while ((vertex= qh vertex_list)) { if (vertex->next) qh_delvertex (vertex); else { qh_memfree (vertex, sizeof(vertexT)); qh vertex_list= NULL; } } }else if (qh VERTEXneighbors) { FORALLvertices qh_setfreelong (&(vertex->neighbors)); } if (allmem) { FORALLfacets { if (!facet->visible) { FOREACHridge_(facet->ridges) ridge->seen= False; } } FORALLfacets { FOREACHridge_(facet->ridges) ridge->seen ^= True; } while ((facet= qh facet_list)) { FOREACHridge_(facet->ridges) { if (ridge->seen) { qh_setfree(&(ridge->vertices)); qh_memfree(ridge, sizeof(ridgeT)); }else ridge->seen= True; } if (facet->next) qh_delfacet (facet); else { qh_memfree (facet, sizeof(facetT)); qh facet_list= NULL; } } }else { FORALLfacets { qh_setfreelong (&(facet->outsideset)); qh_setfreelong (&(facet->coplanarset)); if (!facet->simplicial) { qh_setfreelong (&(facet->neighbors)); qh_setfreelong (&(facet->ridges)); qh_setfreelong (&(facet->vertices)); } } } qh_setfree (&qh hash_table); FOREACHmerge_(qh facet_mergeset) /* usually empty */ qh_memfree (merge, sizeof(mergeT)); qh_freebuffers(); qh_freestatistics(); qh_settempfree_all(); #if qh_QHpointer free (qh_qh); qh_qh= NULL; #endif } /* freeqhull */ /*--------------------------------------------- -init_qhull_command- build qhull_command from argc/argv */ void qh_init_qhull_command(int argc, char *argv[]) { int i; strcpy (qh qhull_command, argv[0]); for (i=1; i 0) qh GOODpointp= qh_point (qh GOODpoint-1); else if (qh GOODpoint < 0) qh GOODpointp= qh_point (-qh GOODpoint-1); if (qh GOODvertex > 0) qh GOODvertexp= qh_point (qh GOODvertex-1); else if (qh GOODvertex < 0) qh GOODvertexp= qh_point (-qh GOODvertex-1); if ((qh GOODpointp && (qh GOODpointp < qh first_point || qh GOODpointp > qh_point (qh num_points-1))) || (qh GOODvertexp && (qh GOODvertexp < qh first_point || qh GOODvertexp > qh_point (qh num_points-1)))) qhull_fatal(69); if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) { qh TRACElevel= (qh IStracing? qh IStracing : 3); qh IStracing= 0; } if (qh ROTATErandom == 0 || qh ROTATErandom == -1) { seed= time (&timedata); qh ROTATErandom= seed; }else if (qh ROTATErandom > 0) seed= qh ROTATErandom; else seed= 1; qh_RANDOMseed_(seed); randr= 0.0; for (i= 1000; i--; ) { randi= qh_RANDOMint; randr += randi; /* DEBUG */ /* - I reset qh_RANDOMmax in qhull.h, but not intelligently. Expect more trouble inn the future. printf("qh_RANDOMmax is %d.\n", qh_RANDOMmax); printf("randi is %d.\n", randi); */ if (randi > qh_RANDOMmax) qhull_fatal(70); } if (randr/1000 < qh_RANDOMmax/10) fprintf (qh ferr, "qhull configuration warning (initqhull_globals): average of 1000 randoms %.2g much less than expected (%.2g). Is qh_RANDOMmax wrong?\n", randr/1000, (double) (qh_RANDOMmax/2)); qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax; qh RANDOMb= 1.0 - qh RANDOMfactor; #ifndef __BCC55__ // This condition is always false under BCC55 if (qh_HASHfactor < 1.1) qhull_fatal(71); #endif // __BCC55__ if (numpoints+extra < pointsneeded) qhull_fatal(72); for (i= qh_PRINTEND; i--; ) { if (qh PRINTout[i] == qh_PRINTmathematica) printmath= True; if (qh PRINTout[i] == qh_PRINTgeom) printgeom= True; else if (qh PRINTout[i]) printother= True; } if (printmath && qh hull_dim > 3) qhull_fatal(73); if (printgeom) { if (qh hull_dim > 4) qhull_fatal(74); if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) qhull_fatal(75); if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) qhull_fatal(76); if (qh hull_dim == 4 && qh DROPdim == -1 && (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) { fprintf (qh ferr, "qhull input warning: coplanars, vertices, and centrums output not\n\ available for 4-d output (ignored). Could use 'GDn' instead.\n"); qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False; } } qh PRINTdim= qh hull_dim; if (qh DROPdim >=0) { /* after Geomview checks */ if (qh DROPdim < qh hull_dim) { qh PRINTdim--; if (printother || qh hull_dim < 3) fprintf (qh ferr, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim); }else qh DROPdim= -1; }else if (qh VORONOI) { qh DROPdim= qh hull_dim-1; qh PRINTdim= qh hull_dim-1; } } /* initqhull_globals */ /*----------------------------------------------------- -initqhull_mem- initialize mem.c for qhull qh.hull_dim and normal_size determines some of the allocation sizes if qh MERGING, includes ridgeT returns: mem.c already for memalloc/memfree (errors if called beforehand) notes: the user can add up to 10 additional sizes for quick allocation (increase numsizes) */ void qh_initqhull_mem (void) { int numsizes; int i; numsizes= 7+10; qh_meminitbuffers (qh IStracing, qh_MEMalign, numsizes, qh_MEMbufsize,qh_MEMinitbuf); qh_memsize(sizeof(vertexT)); if (qh MERGING) qh_memsize(sizeof(ridgeT)); qh_memsize(sizeof(facetT)); qh_memsize(sizeof(hashentryT)); i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize; /* ridge.vertices */ qh_memsize(i); qh_memsize(qh normal_size); /* normal */ i += SETelemsize; /* facet.vertices, .ridges, .neighbors */ qh_memsize(i); /* qh_user_memsizes(); - THIS DID NOTHING */ qh_memsetup(); } /* initqhull_mem */ /*------------------------------------------- -initqhull_start -- start initialization of qhull inits statistics */ void qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile) { clock(); /* start the clock */ #if qh_QHpointer if (!(qh_qh= (qhT *)malloc (sizeof(qhT)))) { fprintf (errfile, "qhull error (initqhull_globals): insufficient memory\n"); exit (qh_ERRmem); /* no error handler */ } memset((char *)qh_qh, 0, sizeof(qhT)); /* every field is 0, FALSE, NULL */ #else memset((char *)&qh_qh, 0, sizeof(qhT)); #endif strcat (qh qhull, "qhull"); qh_initstatistics(); qh ferr= errfile; qh fin= infile; qh fout= outfile; qh lastreport= INT_MIN; qh mergereport= INT_MIN; qh max_outside= 0.0; qh maxmaxcoord= 0.0; qh max_vertex= 0.0; qh min_vertex= 0.0; qh MINdenom_1= fmax_(1.0/REALmax, REALmin); qh MINoutside= 0.0; qh MINvisible= REALmax; qh premerge_centrum= 0.0; qh premerge_cos= REALmax; qh PRINTprecision= True; qh PRINTradius= 0.0; qh postmerge_cos= REALmax; qh postmerge_centrum= 0.0; qh ROTATErandom= INT_MIN; qh DROPdim= -1; qh TRACEdist= REALmax; qh TRACEpoint= -1; qh tracefacet_id= (unsigned int) -1; /* stderr set these to id for tracefacet/tracevertex */ qh tracevertex_id= (unsigned int) -1; } /* initqhull_start */ /*--------------------------------------------- -initthresholds set thresholds for printing and scaling from command line see 'prompt' in unix.c for documentation see also initflags() sets qh GOODthreshold or qh SPLITthreshold if 'Pd0D1' used */ void qh_initthresholds(char *command) { realT value; int index, maxdim, k; char *s= command; char key; maxdim= qh input_dim; if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput)) maxdim++; while (*s) { if (*s == '-') s++; if (*s == 'P') { s++; while (*s && !isspace(key= *s++)) { if (key == 'd' || key == 'D') { if (!isdigit(*s)) { fprintf(qh ferr, "qhull warning: no dimension given for Print option %c. Ignored\n", key); continue; } index= qh_strtol (s, &s); if (index >= qh hull_dim) { fprintf(qh ferr, "qhull warning: dimension %d for Print option %c is >= %d. Ignored\n", index, key, qh hull_dim); continue; } if (*s == ':') { ++s; value= qh_strtod(s, &s); if (fabs((double)value) > 1.0) { fprintf(qh ferr, "qhull warning: value %2.4g for Print option %c is > +1 or < -1. Ignored\n", value, key); continue; } }else value= 0.0; if (key == 'd') qh lower_threshold[index]= value; else qh upper_threshold[index]= value; } } }else if (*s == 'Q') { s++; while (*s && !isspace(key= *s++)) { if (key == 'b' && *s == 'B') { s++; for (k=maxdim; k--; ) { qh lower_bound[k]= -qh_DEFAULTbox; qh upper_bound[k]= qh_DEFAULTbox; } }else if (key == 'b' || key == 'B') { if (!isdigit(*s)) { fprintf(qh ferr, "qhull warning: no dimension given for Qhull option %c. Ignored\n", key); continue; } index= qh_strtol (s, &s); if (index >= maxdim) { fprintf(qh ferr, "qhull warning: dimension %d for Qhull option %c is >= %d. Ignored\n", index, key, maxdim); continue; } if (*s == ':') { ++s; value= qh_strtod(s, &s); } else if (key == 'b') value= -qh_DEFAULTbox; else value= qh_DEFAULTbox; if (key == 'b') qh lower_bound[index]= value; else qh upper_bound[index]= value; } } }else { while (!isspace (*s)) s++; } while (isspace (*s)) s++; } for (k= qh hull_dim; k--; ) { if (qh lower_threshold[k] > -REALmax/2) { qh GOODthreshold= True; if (qh upper_threshold[k] < REALmax/2) { qh SPLITthresholds= True; qh GOODthreshold= False; break; } }else if (qh upper_threshold[k] < REALmax/2) qh GOODthreshold= True; } } /* initthresholds */ #if qh_QHpointer /*------------------------------------------ -restore_qhull- restores a previously saved qhull also restores qh_qhstat and qhmem.tempstack errors if current qhull hasn't been saved or freed uses qhmem for error reporting */ void qh_restore_qhull (qhT **oldqh) { if (*oldqh && strcmp ((*oldqh)->qhull, "qhull")) qhull_fatal(77); if (qh_qh) qhull_fatal(78); if (!*oldqh || !(*oldqh)->old_qhstat) qhull_fatal(79); qh_qh= *oldqh; *oldqh= NULL; qh_qhstat= qh old_qhstat; qhmem.tempstack= qh old_tempstack; trace1((qh ferr, "qh_restore_qhull: restored qhull from %x\n", (int) *oldqh)); } /* restore_qhull */ /*------------------------------------------ -save_qhull- saves qhull for a later qh_restore_qhull also saves qh_qhstat and qhmem.tempstack returns: qhull for a later restore_qhull qh_qh=NULL notes: need to initialize qhull or call qh_restore_qhull before continuing */ qhT *qh_save_qhull (void) { qhT *oldqh; if (!qh_qh) qhull_fatal(80); qh old_qhstat= qh_qhstat; qh_qhstat= NULL; qh old_tempstack= qhmem.tempstack; qhmem.tempstack= NULL; oldqh= qh_qh; qh_qh= NULL; trace1((qhmem.ferr, "qh_save_qhull: saved qhull %x\n", (int) oldqh)); return oldqh; } /* save_qhull */ #endif /*----------------------------------------- -strtol/tod -- internal versions that don't skip trailing spaces */ double qh_strtod (const char *s, char **endp) { double result; result= strtod (s, endp); if (s < (*endp) && (*endp)[-1] == ' ') (*endp)--; return result; } /* strtod */ int qh_strtol (const char *s, char **endp) { int result; result= (int) strtol (s, endp, 10); if (s< (*endp) && (*endp)[-1] == ' ') (*endp)--; return result; } /* strtol */ /*************************************************************************/ /****************** implementation code from qhull.c *********************/ /*************************************************************************/ /* qhull - Quickhull algorithm for convex hulls qhull() and top-level routines see README, qhull.h, unix.c and mac.c see qhull_a.h for internal functions copyright (c) 1993-1994 The Geometry Center */ /*------------------------------------------------- -qhull- hull_dim convex hull of num_points starting at first_point returns: returns facet_list, numfacets, etc. */ void qh_qhull (void) { setT *maxpoints, *vertices; facetT *facet; int numpart, numoutside, i; vertexT *vertex; realT dist; boolT isoutside; qh hulltime= clock(); if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2 && qh lower_threshold[qh hull_dim-1] < -REALmax/2) { for (i= qh_PRINTEND; i--; ) { if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0 && !qh GOODthreshold && !qh SPLITthresholds) break; /* in this case, don't set upper_threshold */ } if (i < 0) { qh upper_threshold[qh hull_dim-1]= 0.0; if (!qh GOODthreshold) qh SPLITthresholds= True; } } maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim); /* qh_maxmin sets DISTround and other precision constants */ vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points); qh_initialhull (vertices); /* initial qh facet_list */ qh_partitionall (vertices, qh first_point, qh num_points); if (qh PREmerge) { qh cos_max= qh premerge_cos; qh centrum_radius= qh premerge_centrum; } if (qh ONLYgood) { if (!(qh GOODthreshold || qh GOODpoint || (qh GOODvertex > 0 && !qh MERGING))) qhull_fatal(81); if (qh GOODvertex > 0 && !qh MERGING /* matches qh_partitionall */ && !qh_isvertex (qh GOODvertexp, vertices)) { facet= qh_findbest (qh GOODvertexp, qh facet_list, False, 0, &dist, &isoutside, &numpart); zadd_(Zdistgood, numpart); if (!isoutside) qhull_fatal(82); if (!qh_addpoint (qh GOODvertexp, facet, False)) { qh_settempfree(&vertices); qh_settempfree(&maxpoints); return; } } qh_findgood (qh facet_list, 0); } qh_settempfree(&vertices); qh_settempfree(&maxpoints); qh_buildhull(); if (qh POSTmerge && !qh STOPpoint && !qh STOPcone) { qh POSTmerging= True; qh cos_max= qh postmerge_cos; qh centrum_radius= qh postmerge_centrum; FORALLfacets zinc_(Zpostfacets); qh newfacet_list= qh facet_list; qh visible_list= qh facet_list; qh newfacet_id= 0; qh newvertex_list= qh vertex_list; FORALLvertices vertex->newlist= True; qh_vertexneighbors (/*qh facet_list*/); qh_merge_nonconvex(/*qh newfacet_list*/); qh_partitionvisible (/*visible_list, newfacet_list*/ (boolT)!qh_ALL, &numoutside); qh_deletevisible (/*qh visible_list*/); qh POSTmerging= False; qh cos_max= qh premerge_cos; qh centrum_radius= qh premerge_centrum; } if (!qh FORCEoutput && (qh MERGING || qh APPROXhull)) qh_check_maxout (); if (qh_setsize ((setT *)qhmem.tempstack) != 0) qhull_fatal(83); qh hulltime= clock() - qh hulltime; qh QHULLfinished= True; trace1((qh ferr, "qh_qhull: algorithm completed\n")); } /* qhull */ /*------------------------------------------------- -addpoint- add point to hull above a facet if checkdist or !facet, locates a facet for the point if !checkdist and facet, assumes point is above facet (major damage if below) returns: if unknown point, adds it to qh other_points False if user requested break */ boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist) { int goodvisible, goodhorizon; vertexT *vertex; facetT *newfacet; realT dist, newbalance, pbalance; boolT isoutside= False; int numpart, numpoints; if (qh_pointid (furthest) == -1) qh_setappend (&qh other_points, furthest); if (checkdist || !facet) { if (!facet) facet= qh facet_list; facet= qh_findbest (furthest, facet, False, 0, &dist, &isoutside, &numpart); zzadd_(Zpartition, numpart); if (!isoutside) { zinc_(Znotmax); /* last point of outsideset is no longer furthest. */ qh_partitioncoplanar (furthest, facet, &dist); return True; } } qh_buildtracing (furthest, facet); if (qh STOPpoint < 0 && qh furthest_id == -qh STOPpoint-1) return False; qh_findhorizon (furthest, facet, &goodvisible, &goodhorizon); if (qh ONLYgood && !(goodvisible+goodhorizon)) { zinc_(Znotgood); /* last point of outsideset is no longer furthest. This is ok since all points of the outside are likely to be bad */ qh_clearvisible (/*qh visible_list*/); return True; } zzinc_(Zprocessed); vertex= qh_makenewfacets (furthest /*visible_list, attaches if !ONLYgood */); newbalance= qh facet_id - qh newfacet_id; newbalance -= (realT) (qh num_facets-qh num_visible)*qh hull_dim/qh num_vertices; wadd_(Wnewbalance, newbalance); wadd_(Wnewbalance2, newbalance * newbalance); if (qh ONLYgood && !qh_findgood (qh newfacet_list, goodhorizon)) { FORALLnew_facets qh_delfacet (newfacet); qh_delvertex (vertex); qh_clearvisible (/*qh visible_list*/); qh_clearnewvertices (/* qh newvertex_list*/); zinc_(Znotgoodnew); return True; } qh_attachnewfacets(/*visible_list*/); qh_matchnewfacets(); if (qh STOPcone && qh furthest_id == qh STOPcone-1) return False; if (qh PREmerge) qh_merge_nonconvex(/*qh newfacet_list*/); qh_partitionvisible (/*visible_list, newfacet_list*/ (boolT)!qh_ALL, &numpoints); zinc_(Zpbalance); pbalance= numpoints - (realT) qh hull_dim /* assumes all points extreme */ * (qh num_points - qh num_vertices)/qh num_vertices; wadd_(Wpbalance, pbalance); wadd_(Wpbalance2, pbalance * pbalance); qh_deletevisible (/*qh visible_list*/); qh_clearnewvertices (/* qh newvertex_list*/); /* if (qh IStracing >= 4) qh_printfacetlist (qh newfacet_list, NULL, True); NO LONGER IN SERVICE */ if (qh CHECKfrequently) { if (qh num_facets < 50) qh_checkpolygon (qh facet_list); else qh_checkpolygon (qh newfacet_list); } if (qh STOPpoint > 0 && qh furthest_id == qh STOPpoint-1) return False; trace2((qh ferr, "qh_addpoint: added p%d new facets %d new balance %2.2g point balance %2.2g\n", qh_pointid (furthest), qh facet_id - qh newfacet_id, newbalance, pbalance)); qh newfacet_id= qh facet_id; qh newfacet_list= NULL; return True; } /* addpoint */ /*------------------------------------------------- -buildhull- constructs a hull by adding outside points one at a time may be called multiple times checks facet and vertex lists for 'visible' and 'newlist' notes: to recover from STOPcone, call qh_deletevisible and qh_clearnewvertices */ void qh_buildhull(void) { facetT *facet; pointT *furthest; vertexT *vertex; int id; trace1((qh ferr, "qh_buildhull: start build hull\n")); FORALLfacets { if (facet->visible) qhull_fatal(84); } FORALLvertices { if (vertex->newlist) qhull_fatal(85); id= qh_pointid (vertex->point); if ((qh STOPpoint>0 && id == qh STOPpoint-1) || (qh STOPpoint<0 && id == -qh STOPpoint-1) || (qh STOPcone>0 && id == qh STOPcone-1)) { trace1((qh ferr,"qh_buildhull: stop point or cone P%d in initial hull\n", id)); return; } } qh facet_next= qh facet_list; /* advance facet when processed */ while ((furthest= qh_nextfurthest (&facet))) { qh num_outside--; if (!qh_addpoint (furthest, facet, qh ONLYmax)) break; } if (qh num_outside && !furthest) qhull_fatal(86); trace1((qh ferr, "qh_buildhull: completed the hull construction\n")); } /* buildhull */ /*------------------------------------------- -buildtracing- for tracing execution of buildhull also resets visit_id, vertext_visit on wrap around */ void qh_buildtracing (pointT *furthest, facetT *facet) { realT cpu, dist; time_t timedata; struct tm *tp; vertexT *vertex; qh furthest_id= qh_pointid(furthest); if (qh TRACEpoint == qh furthest_id) { qh IStracing= qh TRACElevel; qhmem.IStracing= qh TRACElevel; } if (qh REPORTfreq && (zzval_(Zsetplane) > qh lastreport+qh REPORTfreq)) { qh lastreport= zzval_(Zsetplane); time (&timedata); tp= localtime (&timedata); cpu= clock(); cpu /= qh_SECticks; zinc_(Zdistio); qh_distplane (furthest, facet, &dist); fprintf (qh ferr, "\n\ At %d:%d:%d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\ The current hull contains %d facets and %d vertices. There are %d\n\ outside points. Next is point p%d (v%d), %2.2g above f%d.\n", tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, zzval_(Zsetplane), zzval_(Ztotmerge), qh num_facets, qh num_vertices, qh num_outside+1, qh furthest_id, qh vertex_id, dist, facet->id); }else if (qh IStracing >=1) { cpu= clock(); cpu /= qh_SECticks; qh_distplane (furthest, facet, &dist); fprintf (qh ferr, "qh_buildhull: add p%d (v%d) to hull of %d facets (%2.2g above f%d) and %d outside. %4.4g CPU secs.\n", qh furthest_id, qh vertex_id, qh num_facets, dist, facet->id, qh num_outside+1, cpu); } #ifndef __BCC55__ // This condition is always false under BCC55 if (qh visit_id > INT_MAX) { qh visit_id= 0; FORALLfacets facet->visitid= qh visit_id; } #endif // __BCC55__ #ifndef __BCC55__ // This condition is always false under BCC55 if (qh vertex_visit > INT_MAX) { qh vertex_visit= 0; FORALLvertices vertex->visitid= qh vertex_visit; } #endif // __BCC55__ } /* buildtracing */ /*------------------------------------------- -errexit2- return exitcode to system after an error assumes exitcode non-zero for two facets, see qh_errexit() in user.c */ void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet) { qhull_fatal(87); } /* errexit2 */ /*------------------------------------------------- -findgood- identify good facets for qh ONLYgood GOODvertex>0 - facet includes point as vertex if !match, returns goodhorizon inactive if qh MERGING GOODpoint - facet is visible or coplanar (>0) or not visible (<0) GOODthreshold - facet->normal matches threshold if !goodhorizon and !match, selects facet with closest angle and sets GOODclosest returns: number of new, good facets found determins facet->good may update GOODclosest notes: findgood_all further reduces the good region */ int qh_findgood (facetT *facetlist, int goodhorizon) { facetT *facet, *bestfacet; realT angle, bestangle, dist; int numgood=0; if (qh GOODclosest) { bestfacet= qh GOODclosest; qh_inthresholds (bestfacet->normal, &bestangle); }else { bestfacet= NULL; bestangle= -REALmax; } FORALLfacet_(facetlist) { if (facet->good) numgood++; } if (qh GOODvertex>0 && !qh MERGING) { FORALLfacet_(facetlist) { if (!qh_isvertex (qh GOODvertexp, facet->vertices)) { facet->good= False; numgood--; } } } if (qh GOODpoint && numgood) { FORALLfacet_(facetlist) { if (facet->good) { zinc_(Zdistgood); qh_distplane (qh GOODpointp, facet, &dist); if ((qh GOODpoint > 0) ^ (dist > 0.0)) { facet->good= False; numgood--; } } } } if (qh GOODthreshold && (numgood || goodhorizon)) { FORALLfacet_(facetlist) { if (facet->good) { if (!qh_inthresholds (facet->normal, &angle)) { facet->good= False; numgood--; angle= fabs_(angle); if (angle > bestangle) { bestangle= angle; bestfacet= facet; } } } } if (!numgood && bestfacet && bestfacet != qh GOODclosest) { if (qh GOODclosest) qh GOODclosest->good= False; qh GOODclosest= bestfacet; bestfacet->good= True; numgood++; trace2((qh ferr, "qh_findgood: f%d is closest (%2.2g) to thresholds\n", bestfacet->id, bestangle)); return numgood; }else if (numgood && qh GOODclosest) qh GOODclosest->good= False; } zadd_(Zgoodfacet, numgood); trace2((qh ferr, "qh_findgood: found %d good facets\n", numgood)); if (!numgood && qh GOODvertex>0 && !qh MERGING) return goodhorizon; return numgood; } /* findgood */ /*------------------------------------------------- -findgood_all- apply other constraints for good facets (used by qh PRINTgood) GOODvertex - facet includes (>0) or doesn't include (<0) point as vertex if last good facet, prints warning and continues SPLITthreshold - facet->normal matches threshold, or if none, the closest one calls findgood if !ONLYgood returns: clears facet->good if not good sets qh num_good notes: this is like findgood but more restrictive */ void qh_findgood_all (facetT *facetlist) { facetT *facet, *bestfacet=NULL; realT angle, bestangle= REALmax; int numgood=0, startgood; if (!qh ONLYgood) qh_findgood (qh facet_list, 0); FORALLfacet_(facetlist) { if (facet->good) numgood++; } if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) { FORALLfacet_(facetlist) { if ((qh GOODvertex > 0) ^ !!qh_isvertex (qh GOODvertexp, facet->vertices)) { if (!--numgood) { fprintf (qh ferr, "qhull warning: good vertex p%d does not match last good facet f%d. Ignored.\n", qh_pointid(qh GOODvertexp), facet->id); return; } facet->good= False; } } } startgood= numgood; if (qh SPLITthresholds) { FORALLfacet_(facetlist) { if (facet->good) { if (!qh_inthresholds (facet->normal, &angle)) { facet->good= False; numgood--; angle= fabs_(angle); if (angle < bestangle) { bestangle= angle; bestfacet= facet; } } } } if (!numgood) { bestfacet->good= True; numgood++; trace0((qh ferr, "qh_findgood_all: f%d is closest (%2.2g) to thresholds\n", bestfacet->id, bestangle)); return; } } qh num_good= numgood; trace0((qh ferr, "qh_findgood_all: %d good facets remain out of %d facets\n", numgood, startgood)); } /* findgood_all */ /*------------------------------------------------- -findhorizon- given a visible facet, find the point's horizon and visible facets returns: qh visible_list to all visible facets marks visible facets with ->visible goodvisible counts visible->good initializes num_visible notes: similar to delpoint() */ void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible, int *goodhorizon) { facetT *neighbor, **neighborp, *visible; int numhorizon= 0; realT dist; #if qh_MAXoutside boolT ckminvis= (boolT)(qh MINvisible > qh DISTround), isoutside; #endif trace1((qh ferr,"qh_findhorizon: find horizon for point p%d facet f%d\n",qh_pointid(point),facet->id)); *goodvisible= *goodhorizon= 0; zinc_(Ztotvisible); qh_removefacet(facet); /* visible_list at end of qh facet_list */ qh_appendfacet(facet); qh num_visible= 1; if (facet->good) (*goodvisible)++; qh visible_list= facet; facet->visible= True; /* if (qh IStracing >=4) qh_errprint ("visible", facet, NULL, NULL, NULL); NO LONGER IN SERVICE */ qh visit_id++; FORALLvisible_facets { visible->visitid= qh visit_id; FOREACHneighbor_(visible) { if ((int)neighbor->visitid == qh visit_id) continue; neighbor->visitid= qh visit_id; zzinc_(Znumvisibility); qh_distplane(point, neighbor, &dist); #if qh_MAXoutside isoutside= False; if (ckminvis) { if (dist >= qh MINvisible) isoutside= True; }else if (qh ONLYmax) { /* furthest points are at least maxoutside above */ if (dist >= neighbor->maxoutside || dist >= qh max_vertex) isoutside= True; }else if (qh PREmerge) { if (dist >= qh MINoutside) isoutside= True; }else if (dist > qh DISTround) isoutside= True; if (isoutside) { #else if (dist > qh MINvisible) { #endif zinc_(Ztotvisible); qh_removefacet(neighbor); /* append to end of qh visible_list */ qh_appendfacet(neighbor); neighbor->visible= True; qh num_visible++; if (neighbor->good) (*goodvisible)++; /* if (qh IStracing >=4) qh_errprint ("visible", neighbor, NULL, NULL, NULL); NO LONGER IN SERVICE */ }else { if (dist > -qh DISTround) { zzinc_(Zcoplanarhorizon); trace0((qh ferr, "qh_findhorizon: point p%d is coplanar to horizon f%d, dist=%2.7g < qh MINvisible (%2.7g)\n", qh_pointid(point), neighbor->id, dist, qh MINvisible)); } zinc_(Ztothorizon); numhorizon++; if (neighbor->good) (*goodhorizon)++; /* if (qh IStracing >=4) qh_errprint ("horizon", neighbor, NULL, NULL, NULL); NO LONGER IN SERVICE */ } } } if (!numhorizon) qhull_fatal(88); trace1((qh ferr, "qh_findhorizon: %d horizon facets (good %d), %d visible (good %d) min visible %2.2g\n", numhorizon, *goodhorizon, qh num_visible, *goodvisible, qh MINvisible)); if (qh IStracing >= 4 && qh num_facets < 50) qh_printlists (); } /* findhorizon */ /*-------------------------------------------------- -initialhull- constructs the initial hull as a qh hull_dim simplex of vertices */ void qh_initialhull(setT *vertices) { facetT *facet, *firstfacet; int k; realT dist; qh_createsimplex(vertices); /* qh facet_list */ qh interior_point= qh_getcenter(vertices); firstfacet= qh facet_list; qh_setfacetplane(firstfacet); zinc_(Znumvisibility); /* needs to be in printsummary */ qh_distplane(qh interior_point, firstfacet, &dist); if (dist > 0) { FORALLfacets facet->toporient ^= True; } FORALLfacets qh_setfacetplane(facet); FORALLfacets { if (!qh_checkflipped (facet, NULL, qh_ALL)) {/* due to axis-parallel facet */ trace1((qh ferr, "qh_initialhull: initial orientation incorrect. Correct all facets\n")); facet->flipped= False; FORALLfacets { facet->toporient ^= True; qh_orientoutside (facet); } break; } } FORALLfacets { if (!qh_checkflipped (facet, NULL, (boolT)!qh_ALL)) qhull_fatal(89); } zzval_(Zprocessed)= qh hull_dim+1; qh_checkpolygon (qh facet_list); qh_checkconvex(qh facet_list, qh_DATAfault); if (qh IStracing >= 1) { fprintf(qh ferr, "qh_initialhull: simplex constructed, interior point:"); for (k=0; k= 8) { qh_setunique (&simplex, SETfirst_(maxpoints)); FOREACHpoint_i_(maxpoints) { if (point_i & 0x1) { /* first pick up max/min x and max points */ qh_setunique (&simplex, point); if (qh_setsize (simplex) == dim) /* search for last point */ break; } } if (qh_setsize (simplex) != dim) { while ((point= (pointT *)qh_setdellast (maxpoints))) { qh_setunique (&simplex, point); if (qh_setsize (simplex) == dim) break; } } index= 0; while (qh_setsize (simplex) != dim) { point= qh_point (index++); qh_setunique (&simplex, point); } qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex); }else qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex); FOREACHpoint_(simplex) qh_setaddnth (&vertices, 0, qh_newvertex(point)); /* descending order */ qh_settempfree (&simplex); return vertices; } /* initialvertices */ /*------------------------------------------------ -nextfurthest- returns next furthest point for processing returns: NULL if none available visible facet for furthest removes empty outside sets */ pointT *qh_nextfurthest (facetT **visible) { facetT *facet; int size; /* , index; UNUSED */ /* realT randr; UNUSED */ pointT *furthest; while ((facet= qh facet_next) != qh facet_tail) { if (!facet->outsideset) { qh facet_next= facet->next; continue; } SETreturnsize_(facet->outsideset, size); if (!size) { qh_setfree (&facet->outsideset); qh facet_next= facet->next; continue; } if (!qh RANDOMoutside && !qh VIRTUALmemory) { *visible= facet; return (pointT *)(qh_setdellast (facet->outsideset)); } if (qh RANDOMoutside) qhull_fatal(90); else { /* VIRTUALmemory */ facet= qh facet_tail->previous; if (!(furthest= (pointT *)qh_setdellast(facet->outsideset))) { if (facet->outsideset) qh_setfree (&facet->outsideset); qh_removefacet (facet); qh_prependfacet (facet, &qh facet_list); continue; } *visible= facet; return furthest; } } return NULL; } /* nextfurthest */ /*------------------------------------------------- -partitionall- partitions all points into the outsidesets of facets vertices= set of vertices used by qh facet_list does not partition qh GOODpoint if ONLYgood && !MERGING, does not partition GOODvertex qh newfacet_id=0 for qh_findbest notes: faster if qh facet_list sorted by anticipated size of outside set */ void qh_partitionall(setT *vertices, pointT *points, int numpoints){ setT *pointset; vertexT *vertex, **vertexp; pointT *point, **pointp, *bestpoint; int size, point_i, point_n, point_end, remaining, i, id; facetT *facet; realT bestdist= -REALmax, dist; trace1((qh ferr, "qh_partitionall: partition all points into outside sets\n")); pointset= qh_settemp (numpoints); pointp= SETaddr_(pointset, pointT); for (i=numpoints, point= points; i--; point += qh hull_dim) *(pointp++)= point; qh_settruncate (pointset, numpoints); FOREACHvertex_(vertices) { if ((id= qh_pointid(vertex->point)) >= 0) SETelem_(pointset, id)= NULL; } id= qh_pointid (qh GOODpointp); if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id) SETelem_(pointset, id)= NULL; if (qh GOODvertexp && qh ONLYgood && !qh MERGING) { /* matches qhull()*/ if ((id= qh_pointid(qh GOODvertexp)) >= 0) SETelem_(pointset, id)= NULL; } if (!qh BESToutside) { zval_(Ztotpartition)= qh num_points - qh hull_dim - 1; /*misses GOOD... */ remaining= qh num_facets; point_end= numpoints; FORALLfacets { size= point_end/(remaining--) + 100; facet->outsideset= qh_setnew (size); bestpoint= NULL; point_end= 0; FOREACHpoint_i_(pointset) { if (point) { zzinc_(Zpartitionall); qh_distplane (point, facet, &dist); if (dist < qh MINoutside) SETelem_(pointset, point_end++)= point; else { qh num_outside++; if (!bestpoint) { bestpoint= point; bestdist= dist; }else if (dist > bestdist) { qh_setappend (&facet->outsideset, bestpoint); bestpoint= point; bestdist= dist; }else qh_setappend (&facet->outsideset, point); } } } if (bestpoint) { qh_setappend (&facet->outsideset, bestpoint); #if !qh_COMPUTEfurthest facet->furthestdist= bestdist; #endif }else qh_setfree (&facet->outsideset); qh_settruncate (pointset, point_end); } } FOREACHpoint_i_(pointset) { if (point) qh_partitionpoint(point, qh facet_list); } qh_settempfree(&pointset); /* if (qh IStracing >= 4) qh_printfacetlist (qh facet_list, NULL, True); NO LONGER IN SERVICE */ } /* partitionall */ /*------------------------------------------------- -partitioncoplanar- partition coplanar point to a facet if dist NULL, searches from bestfacet, and does nothing if inside returns: max_ouside, num_coplanar updated if KEEPcoplanar or KEEPinside point assigned to best coplanarset */ void qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist) { facetT *bestfacet; pointT *oldfurthest; realT bestdist, dist2; int numpart= 0; boolT isoutside; if (!dist) { bestfacet= qh_findbest (point, facet, True, 0, &bestdist, &isoutside, &numpart); zinc_(Ztotpartcoplanar); zzadd_(Zpartcoplanar, numpart); if (bestdist < qh min_vertex) { zinc_(Zcoplanarinside); if (!qh KEEPinside) return; }else qh num_coplanar++; }else { bestfacet= facet; bestdist= *dist; if (!qh KEEPinside || bestdist >= qh min_vertex) qh num_coplanar++; } if (qh KEEPcoplanar + qh KEEPinside) { oldfurthest= (pointT *)qh_setlast (bestfacet->coplanarset); if (oldfurthest) { zinc_(Zcomputefurthest); qh_distplane (oldfurthest, bestfacet, &dist2); } if (!oldfurthest || dist2 < bestdist) { qh_setappend(&bestfacet->coplanarset, point); maximize_(qh max_outside, bestdist); }else qh_setappend2ndlast(&bestfacet->coplanarset, point); }else maximize_(qh max_outside, bestdist); trace2((qh ferr, "qh_partitioncoplanar: point p%d is coplanar with facet f%d (or inside) dist %2.2g\n", qh_pointid(point), bestfacet->id, bestdist)); } /* partitioncoplanar */ /*------------------------------------------------- -partitionpoint- assigns point to a visible facet !BESToutside stops search when point is outside or new facets findbest does not search !newfacet_id if precise and !BESToutside */ void qh_partitionpoint (pointT *point, facetT *facet) { realT bestdist; pointT *oldfurthest; boolT isoutside; facetT *bestfacet; int numpart; bestfacet= qh_findbest (point, facet, qh BESToutside, qh newfacet_id, &bestdist, &isoutside, &numpart); zinc_(Ztotpartition); zzadd_(Zpartition, numpart); if (isoutside) { if (!bestfacet->outsideset || !(oldfurthest= (pointT *)qh_setlast (bestfacet->outsideset))) { qh_setappend(&(bestfacet->outsideset), point); if (bestfacet->id < qh newfacet_id) { qh_removefacet (bestfacet); /* move after qh facet_next */ qh_appendfacet (bestfacet); } }else { #if qh_COMPUTEfurthest zinc_(Zcomputefurthest); qh_distplane (oldfurthest, bestfacet, &dist); if (dist < bestdist) qh_setappend(&(bestfacet->outsideset), point); else qh_setappend2ndlast(&(bestfacet->outsideset), point); #else if (bestfacet->furthestdist < bestdist) { qh_setappend(&(bestfacet->outsideset), point); bestfacet->furthestdist= bestdist; }else qh_setappend2ndlast(&(bestfacet->outsideset), point); #endif } qh num_outside++; trace4((qh ferr, "qh_partitionpoint: point p%d is outside facet f%d\n", qh_pointid(point), bestfacet->id)); }else if (bestdist < qh min_vertex) { zinc_(Zpartinside); trace4((qh ferr, "qh_partitionpoint: point p%d is inside all facets, closest to f%d dist %2.2g\n", qh_pointid(point), bestfacet->id, bestdist)); if (qh KEEPinside) qh_partitioncoplanar (point, bestfacet, &bestdist); }else { zzinc_(Zcoplanarpart); if (qh KEEPcoplanar || bestdist > qh max_outside || (!qh BESToutside && qh newfacet_id && !qh MERGING)) qh_partitioncoplanar (point, bestfacet, &bestdist); } } /* partitionpoint */ /*------------------------------------------------- -partitionvisible- partitions points in visible_list to newfacet_list 1st neighbor (if any) points to a horizon facet or a new facet repartitions coplanar points if allpoints */ void qh_partitionvisible(/*visible_list*/ boolT allpoints, int *numoutside) { facetT *visible, *newfacet; pointT *point, **pointp; int coplanar=0, size; vertexT *vertex, **vertexp; if (qh ONLYmax) maximize_(qh MINoutside, qh max_vertex); *numoutside= 0; FORALLvisible_facets { if (!visible->outsideset && !visible->coplanarset) continue; newfacet= (facetT *)SETfirst_(visible->neighbors); while (newfacet && newfacet->visible) newfacet= (facetT *)SETfirst_(newfacet->neighbors); if (!newfacet) newfacet= qh newfacet_list; if (visible->outsideset) { size= qh_setsize (visible->outsideset); *numoutside += size; qh num_outside -= size; FOREACHpoint_(visible->outsideset) qh_partitionpoint (point, newfacet); } if (visible->coplanarset && (qh KEEPcoplanar || qh KEEPinside)) { size= qh_setsize (visible->coplanarset); coplanar += size; qh num_coplanar -= size; FOREACHpoint_(visible->coplanarset) { if (allpoints) qh_partitionpoint (point, newfacet); else qh_partitioncoplanar (point, newfacet, NULL); } } } FOREACHvertex_(qh del_vertices) { if (vertex->point) { if (qh DELAUNAY && !allpoints && !(qh APPROXhull | qh MERGING)) fprintf (qh ferr, "qhull precision warning: point p%d (v%d) deleted due to roundoff errors\n", qh_pointid(vertex->point), vertex->id); if (allpoints) qh_partitionpoint (vertex->point, qh newfacet_list); else qh_partitioncoplanar (vertex->point, qh newfacet_list, NULL); } } trace1((qh ferr,"qh_partitionvisible: partitioned %d points from outsidesets and %d points from coplanarsets\n", *numoutside, coplanar)); } /* partitionvisible */ gambit-0.2010.09.01/src/tools/enumpoly/pelqhull.h0000644000076500007650000023467711351773322016265 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* qhull.h -- user-level header file for using qhull.a library see README, qhull_a.h copyright (c) 1993-1994, The Geometry Center defines qh_qh, global data structure for qhull. NOTE: access to qh_qh is via the 'qh' macro. This allows qh_qh to be either a pointer or a structure. An example of using qh is "qh DROPdim" which accesses the DROPdim field of qh_qh. Similarly, access to qh_qhstat is via the 'qhstat' macro. includes function prototypes for qhull.c, geom.c, global.c, io.c, user.c use mem.h for mem.c use set.h for set.c see unix.c for an example of using qhull.h recompile qhull if you change this file */ #include #include #include #include #include #include /* some compilers will not need float.h */ #include #include #include #ifndef qhDEFqhull #define qhDEFqhull 1 #include #include #include /* ============ -types- ==================== */ #define pointT coordT /* array of hull_dim coordinates */ #define flagT unsigned int /* Boolean flag */ typedef enum {False, True} boolT; /* True=1, False= 0 */ /* -center type for facet->center and CENTERtype */ enum qh_CENTER {qh_none, qh_voronoi, qh_centrum}; /* -output formats for printing (qh PRINTout) */ enum qh_PRINT {qh_PRINTnone, qh_PRINTfacets, qh_PRINTgeom, qh_PRINTnormals, qh_PRINTincidences, qh_PRINTmathematica, qh_PRINToff, qh_PRINTpoints, qh_PRINTEND}; /*--------------------------------- -realT -- select size of floating point numbers normally use 'float' because convex hulls are space limited in high-d this saves about 8% in time and 25% in space could use 'double' for internal calculations (realT vs. coordT) but this requires many type casts, and adjusted error bounds C compilers will often do expressions in double WARNING: on some machines, can not test for equality after setting REALmax. Use REALmax/2 instead. */ #define REALfloat 1 /* use 0 for double precision */ #if REALfloat #define realT float #define REALmax FLT_MAX #define REALmin FLT_MIN #define REALepsilon FLT_EPSILON #define qh_REALdigits 8 /* maximum number of significant digits */ #define qh_REAL_1 "%6.8g " #define qh_REAL_2n "%6.8g %6.8g\n" #define qh_REAL_3n "%6.8g %6.8g %6.8g\n" #else #define realT double #define REALmax DBL_MAX #define REALmin DBL_MIN #define REALepsilon DBL_EPSILON #define qh_REALdigits 16 /* maximum number of significant digits */ #define qh_REAL_1 "%6.16g " #define qh_REAL_2n "%6.16g %6.16g\n" #define qh_REAL_3n "%6.16g %6.16g %6.16g\n" #endif #define coordT realT /* for stored coordinates and coefficients */ /*------------------------------------------ constants */ #define qh_DEFAULTbox 0.5 /* default box size (Geomview expects 0.5) */ #define qh_INFINITE -10.101 /* coordinates for Voronoi center at infinity */ #define qh_ALL True /* argument for printall and checkall parameters*/ /*------------------------------------ Conditional compilation -COMPUTEfurthest computing furthest saves 4% of memory and costs ca. 3% time (about 40% more distance tests for partitioning) -MAXoutside keep maxoutside for each facet this takes a realT per facet and slightly slows down qhull it should speed up pre-merging with Wn or Qm better outer planes for geomview output */ #define qh_COMPUTEfurthest 0 /* 1 removes facet->furthestdist */ #define qh_MAXoutside 1 /* 0 removes facet->maxoutside */ /*------------------------------------------- -ERR - qhull exit codes, for indicating errors */ #define qh_ERRnone 0 /* no error occurred during qhull */ #define qh_ERRinput 1 /* input inconsistency */ #define qh_ERRsingular 2 /* singular input data */ #define qh_ERRprec 3 /* precision error */ #define qh_ERRmem 4 /* insufficient memory, matches mem.h */ #define qh_ERRqhull 5 /* internal error detected, matches mem.h */ /* ============ -structures- ==================== each of the following structures is defined by a typedef all realT and coordT fields occur at the beginning of a structure (otherwise space may be wasted due to alignment) define all flags together and pack into 32-bit number */ typedef struct vertexT vertexT; typedef struct ridgeT ridgeT; typedef struct facetT facetT; #ifndef DEFsetT #define DEFsetT 1 typedef struct setT setT; /* defined in set.h */ #endif /* ---------------------------------------------- -facetT- specifies a facet */ struct facetT { #if !qh_COMPUTEfurthest coordT furthestdist;/* distance to furthest point of outsideset */ #endif #if qh_MAXoutside coordT maxoutside; /* max computed distance of point to facet Before QHULLfinished this is an approximation since maxdist not always set for mergefacet */ #endif coordT offset; /* offset of hyperplane from origin */ coordT *normal; /* normal of hyperplane, hull_dim coefficients */ coordT *center; /* centrum or Voronoi center, see CENTERtype */ facetT *previous; /* previous facet in the facet_list */ facetT *next; /* next facet in the facet_list */ setT *vertices; /* vertices for this facet, inverse sorted by id */ setT *ridges; /* explicit ridges for nonsimplicial facets. for simplicial facets, neighbors defines ridge */ setT *neighbors; /* neighbors of the facet. if simplicial, kth neighbor skips kth vertex. if visible, 1st neighbor (if any) is newfacet or deleted newfacet (visible) */ setT *outsideset; /* set of points outside this facet if non-empty, last point is furthest */ setT *coplanarset; /* set of points coplanar with this facet > min_vertex and <= facet->max_outside a point is assigned to the furthest facet if non-empty, last point is furthest away */ unsigned visitid; /* visit_id, for visiting all neighbors, all uses must be independent */ unsigned id:24; /* unique identifier, =>room for 8 flags new facet if >= qh newfacet_id */ flagT toporient:1; /* True if created with top orientation after merging, use ridge orientation */ flagT simplicial:1;/* True if simplicial facet, ->ridges may be implicit */ flagT good:1; /* True if a good facet (for output) */ flagT tested:1; /* True if facet changed due to merge */ flagT seen:1; /* used to perform operations only once, like visitid */ flagT flipped:1; /* True (if !NEWmerges) if facet is flipped */ flagT visible:1; /* True if visible facet */ }; #define qh_isnewmerge_(facet) ((facet)->flipped) /* if qh NEWmerges */ #define qh_newmerge_(facet) {(facet)->flipped= True; numnewmerges++;} #define qh_clearnewmerge_(facet) (facet)->flipped= False; /*---------------------------------------------- -ridgeT- specifies a ridge */ struct ridgeT { setT *vertices; /* vertices belonging to this ridge, inverse sorted by id NULL if a degen ridge (matchsame) */ facetT *top; /* top facet this ridge is part of */ facetT *bottom; /* bottom facet this ridge is part of */ unsigned id:24; /* unique identifier, =>room for 8 flags */ flagT seen:1; /* used to perform operations only once */ flagT tested:1; /* True when ridge is tested for convexity */ flagT nonconvex:1; /* True if getmergeset detected a non-convex neighbor */ flagT mergeridge:1; /* True if from a qh_MERGEridge (duplicates) */ }; /* ---------------------------------------------- -vertexT- specifies a vertex */ struct vertexT { vertexT *next; /* next vertex in vertex_list */ vertexT *previous; /* previous vertex in vertex_list */ pointT *point; /* hull_dim coordinates (coordT) */ setT *neighbors; /* neighboring facets of vertex, if qh_vertexneighbors */ unsigned visitid; /* for use with qh vertex_visit */ unsigned id:24; /* unique identifier, =>room for 8 flags */ flagT seen:1; /* used to perform operations only once */ flagT seen2:1; /* another seen flag */ flagT delridge:1; /* vertex was part of a deleted ridge */ flagT deleted:1; /* true if vertex on qh del_vertices */ flagT newlist:1; /* true if vertex on qh newvertex_list */ }; /* ======= -global variables -qh ============================ all global variables for qhull are in qh, qhmem, and qhstat qhmem is defined in mem.h and qhstat is defined in stat.h set qh_QHpointer 1 to enable qh_saveqhull() and qh_restoreqhull() this costs about 7% in time and space. */ typedef struct qhT qhT; #define qh_QHpointer 0 /* 1 for dynamic allocation, 0 for global structure */ #if qh_QHpointer #define qh qh_qh-> extern qhT *qh_qh; /* allocated in global.c */ #else #define qh qh_qh. extern qhT qh_qh; #endif struct qhT { /*-user flags */ boolT ALLpoints; /* true 'Qi' if search all points for initial simplex */ boolT APPROXhull; /* true 'W' if MINoutside set */ realT MINoutside; /* min. distance for an outside point */ boolT BESToutside; /* true 'Qf' if partition points into best outsideset */ boolT CHECKfrequently; /* true 'Tc' if checking frequently */ realT premerge_cos; /* 'C-n' cos_max when pre merging */ realT postmerge_cos; /* 'Cn' cos_max when post merging */ boolT DELAUNAY; /* true 'd' if computing DELAUNAY triangulation */ boolT DOintersections; /* print hyperplaneintersections in 3-d and 4-d */ int DROPdim; /* drops dim 'GDn' for 4-d -> 3-d output */ boolT ERREXITcalled; /* true during errexit (prevents duplicate calls */ boolT FORCEoutput; /* true 'Po' if forcing output despite degeneracies */ int GOODpoint; /* 1+n, good facet if visible/not(-) from point n*/ pointT *GOODpointp; /* the actual point */ boolT GOODthreshold; /* true if qh lower_threshold/upper_threshold defined false if qh SPLITthreshold */ int GOODvertex; /* 1+n, good facet if vertex for point n */ pointT *GOODvertexp; /* the actual point */ int IStracing; /* trace execution, 0=none, 1=least, 4=most, -1=events */ boolT KEEPcoplanar; /* true if keeping nearest facet for coplanar points */ boolT KEEPinside; /* true if keeping nearest facet for inside/coplanar points */ boolT MERGING; /* true if merging, with angle and centrum tests */ realT premerge_centrum; /* 'R-n' centrum_radius when pre merging */ realT postmerge_centrum; /* 'Rn' centrum_radius when post merging */ realT MINvisible; /* min. distance for a facet to be visible */ boolT ONLYgood; /* only process points with good visible or horizon facets */ boolT ONLYmax; /* only process points that increase max_outside */ boolT POINTSmalloc; /* true if qh first_point/num_points allocated */ boolT POSTmerge; /* true if merging after buildhull (C-n or R-n) */ boolT PREmerge; /* true if merging during buildhull (Cn or Rn) */ boolT PRINTcentrums; /* true 'Gc' if printing centrums */ boolT PRINTcoplanar; /* true 'Gp' if printing coplanar points */ int PRINTdim; /* print dimension for Geomview output */ boolT PRINTdots; /* true 'Ga' if printing all points as dots */ boolT PRINTgood; /* true 'Pg' if printing good facets */ boolT PRINTinner; /* true 'Gi' if printing inner planes */ boolT PRINTneighbors; /* true 'PG' if printing neighbors of good facets */ boolT PRINTnoplanes; /* true 'Gn' if printing no planes */ boolT PRINTouter; /* true 'Go' if printing outer planes */ boolT PRINTprecision; /* false 'Pp' if not reporting precision problems */ int PRINTout[qh_PRINTEND]; /* list of output formats to print */ boolT PRINTridges; /* true 'Gr' if print ridges */ boolT PRINTspheres; /* true 'Gv' if print vertices as spheres */ boolT PRINTstatistics; /* true 'Ts' if printing statistics to stderr */ boolT PRINTsummary; /* true 's' if printing summary to stderr */ boolT PROJECTdelaunay; /* true if DELAUNAY, no readpoints() and need projectinput() for Delaunay */ int PROJECTinput; /* number of projected dimensions 'bn:0Bn:0' */ boolT QUICKhelp; /* true if quick help message for degen input */ boolT RANDOMdist; /* true if randomly change distplane and setfacetplane */ realT RANDOMfactor; /* maximum perturbation */ realT RANDOMa; /* qh_randomfactor is randr * RANDOMa + RANDOMb */ realT RANDOMb; boolT RANDOMoutside; /* true if select a random outside point */ int REPORTfreq; /* buildtracing reports every n facets */ int ROTATErandom; /* 'QRn' seed, 0 time, >= rotate input */ boolT SCALEinput; /* true if scaling input, 'Qb' */ boolT SETroundoff; /* true 'E' if qh DISTround is predefined */ boolT SPLITthresholds; /* true if upper_/lower_threshold defines a region used only for printing (not for qh ONLYgood) */ int STOPcone; /* 1+n for stopping after building cone for point n*/ int STOPpoint; /* 1+n for stopping after/before(-) adding point n*/ int TRACElevel; /* conditional IStracing level */ int TRACEpoint; /* start tracing when point n becomes a vertex */ realT TRACEdist; /* start tracing when merge distance too big */ int TRACEmerge; /* start tracing before this merge */ boolT VERIFYoutput; /* true 'Tv' if verify output at end of qhull */ boolT VERTEXneighbors; /* true if maintaining vertex neighbors */ boolT VIRTUALmemory; /* true if depth-first processing in buildhull */ boolT VORONOI; /* true 'v' if computing Voronoi diagram */ /* -input constants */ int input_dim; /* dimension of input, set by initbuffers */ int num_points; /* number of input points */ pointT *first_point; /* first input point */ int hull_dim; /* dimension of hull, set by initbuffers */ char qhull_command[256];/* command line that invoked this program */ char rbox_command[256]; /* command line that produced the input points */ realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k] must set either GOODthreshold or SPLITthreshold if Delaunay, default is 0.0 for upper envelope */ realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */ realT *upper_bound; /* scale point[k] to new upper bound */ realT *lower_bound; /* scale point[k] to new lower bound project if both upper_ and lower_bound == 0 */ /* -precision constants, computed in qh_maxmin */ realT centrum_radius; /* max centrum radius for convexity (roundoff added) */ realT cos_max; /* max cosine for convexity (roundoff added) */ realT maxmaxcoord; /* max coordinate in any dimension */ realT DISTround; /* max round off error for distances, 'E' overrides */ realT ONEmerge; /* max distance for merging simplicial facets */ realT MINdenom_1; /* min. abs. value for 1/x */ realT MINdenom; /* use divzero if denominator < MINdenom */ realT MINdenom_1_2; /* min. abs. val for 1/x that allows normalization */ realT MINdenom_2; /* use divzero if denominator < MINdenom_2 */ realT *NEARzero; /* hull_dim array for near zero in gausselim */ /* -internal constants */ char qhull[sizeof("qhull")]; /* for checking ownership */ void *old_stat; /* pointer to saved qh_qhstat, qh_save_qhull */ jmp_buf errexit; /* exit label for qh_errexit */ FILE *fin; /* pointer to input file, init by qh_meminit */ FILE *fout; /* pointer to output file */ FILE *ferr; /* pointer to error file */ pointT *interior_point; /* center point of the initial simplex*/ int normal_size; /* size in bytes for facet normals and point coords*/ int center_size; /* size in bytes for Voronoi centers */ int TEMPsize; /* size for small, temporary sets (in quick mem) */ /* -list of all facets, from facet_list to facet_tail, see qh_appendfacet */ facetT *facet_list; /* first facet */ facetT *facet_next; /* next facet for buildhull() all previous facets do not have outside sets*/ facetT *visible_list; /* list of visible facets, with visible set */ int num_visible; /* current number of visible facets */ facetT *newfacet_list; /* list of new facets to end of facet_list */ facetT *facet_tail; /* end of facet_list (dummy facet) */ unsigned tracefacet_id; /* set at init, then can print whenever */ facetT *tracefacet; /* set in newfacet/mergefacet, undone in delfacet*/ unsigned tracevertex_id; /* set at buildtracing, can print whenever */ vertexT *tracevertex; /* set in newvertex, undone in delvertex*/ vertexT *vertex_list; /* list of all vertices, to vertex_tail */ vertexT *vertex_tail; vertexT *newvertex_list; /* list of vertices in newfacet_list all vertices have 'new' set */ int num_facets; /* number of facets in facet_list includes visble faces (num_visible) */ int num_vertices; /* number of vertices in facet_list */ int num_outside; /* number of points in outsidesets */ int num_coplanar; /* number of coplanar points */ int num_good; /* number of good facets (after findgood_all) */ unsigned newfacet_id; /* new facet if facet->id >= newfacet_id */ int facet_id; /* id of next, new facet from newfacet() */ int ridge_id; /* id of next, new ridge from newridge() */ unsigned vertex_id; /* id of next, new vertex from newvertex() */ /* -variables */ clock_t hulltime; /* ignore time to set up input and randomize */ int CENTERtype; /* current type of facet->center, qh_CENTER */ int furthest_id; /* pointid of furthest point, for tracing */ facetT *GOODclosest; /* closest facet to GOODthreshold in qh_findgood */ realT max_outside; /* maximum distance from a point to a facet, before roundoff, not simplicial vertices */ realT max_vertex; /* maximum distance (>0) from vertex to a facet, before roundoff, not simplicial vertices */ realT min_vertex; /* minimum distance (<0) from vertex to a facet, before roundoff, not simplicial vertices defines coplanar points */ boolT NEWfacets; /* true while visible facets invalid from makecone/attachnewfacets to deletevisible */ boolT NEWmerges; /* true while merging, facet->flipped is defined as facet->newmerge */ boolT NOerrexit; /* true if qh_errexit is not available */ realT PRINTcradius; /* radius for printing centrums */ realT PRINTradius; /* radius for printing vertex spheres and points */ boolT POSTmerging; /* true when post merging */ int printoutvar; /* temporary variable for qh_printbegin, etc. */ int printoutnum; /* number of facets printed */ boolT QHULLfinished; /* True after qhull() is finished */ int visit_id; /* unique id for searching neighborhoods, */ int vertex_visit; /* unique id for searching vertices */ /* -sets */ setT *facet_mergeset; /* temporary set of merges to be done */ setT *initial_points; /* initial simplex for buildhull() */ setT *hash_table; /* hash table for matching ridges in qh_matchfacets size is setsize() */ int num_hashentries; /* current number of hashentries */ setT *other_points; /* additional points (first is qh interior_point) */ setT *del_vertices; /* vertices to partition and delete with visible facets. Have deleted set for checkfacet */ /* -buffers */ coordT *gm_matrix; /* (dim+1)Xdim matrix for geom.c */ coordT **gm_row; /* array of gm_matrix rows */ char* line; /* malloc'd input line of maxline+1 chars */ int maxline; /* -statics */ boolT firstcentrum; /* for qh_printcentrum */ int lastreport; /* for qh_buildtracing */ int mergereport; /* for qh_tracemerging */ boolT old_randomdist; /* save in io.c for RANDOMdist */ int ridgeoutnum; /* number of ridges in 4OFF output */ void *old_qhstat; /* for saving qh_qhstat in save_qhull() */ setT *old_tempstack; /* for saving qhmem.tempstack in save_qhull */ }; /* =========== -macros- ========================= -otherfacet_(ridge, facet) return neighboring facet for a ridge in facet -getid_(p) return id or -1 if NULL */ #define otherfacet_(ridge, facet) \ (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top) #define getid_(p) ((p) ? (p)->id : (unsigned int) -1) /* --------------------------------------------- -FORALL and FOREACH macros These all iterate using a variable of the same name, e.g. FORALLfacets and FOREACHfacet_ uses 'facet' declared by 'facetT *facet'. The macros may use auxiliary variables as indicated. -FORALLfacets iterate over all facets in facetlist -FORALLpoint_(points, num) iterate over num points (uses 'pointT *pointtemp') -FORALLvertices iterate over all vertices in vertex_list -FOREACHfacet_(facets) iterate over facet set (uses 'facetT **facetp') -FOREACHneighbor_(facet) iterate over facet->neighbors (uses 'facetT **neighborp') -FOREACHpoint_(points) iterate over point set (uses 'pointT **pointp') -FOREACHridge_(ridges) iterate over ridge set (uses 'ridgeT **ridgep') -FOREACHvertex_(vertice) iterate over vertex set (uses 'vertexT **vertexp') -FOREACHadjacent_(vertex) iterate over adjacent vertices to vertex -FOREACHneighbor_(vertex) iterate over neighboring facets to vertex -FOREACHfacet_i_(facets) iterate over facets by facet_i and facet_n -FOREACHneighbor_i_(facet) iterate over facet->neighbors by neighbor_i, neighbor_n -FOREACHvertex_i_(vertices) iterate over vertices by vertex_i, vertex_n -FOREACHpoint_i_(points) iterate over points by point_i, point_n -FOREACHridge_i_(ridges) iterate over ridges by ridge_i, ridge_n -FOREACHadjacent_i_(vertex) iterate over adjacents by adjacent_i, adjacent_n -FOREACHneighbor_i_(vertex) iterate over vertex->neighbors by neighbor_i, neighbor_n WARNING: nested loops can't use the same variable (define another FOREACH) WARNING: strange behavior if don't fully brace when nested (including intervening blocks, e.g. FOREACH...{ if () FOREACH...} ) poly.h defines other FOREACH/FORALL macros set.h defines FOREACHsetelement and contains additional notes */ #define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next) #define FORALLpoints FORALLpoint_(qh first_point, qh num_points) #define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next) #define FORALLpoint_(points, num) for(point= (points), \ pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim) #define FOREACHfacet_(facets) FOREACHsetelement_(facetT, facets, facet) #define FOREACHneighbor_(facet) FOREACHsetelement_(facetT, facet->neighbors, neighbor) #define FOREACHpoint_(points) FOREACHsetelement_(pointT, points, point) #define FOREACHridge_(ridges) FOREACHsetelement_(ridgeT, ridges, ridge) #define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex) #define FOREACHadjacent_(vertex) FOREACHsetelement_(vertexT, vertex->adjacencies, adjacent) #define FOREACHfacet_i_(facets) FOREACHsetelement_i_(facetT, facets, facet) #define FOREACHneighbor_i_(facet) FOREACHsetelement_i_(facetT, facet->neighbors, neighbor) #define FOREACHpoint_i_(points) FOREACHsetelement_i_(pointT, points, point) #define FOREACHridge_i_(ridges) FOREACHsetelement_i_(ridgeT, ridges, ridge) #define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex) /* ======= -functions =========== see corresponding .c file for definitions Qhull functions (see qhull.c and qhull_a.h) -qhull construct the convex hull of a set of points -addpoint add point to hull (must be above facet) -delpoint delete vertex for point from hull User redefinable functions (see user.c) -errexit return exitcode to system after an error -errprint print erroneous facets, ridge, and vertex -printfacetlist print all fields for a list of facets -user_memsizes define up to 10 additional quick allocation sizes Geometric functions (see geom.c and geom.h, other useful functions) -gram_schmidt implements Gram-Schmidt orthogonalization by rows -projectinput project input along one or more dimensions + Delaunay projection -randommatrix generate a random dimXdim matrix in range (-1,1) -rotatepoints rotate numpoints points by a row matrix -scaleinput scale input to new lowbound and highbound -findbest find visible facet for a point starting at a facet Global init/free functions (see global.c and qhull_a.h) -freeqhull free memory used by qhull -init_qhull_command build qhull_command from argc/argv -initflags set flags and initialized constants from command line -initqhull_buffers initialize global memory buffers -initqhull_globals initialize globals -initqhull_mem initialize mem.c for qhull -initqhull_start start initialization of qhull -initthresholds set thresholds for printing and scaling from command line -restore_qhull restores a saved qhull -save_qhull saves qhull for later restoring Input/output functions (see io.c and io.h) -readpoints read points from input Polyhedron functions (see poly.c) -check_output check output data structure according to user flags -check_points verify that all points are inside the hull -point return point for a point id, or NULL if unknown -pointid return id for a point, or -1 if not known -facetvertices returns temporary set of vertices in a set of facets -pointfacet return temporary set of facets indexed by point id -pointvertex return temporary set of vertices indexed by point id */ /********* -qhull.c prototypes (duplicated from qhull_a.h) ***************/ void qh_qhull (void); boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist); boolT qh_delpoint (pointT *point, facetT *facet); /***** -geom.c prototypes (duplicated from geom.h) ****************/ facetT *qh_findbest (pointT *point, facetT *facet, boolT bestoutside, unsigned firstid, realT *dist, boolT *isoutside, int *numpart); boolT qh_gram_schmidt(int dim, realT **rows); void qh_projectinput (void); void qh_randommatrix (realT *buffer, int dim, realT **row); void qh_rotateinput (realT **rows); void qh_scaleinput (void); /***** -global.c prototypes (alphabetical) ***********************/ void qhull_fatal(int); void qh_freebuffers (void); void qh_freeqhull (boolT allmem); void qh_init_qhull_command (int argc, char *argv[]); void qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc); void qh_initflags (char *command); void qh_initqhull_buffers (void); void qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc); void qh_initqhull_mem (void); void qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile); void qh_initthresholds (char *command); #if qh_QHpointer void qh_restore_qhull (qhT **oldqh); qhT *qh_save_qhull (void); #endif /**************************************************************************/ /****************** some definitions from qhull_a.h ***********************/ /**************************************************************************/ /********* -poly.c prototypes (duplicated from poly.h) **********************/ void qh_check_output (void); void qh_check_points (void); setT *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets); pointT *qh_point (int id); setT *qh_pointfacet (void /*qh.facet_list*/); int qh_pointid (pointT *point); setT *qh_pointvertex (void /*qh.facet_list*/); /********* -stat.c prototypes (duplicated from stat.h) **********************/ void qh_collectstatistics (void); void qh_freestatistics (void); void qh_initstatistics (void); void qh_printallstatistics (FILE *fp, char *string); void qh_printstatistics (FILE *fp, char *string); /* ======= -constants- ====================== System dependent constants -SECticks ticks per second from clock() -RANDOMmax maximum random number and random generator, default is random() Memory constants for calling qh_meminitbuffers in global.c -MEMalign memory alignment (see mem.h). If using gcc, best alignment is #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *)) -MEMbufsize memory buffer size -MEMinitbuf initial memory buffer size. It should hold enough facets to keep outsidesets in short memory. -HASHfactor total hash slots / used hash slots -VERIFYdirect verify all points against all facets if op count smaller -MAXrandom maximum random number -ORIENTclock true if clockwise orientation on output Conditional compilation -KEEPstatistics 1 removes most of statistic gathering and reporting it reduces code by about 8%, time is the same. -QUICKhelp use abbreviated help messages for degenerate inputs -UNIX true if compiling for UNIX */ #define qh_SECticks 1E6 /* CLOCKS_PER_SECOND for clock() */ #if 0 /* use 1 if your compiler supports random(), otherwise use 0 */ /* #define qh_RANDOMmax ((realT)0x7fffffffUL) */ /* 31 bits, random()/MAX */ #define qh_RANDOMint random() #define qh_RANDOMseed_(seed) srandom(seed); #else /* #define qh_RANDOMmax ((realT)32767) */ /* 15 bits (System 5) */ #define qh_RANDOMmax 2147483647 /* Kludge added, ignorantly, by AMM */ /* WARNING: Sun produces 31 bits from rand() */ #define qh_RANDOMint rand() #define qh_RANDOMseed_(seed) srand((unsigned)seed); #endif #define qh_MEMalign fmax_(sizeof(realT), sizeof(void *)) #define qh_MEMbufsize 0x8000 /* allocate 32K memory buffers */ #define qh_MEMinitbuf 0x10000 /* initially allocate 64K buffer */ #define qh_HASHfactor 2 /* (int) at worst 50% occupancy for qh hash_table and normally 25% occupancy */ #define qh_VERIFYdirect 100000 /* if more tests, use qh_findbest instead */ #define qh_ORIENTclock 0 /* counter clockwise for Geomview inward */ #define qh_KEEPstatistics 1 /* 0 to take out statistics */ #define qh_QUICKhelp 0 /* 1 for short help messages */ #define qh_UNIX 1 /* 1 if compiling for UNIX */ /**************************************************************************/ /************** definitions and signatures from mem.h *********************/ /**************************************************************************/ /* to avoid bus errors, memory allocation must consider alignment requirements. malloc() automatically takes care of alignment. Since mem.c manages its own memory, we need to explicitly specify alignment in qh_meminitbuffers(). A safe choice is sizeof(double). sizeof(float) may be used if doubles do not occur in data structures and pointers are the same size. Be careful of machines (e.g., DEC Alpha) with large pointers. If gcc is available, use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)). see qhull_a.h for qhull's alignment */ #define qhmem_ERRmem 4 /* matches qh_ERRmem in qhull.h */ #define qhmem_ERRqhull 5 /* matches qh_ERRqhull in qhull.h */ /*--------------------------------------- -qhmemT - global memory structure for mem.c users should ignore qhmem except for writing extensions qhmem could be swapable like qh and qhstat, but then multiple qh's and qhmem's would need to keep in synch. A swapable qhmem would also waste memory buffers. As long as memory operations are atomic, there is no problem with multiple qh structures being active at the same time. If you need separate address spaces, you can swap the contents of qhmem. */ typedef struct qhmemT qhmemT; extern qhmemT qhmem; /* allocated in mem.c */ struct qhmemT { /* global memory management variables */ int BUFsize; /* size of memory allocation buffer */ int BUFinit; /* initial size of memory allocation buffer */ int TABLEsize; /* actual number of sizes in free list table */ int NUMsizes; /* maximum number of sizes in free list table */ int LASTsize; /* last size in free list table */ int ALIGNmask; /* worst-case alignment, must be 2^n-1 */ void **freelists; /* free list table, linked by offset 0 */ int *sizetable; /* size of each freelist */ int *indextable; /* size->index table */ void *curbuffer; /* current buffer, linked by offset 0 */ void *freemem; /* free memory in curbuffer */ int freesize; /* size of free memory in bytes */ void *tempstack; /* stack of temporary memory, managed by users */ FILE *ferr; /* file for reporting errors */ int IStracing; /* =5 if tracing memory allocations */ int cntquick; /* count of quick allocations */ /* remove statistics doesn't effect speed */ int cntshort; /* count of short allocations */ int cntlong; /* count of long allocations */ int curlong; /* current count of inuse, long allocations */ int freeshort; /* count of short memfrees */ int freelong; /* count of long memfrees */ int totshort; /* total size of short allocations */ int totlong; /* total size of long allocations */ int maxlong; /* maximum totlong */ int cntlarger; /* count of setlarger's */ int totlarger; /* total copied by setlarger */ }; /* ======= -macros =========== qh_memalloc_(size, freelistp, object) returns object of size bytes assumes size<=qhmem.LASTsize and void **freelistp is a temp qh_memfree_(object, size, freelistp) free up quick object object may be NULL assumes size<=qhmem.LASTsize and void **freelistp is a temp */ #define qh_memalloc_(size, freelistp, object) {\ freelistp= (void **)(qhmem.freelists + qhmem.indextable[size]);\ if ((object= (setT *)*freelistp)) {\ qhmem.cntquick++; \ *freelistp= *((void **)*freelistp);\ }else object= (setT *)qh_memalloc (size);} #define float_qh_memalloc_(size, freelistp, object) {\ freelistp= (void **)(qhmem.freelists + qhmem.indextable[size]);\ if ((object= (float *)*freelistp)) {\ qhmem.cntquick++; \ *freelistp= *((void **)*freelistp);\ }else object= (float *)qh_memalloc (size);} #define facetT_qh_memalloc_(size, freelistp, object) {\ freelistp= (void **)(qhmem.freelists + qhmem.indextable[size]);\ if ((object= (facetT *)*freelistp)) {\ qhmem.cntquick++; \ *freelistp= *((void **)*freelistp);\ }else object= (facetT *)qh_memalloc (size);} #define ridgeT_qh_memalloc_(size, freelistp, object) {\ freelistp= (void **)(qhmem.freelists + qhmem.indextable[size]);\ if ((object= (ridgeT *)*freelistp)) {\ qhmem.cntquick++; \ *freelistp= *((void **)*freelistp);\ }else object= (ridgeT *)qh_memalloc (size);} #define mergeT_qh_memalloc_(size, freelistp, object) {\ freelistp= (void **)(qhmem.freelists + qhmem.indextable[size]);\ if ((object= (mergeT *)*freelistp)) {\ qhmem.cntquick++; \ *freelistp= *((void **)*freelistp);\ }else object= (mergeT *)qh_memalloc (size);} #define qh_memfree_(object, size, freelistp) {\ if (object) { \ qhmem .freeshort++;\ freelistp= qhmem.freelists + qhmem.indextable[size];\ *((void **)object)= *freelistp;\ *freelistp= object;}} /* ======= -functions =========== see mem.c for definitions User level functions -memalloc allocate memory -memfree free memory -memstatistics print memory statistics Initialization and termination functions -meminit initialize memory -meminitbuffers initialize memory buffers -memsize define a free list for a size -memsetup set up memory (activates memalloc/free) -memfreeshort free up all memory buffers */ /*---------- -prototypes in alphabetical order -----------*/ void *qh_memalloc(int insize); void qh_memfree (void *object, int size); void qh_memfreeshort (int *curlong, int *totlong); void qh_meminit (FILE *ferr); void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit); void qh_memsetup (void); void qh_memsize(int size); void qh_memstatistics (FILE *fp); /**** end mem.h ****/ /**************************************************************************/ /************** definitions and signatures from set.h *********************/ /**************************************************************************/ /* ---------------------------------------------- -constants and flags */ #define SETelemsize sizeof(void *) /* specifies size of set element in bytes */ /* ================= -structures- =============== */ #ifndef DEFsetT #define DEFsetT 1 typedef struct setT setT; /* a set is a sorted or unsorted array of pointers */ #endif /* ---------------------------------------------- -setT- a set of anything */ struct setT { unsigned int maxsize; /* maximum number of elements (except NULL) */ void *e[1]; /* array of pointers, tail is NULL */ /* last slot (unless NULL) is actual size+1 e[maxsize]==NULL or e[e[maxsize]-1]==NULL */ }; /* =========== -macros- ========================= */ /*----------------------------------------------- -FOREACHsetelement_(type, set, variable)- define FOREACH iterator variable is NULL at end of loop assumes *variable and **variablep are declared variablep is one beyond variable. to repeat an element, variablep--; / *repeat* / use FOREACHsetelement_i_() if need index or include NULLs WARNING: strange behavior if don't use braces when nested -FOREACHsetelement_i_(type, set, variable)- define FOREACH iterator assumes *variable, variable_n, and variable_i are declared variable_i is index, variable_n is qh_setsize() variable may be NULL inside looop variable is NULL at end of loop variable_i--; variable_n-- repeats for deleted element -FOREACHsetelementreverse_ same as FOREACHsetelement but returns elements in reverse order uses 'int variabletemp' -FOREACHsetelementreverse12_ same as FOREACHsetelement but returns e[1], e[0], e[2], e[3], -FOREACHelem_(set)- for each element in a set of elements -FOREACHset_(sets)- for each set in a set of sets -SETindex_(set,elem)- returns index for iterated elem in set */ #define FOREACHsetelement_(type, set, variable) \ if (set || (variable= NULL)) for(\ variable##p= (type **)&((set)->e[0]); \ (variable= *variable##p++);) #define FOREACHsetelement_i_(type, set, variable) \ if (set || (variable= NULL)) for (\ variable##_i= 0, variable= (type *)((set)->e[0]), \ variable##_n= qh_setsize(set);\ variable##_i < variable##_n;\ variable= (type *)((set)->e[++variable##_i]) ) #define FOREACHsetelementreverse_(type, set, variable) \ if (set || (variable= NULL)) for(\ variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\ variable; variable= \ ((--variable##temp >= 0) ? SETelem_(set, variable##temp) : NULL)) #define FOREACHsetelementreverse12_(type, set, variable) \ if (set || (variable= NULL)) for(\ variable##p= (type **)&((set)->e[1]); \ (variable= *variable##p); \ variable##p == ((type **)&((set)->e[0]))?variable##p += 2: \ (variable##p == ((type **)&((set)->e[1]))?variable##p--:variable##p++)) #define FOREACHelem_(set) FOREACHsetelement_(void, set, elem) #define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set) #define SETindex_(set, elem) ((void **)elem##p - (void **)&(set)->e[1]) /*----------------------------------------------- -SETelem_(set, n)- return the n'th element of set assumes that n is valid [0..size] and that set is defined may need a type cast -SETelemaddr_(set, n, type)-return address of the n'th element of a set assumes that n is valid [0..size] and set is defined -SETfirst_(set)- return first element of set -SETsecond_(set)- return second element of set -SETaddr_(set, type)- return address of set's elements */ #define SETelem_(set, n) ((set)->e[n]) #define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n]))) #define SETfirst_(set) ((set)->e[0]) #define SETsecond_(set) ((set)->e[1]) #define SETaddr_(set,type) ((type **)(&((set)->e[0]))) /*----------------------------------------------- -SETreturnsize_(set, size) - return size of a set set must be defined use qh_setsize(set) unless speed is critical -SETempty_(set) - return true (1) if set is empty set may be NULL */ #define SETreturnsize_(set, size) (((size)= (long)((set)->e[(set)->maxsize]))?(--(size)):((size)= (set)->maxsize)) #define SETempty_(set) (!set || (SETfirst_(set) ? 0:1)) /* ======= -functions =========== see set.c for function definitions Add functions -setaddsorted adds an element to a sorted set -setaddnth adds newelem as n'th element of sorted or unsorted set -setappend appends an element to a set -setappend_set appends a set to a set -setappend2ndlast makes newelem the next to the last element in set -setlarger returns a larger set that contains elements of *setp -setreplace replaces oldelem in set with newelem -setunique add an element if not already in set Access and predicate functions -setin returns 1 if setelem is in a set, 0 otherwise -setindex returns the index of elem in set. If none, returns -1 -setlast return last element of set or NULL -setequal returns 1 if two sorted sets are equal, otherwise returns 0 -setequal_except returns 1 if two sorted sets are equal except at element -setequal_skip returns 1 if two sorted sets are equal except for skips Delete functions -setdel deletes oldelem from unsorted set. -setdelsorted deletes oldelem from sorted set -setdelnth delete and return nth element from unsorted set -setdelnthsorted delete and return nth element from sorted set -setdellast delete and return last element from set or NULL -setnew_delnthsorted create a sorted set not containing nth element Allocation and deallocation functions -setnew create a new set -setfree free the space occupied by a sorted or unsorted set -setfreelong frees a set only if it's in long memory Temporary set functions -settemp return a stacked, temporary set -settempfree free temporary set at top of qhmem.tempstack -settemppop pop qhmem.tempstack (makes temporary set permanent) -settemppush push temporary set unto qhmem.tempstack (makes it temporary) -settempfree_all free all temporary sets in qhmem.tempstack Other functions -setsize returns the size of a set -setcopy copies a sorted or unsorted set into another -setcheck check set for validity -setprint print set elements to fp -settruncate truncate set to size elements -setzero zero remainder of set and set to maximum size */ /*---------- -prototypes in alphabetical order -----------*/ void qh_setaddsorted(setT **setp, void *elem); void qh_setaddnth(setT **setp, int nth, void *newelem); void qh_setappend(setT **setp, void *elem); void qh_setappend_set(setT **setp, setT *setA); void qh_setappend2ndlast(setT **setp, void *elem); void qh_setcheck(setT *set, char */* typename: GIVES ERROR */, int id); setT *qh_setcopy(setT *set, int extra); void *qh_setdel(setT *set, void *elem); void *qh_setdellast(setT *set); void *qh_setdelnth(setT *set, int nth); void *qh_setdelnthsorted(setT *set, int nth); void *qh_setdelsorted(setT *set, void *newelem); int qh_setequal(setT *setA, setT *setB); int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB); int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB); void qh_setfree(setT **set); void qh_setfreelong(setT **set); int qh_setin(setT *set, void *setelem); int qh_setindex(setT *set, void *setelem); void qh_setlarger(setT **setp); void *qh_setlast(setT *set); setT *qh_setnew(int size); setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend); void qh_setprint(FILE *fp, char* string, setT *set); void qh_setreplace(setT *set, void *oldelem, void *newelem); int qh_setsize(setT *set); setT *qh_settemp(int setsize); void qh_settempfree(setT **set); void qh_settempfree_all(void); setT *qh_settemppop(void); void qh_settemppush(setT *set); void qh_settruncate (setT *set, int size); int qh_setunique (setT **set, void *elem); void qh_setzero (setT *set, int index, int size); /**** end set.h ****/ /**************************************************************************/ /************** definitions and signatures from geom.h ********************/ /**************************************************************************/ /* ============ -macros- ======================== */ /*---------------------------------------------- -fabs_(a) returns the absolute value of a -fmax_(a,b) returns the maximum value of a and b -fmin_(a,b) returns the minimum value of a and b -maximize_(maxval, val) sets maxval to val if greater -minimize_(minval, val) sets minval to val if less */ #define fabs_(a) (((a) < 0) ? -(a):(a)) #define fmax_(a,b) ( (a) < (b) ? (b) : (a) ) #define fmin_(a,b) ( (a) > (b) ? (b) : (a) ) #define maximize_(maxval, val) {if ((maxval) < (val)) (maxval)= (val);} #define minimize_(minval, val) {if ((minval) > (val)) (minval)= (val);} /*----------------------------------------------- -det2_(a1, a2, 2-d determinate b1, b2) -det3_(a1, a2, a3, 3-d determinate b1, b2, b3, c1, c2, c3) */ #define det2_(a1,a2,b1,b2) ((a1)*(b2) - (a2)*(b1)) #define det3_(a1,a2,a3,b1,b2,b3,c1,c2,c3) ( (a1)*det2_(b2,b3,c2,c3) \ - (b1)*det2_(a2,a3,c2,c3) + (c1)*det2_(a2,a3,b2,b3) ) /*----------------------------------------------- -dX, dY, dZ- coordinate differences given row pointers rows[] */ #define dX(p1,p2) (*(rows[p1]) - *(rows[p2])) #define dY(p1,p2) (*(rows[p1]+1) - *(rows[p2]+1)) #define dZ(p1,p2) (*(rows[p1]+2) - *(rows[p2]+2)) #define dW(p1,p2) (*(rows[p1]+3) - *(rows[p2]+3)) /* ======= -functions =========== see geom.c for definitions Geometric functions -crossproduct compute the cross product of 2 3-d vectors -determinant compute the determinant of a square matrix -detsimplex return determinate of a simplex of points -divzero divide by a number that's nearly zero -gausselim Gaussian elimination with partial pivoting -getangle return cosine of angle (dot product of two qh hull_dim vectors) -gram_schmidt implements Gram-Schmidt orthogonalization by rows -inthresholds return True if normal within qh lower_/upper_threshold -maxabsval return max absolute value of a vector -maxsimplex determines maximum simplex for a set of points -minabsval return min absolute value of a dim vector -normalize normalize a vector -pointdist return distance between two points -printmatrix print matrix given by row vectors -printpoints print pointids for a set of points starting at index -projectpoints project points along one or more dimensions -randomfactor return a random factor within qh RANDOMdistmax of 1.0 -randommatrix generate a random dimXdim matrix in range (-1,1) -rotatepoints rotate numpoints points by a row matrix -scalepoints scale points to new lowbound and highbound -sethyperplane_det return hyperplane for oriented simplex, uses determinates -sethyperplane_gauss return hyperplane for oriented simplex, uses Gaussian elimination -voronoi_center return Voronoi center for a set of points Qhull's geometric functions -backnormal solve for normal x using back substitution over rows U -distplane return distance from point to facet (>0 if point is above facet) -facetcenter return Voronoi center for a facet's vertices -findbest find visible facet for a point starting at a facet -findgooddist find best good facet visible for point from facet -getcenter return arithmetic center of a set of vertices -getcentrum return centrum for a facet -maxmin return max/min points for each dim., sets max roundoff errors -orientoutside make facet outside oriented via qh interior_point -projectinput project input using qh DELAUNAY and qh low_bound/high_bound -projectpoint project point onto a facet by distance -rotateinput rotate input using row matrix -scaleinput scale input using qh low_bound/high_bound -setfacetplane sets the hyperplane for a facet */ /*---------- -prototypes in alphabetical order -----------*/ void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero); void qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]); realT qh_determinant (realT **rows, int dim, boolT *nearzero); realT qh_detsimplex (pointT *apex, setT *points, int dimension, boolT *nearzero); void qh_distplane (pointT *point, facetT *facet, realT *dist); realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv); pointT *qh_facetcenter (setT *vertices); facetT *qh_findbest (pointT *point, facetT *facet, boolT bestoutside, unsigned firstid, realT *dist, boolT *isoutside, int *numpart); facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp); void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero); realT qh_getangle(pointT *vect1, pointT *vect2); pointT *qh_getcenter(setT *vertices); pointT *qh_getcentrum(facetT *facet); boolT qh_gram_schmidt(int dim, realT **rows); boolT qh_inthresholds (coordT *normal, realT *angle); realT *qh_maxabsval (realT *normal, int dim); setT *qh_maxmin(pointT *points, int numpoints, int dimension); void qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex); realT qh_minabsval (realT *normal, int dim); void qh_normalize (coordT *normal, int dim, boolT toporient); boolT qh_orientoutside (facetT *facet); coordT qh_pointdist(pointT *point1, pointT *point2, int dim); void qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol); void qh_printpoints (FILE *fp, char *string, setT *points); void qh_projectinput (void); pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist); void qh_projectpoints (signed char *project, int n, realT *points, int numpoints, int dim, realT *newpoints, int newdim); realT qh_randomfactor (void); void qh_randommatrix (realT *buffer, int dim, realT **row); void qh_rotateinput (realT **rows); void qh_rotatepoints (realT *points, int numpoints, int dim, realT **rows); void qh_scaleinput (void); void qh_scalepoints (pointT *points, int numpoints, int dim, realT *newlows, realT *newhighs); void qh_setfacetplane(facetT *newfacets); void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, boolT toporient, coordT *normal, realT *offset); void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, boolT toporient, coordT *normal, coordT *offset, boolT *nearzero); pointT *qh_voronoi_center (int dim, setT *points); /**** end geom.h ****/ /**************************************************************************/ /************** definitions and signatures from merge.h *******************/ /**************************************************************************/ /* ============ -constants- ==================== -BESTcentrum if > dim+n vertices, findbestneighbor tests centrums (faster) else, findbestneighbor test all vertices (much better merges) -BESTnonconvex if > dim*n neighbors, findbestneighbor tests nonconvex ridges needed because findbestneighbor is slow for large facets -MAXnewmerges if >n newmerges, merge_nonconvex calls reducevertices_centrums needed because postmerge can merge many facets at once -MAXnewcentrum if <= dim+n vertices (n approximates the number of merges), reset the centrum in reducevertices_centrum needed to reduce cost and because centrums may move too much if many vertices in high-d */ #define qh_BESTcentrum 20 /* findbestneighbor tests centrum or vertices */ #define qh_BESTnonconvex 5 /*findbestneighbor only tests nonconvex */ #define qh_MAXnewmerges 2 /*merge_nonconvex calls reducevertices_centrums*/ #define qh_MAXnewcentrum 5 /*reducevertices_centrums resets centrum */ #define qh_ANGLEredundant 6.0 /* angle for redundant merge in mergeT */ #define qh_ANGLEdegen 5.0 /* angle for degenerate facet in mergeT */ #define qh_ANGLEconcave 1.5 /* [2,4] for angle of concave facets in mergeT, may be <2 or >4 due to roundoff */ /* ============ -structures- ==================== */ /* ---------------------------------------------- -mergeT- structure used to merge facets */ typedef struct mergeT mergeT; struct mergeT { realT angle; /* angle between normals of facet1 and facet2 */ facetT *facet1; facetT *facet2; flagT mergeridge:1; /* set if merge due to qh_MERGEridge */ flagT newmerge:1; /* set if new merge, for forcedmerges() */ flagT anglecoplanar:1; /* set if merge due to qh cos_max */ }; /* =========== -macros- ========================= -FOREACHmerge- if qh_mergefacet() then must restart since facet_mergeset may change. */ #define FOREACHmerge_(merges) FOREACHsetelement_(mergeT, merges, merge) /* ======= -functions and procedures- =========== top-level merge functions -merge_nonconvex merges all nonconvex facets -flippedmerges merge flipped facets into best neighbor -forcedmerges merge across duplicated ridges and mutually flipped facets -tracemerging print trace message during post merging mergeset functions for identifying merges -getmergeset_initial initial mergeset for facets -getmergeset returns facet_mergeset of facet-neighbor pairs to be merged -degen_redundant_neighbors append degen. and redundant neighbors to facet_mergeset -test_appendmerge facet/neighbor and appends to mergeset if nonconvex -appendmergeset appends an entry to facet_mergeset, angle is optional -facetdegen true if facet already in mergeset as a degenerate functions for determining the best merge -findbest_test test neighbor for findbestneighbor() -findbestneighbor finds best neighbor (least dist) of a facet for merging -getdistance returns the max and min distance of any vertex from neighbor functions for merging facets -merge_degenredundant merge degenerate and redundant facets -mergefacet merges facet1 into facet2 -makeridges creates explicit ridges between simplicial facets -mergeneighbors merges the neighbors of facet1 into facet2 -mergeridges merges the ridge set of facet1 into facet2 -mergevertex_neighbors merge the vertex neighbors of facet1 to facet2 -mergevertices merges the vertex set of facet1 into facet2 -mergevertices2d merges vertices1 into vertices2 in 2-d case functions for renaming a vertex -reducevertices_centrums reduce vertex sets and reset centrums -rename_sharedvertex detect and rename if shared vertex in facet -redundant_vertex returns true if detect and rename redundant vertex -renamevertex renames oldvertex as newvertex in ridges -renameridgevertex renames oldvertex as newvertex in ridge -maydropneighbor drop neighbor relationship if no ridge between facet and neighbor -remove_extravertices remove extra vertices in non-simplicial facets -copynonconvex- copy non-convex flag to all ridges between same neighbors functions for identifying vertices for renaming -find_newvertex locate new vertex for renaming old vertex -neighbor_intersections return intersection for vertex->neighbors -vertexridges return temporary set of ridges adjacent to a vertex -vertexridges_facet add adjacent ridges for vertex in facet -hashridge add ridge to hashtable without oldvertex -hashridge_find returns matching ridge in hashtable without oldvertex check functions -checkridge_boundary checks that ridges of a facet are boundaryless */ /*---------- -prototypes in alphabetical order -----------*/ mergeT *qh_appendmergeset(facetT *facet, facetT *neighbor, realT *angle); void qh_checkridge_boundary(facetT *facet); void qh_copynonconvex (ridgeT *atridge); void qh_degen_redundant_neighbors (facetT *facet); boolT qh_facetdegen (facetT *facet); vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges); void qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor, facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp); facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp); void qh_flippedmerges(facetT *facetlist); void qh_forcedmerges(facetT *facetlist); realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist); void qh_getmergeset(facetT *facetlist); void qh_getmergeset_initial (facetT *facetlist); void qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex); ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *vertex, vertexT *oldvertex, int *hashslot); void qh_makeridges(facetT *facet); void qh_maydropneighbor (facetT *facet); boolT qh_merge_degenredundant (facetT *facet1, facetT *facet2, realT *angle); void qh_merge_nonconvex(void /*newfacet_list*/); void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, realT *angle); void qh_mergeneighbors(facetT *facet1, facetT *facet2); void qh_mergeridges(facetT *facet1, facetT *facet2); void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2); void qh_mergevertices(setT *vertices1, setT **vertices); void qh_mergevertices2d(setT *vertices1, setT *vertices2); setT *qh_neighbor_intersections (vertexT *vertex); boolT qh_reducevertices_centrums (void); vertexT *qh_redundant_vertex (vertexT *vertex); boolT qh_remove_extravertices (facetT *facet); vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet); void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex); void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA); boolT qh_test_appendmerge (facetT *facet, facetT *neighbor); void qh_tracemerging (char *string); setT *qh_vertexridges (vertexT *vertex); void qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges); /**** end merge.h ****/ /**************************************************************************/ /************** definitions and signatures from poly.h ********************/ /**************************************************************************/ /*----------------------------------------------- -constants- for calling checkconvex() -ALGORITHMfault flag for checkconvex for error during buildhull -DATAfault flag for checkconvex for error during initialhull set by matchneighbor, used by matchmatch and forcedmerges -DUPLICATEridge flag in facet->neighbors to indicate duplicated ridge -MERGEridge flag in facet->neighbors to indicate merged ridge */ #define qh_ALGORITHMfault 0 #define qh_DATAfault 1 #define qh_DUPLICATEridge (facetT *) 1 #define qh_MERGEridge (facetT *) 2 /* ============ -structures- ==================== */ /* ---------------------------------------------- -hashentryT- hash table entry for matching sub-ridges in makecone() */ typedef struct hashentryT hashentryT; struct hashentryT { facetT *facet; /* facet */ hashentryT *next; /* next hash table entry for this bucket */ unsigned skipindex; /* skipped vertex in facet, for orientation */ }; /* =========== -macros- ========================= */ /* ---------------------------------------------- -FOREACH... and FORALL... -- standard for loops see qhull.h for notes */ #define FORALLfacet_(facetlist) if (facetlist) for(facet=(facetlist);facet && facet->next;facet=facet->next) #define FORALLnew_facets for(newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next) #define FORALLvertex_(vertexlist) for (vertex=(vertexlist);vertex && vertex->next;vertex= vertex->next) #define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next) #define FOREACHentry_(entries) FOREACHsetelement_(hashentryT, entries, entry) #define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible) #define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet) #define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA) #define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex) /* ======= -functions =========== see poly.c for definitions Facetlist functions -appendfacet appends facet to end of qh facet_list, -prependfacet prepends facet to start of facetlist -removefacet unlinks facet from qh facet_list, -clearvisible clear facets from visible list Facet functions -createsimplex creates a simplex of facets from a set of vertices -makenewfacet creates a toporient? facet from vertices and apex -makenewfacets make new facets from point, horizon facets, and visible facets -makenew_nonsimplicial make new facets for ridges of visible facets -makenew_simplicial make new facets for horizon neighbors -attachnewfacets attach new facets in qh newfacet_list to the horizon -makeadjacencies make adjacencies for non-simplicial facets Vertex, ridge, and point functions -appendvertex appends vertex to end of qh vertex_list, -removevertex unlinks vertex from qh vertex_list, -clearnewvertices clear vertices from qh newvertex_list -point return point for a point id, or NULL if unknown -pointid return id for a point, or -1 if not known -vertexintersect intersects two vertex sets -vertexintersect_new intersects two vertex sets -facetintersect intersect simplicial facets -isvertex true if point is in the vertex set -vertexsubset returns True if vertexsetA is a subset of vertexsetB -nextridge3d iterate each ridge and vertex for a 3d facet -facet3vertex return oriented vertex set for 3-d facet -vertexneighhbors for each vertex in hull, determine facet neighbors -pointfacet return temporary set of facets indexed by point id -pointvertex return temporary set of vertices indexed by point id Hashtable functions -newhashtable allocates a new qh hash_table -gethash return hashvalue for a set with firstindex -matchnewfacets match newfacets in to their newfacet neighbors -matchneighbor try to match subridge of newfacet with a neighbor -matchduplicate try to match an unmatched duplicate ridge -matchmatch try to match duplicate matching pair and newfacet -matchvertices tests whether a facet and hashentry match at a ridge -printhashtable print hash table Allocation and deallocation functions -newfacet creates and allocates space for a facet -newridge creates and allocates space for a ridge -newvertex creates and allocates space for a vertex -deletevisible delete visible facets and related structures -delfacet frees up the memory occupied by a facet -delridge deletes ridge from data structures it belongs to and frees up the -delvertex deletes vertex and its memory -clearcenters clear old data from facet->center Check functions -check_bestdist check that points are not outside their best facet -check_maxout updates max_outside, checks all points against bestfacet -check_output performs the checks at the end of qhull algorithm -check_point check that point is not outside facet -check_points checks that all points are inside all facets -checkconvex check that each ridge in facetlist is convex -checkfacet checks for consistency errors in facet -checkflipped checks facet orientation to the interior point -checkflipped_all checks facet orientation for a facet list -checkpolygon checks the correctness of the structure -checkvertex check vertex for consistency -printlists print out facet list for debugging */ /*---------- -prototypes in alphabetical order -----------*/ void qh_appendfacet(facetT *facet); void qh_appendvertex(vertexT *vertex); void qh_attachnewfacets (void); void qh_check_bestdist (); void qh_check_maxout (void); void qh_check_output (void); void qh_check_point (pointT *point, facetT *facet, realT *maxoutside, facetT **errfacet1, facetT **errfacet2); void qh_check_points(void); void qh_checkconvex(facetT *facetlist, int fault); void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp); boolT qh_checkflipped (facetT *facet, realT *dist, boolT allerror); void qh_checkflipped_all (facetT *facetlist); void qh_checkpolygon(facetT *facetlist); void qh_checkvertex (vertexT *vertex); void qh_clearcenters (int type); void qh_clearvisible (void /*qh visible_list*/); void qh_clearnewvertices (void /*qh newvertex_list*/); void qh_createsimplex(setT *vertices); int qh_degeneratematch(facetT *facet, setT *vertices, int skipindex); void qh_deletevisible(/*qh visible_list, qh horizon_list*/); void qh_delfacet(facetT *facet); void qh_delridge(ridgeT *ridge); void qh_delvertex (vertexT *vertex); setT *qh_facet3vertex (facetT *facet); setT *qh_facetintersect (facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra); unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem); vertexT *qh_isvertex (pointT *point, setT *vertices); facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet); vertexT *qh_makenewfacets (pointT *point /*horizon_list, visible_list*/); facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew); facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew); boolT qh_matchduplicate (facetT *facet, int skip, facetT *newfacet, int newskip, boolT keepfound); boolT qh_matchmatch (facetT *facet, int skip, facetT *matchfacet, facetT *newfacet, int newskip, boolT ismatch, boolT *keepfound, boolT *newmatched); void qh_matchneighbor (facetT *newfacet, int newskip, int hashsize, int *hashcount, boolT matchall); void qh_matchnewfacets (); boolT qh_matchvertices (int firstindex, setT *verticesA, int skipA, setT *verticesB, int *skipB, boolT *same); int qh_newhashtable(int newsize); facetT *qh_newfacet(void); ridgeT *qh_newridge(void); vertexT *qh_newvertex(pointT *point); ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp); pointT *qh_point (int id); void qh_point_add (setT *set, pointT *point, void *elem); setT *qh_pointfacet (void /*qh facet_list*/); int qh_pointid (pointT *point); setT *qh_pointvertex (void /*qh facet_list*/); void qh_prependfacet(facetT *facet, facetT **facetlist); void qh_printhashtable(FILE *fp); void qh_printlists (void); void qh_removefacet(facetT *facet); void qh_removevertex(vertexT *vertex); void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB); setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB); void qh_vertexneighbors (void /*qh facet_list*/); boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB); /**************************************************************************/ /************** definitions and signatures from stat.h ********************/ /**************************************************************************/ #ifndef qh_KEEPstatistics #define qh_KEEPstatistics 1 #endif /*---------------------------------------------------- -statistics, Zxxx for integers, Wxxx for reals can pick up all statistics by: grep '[zw].*_[(][ZW]' *.c >z.x remove trailers with query-replace-regexp [,)].* remove leaders with query-replace-regexp [ ^I]+ ( */ #if qh_KEEPstatistics enum statistics { /* alphabetical after Z/W */ Zacoplanar, Wacoplanarmax, Wacoplanartot, Zangle, Wangle, Wanglemax, Wanglemin, Zangletests, Zavoidold, Wavoidoldmax, Wavoidoldtot, Zback0, Zbestcentrum, Zbestdist, Zcentrumtests, Zcomputefurthest, Zconcave, Wconcavemax, Wconcavetot, Zconcaveridges, Zconcaveridge, Zcoplanar, Wcoplanarmax, Wcoplanartot, Zcoplanarangle, Zcoplanarcentrum, Zcoplanarhorizon, Zcoplanarinside, Zcoplanarpart, Zcoplanarridges, Wcpu, Zdegen, Wdegenmax, Wdegentot, Zdegenvertex, Zdelfacetdup, Zdelridge, Zdetsimplex, Zdistcheck, Zdistconvex, Zdistgood, Zdistio, Zdistplane, Zdiststat, Zdoc1, Zdoc2, Zdoc3, Zdoc4, Zdoc5, Zdoc6, Zdoc7, Zdoc8, Zdoc9, Zdoc10, Zdropdegen, Zdropneighbor, Zduplicate, Wduplicatemax, Wduplicatetot, Zdupridge, Zfindvertex, Zfindfail, Zflipped, Wflippedmax, Wflippedtot, Zflippedfacets, Zgauss0, Zgoodfacet, Zhashlookup, Zhashridge, Zhashridgetest, Zhashtests, Zinsidevisible, Zintersect, Zintersectfail, Zintersectmax, Zintersectnum, Zintersecttot, Zmaxneighbors, Wmaxoutside, Zmaxridges, Zmaxvertices, Zmaxvneighbors, Zmemfacets, Zmempoints, Zmemridges, Zmemvertices, Zmergeflip, Zmergeflipdup, Zmergehorizon, Zmergeintohorizon, Zmergenew, Zmergevertex, Wmindenom, Wminvertex, Zmultiflip, Zmultimatch, Znearlysingular, Zneighbor, Wnewbalance, Wnewbalance2, Znewvertex, Wnewvertex, Wnewvertexmax, Znotgood, Znotgoodnew, Znotmax, Znumfacets, Znumneighbors, Znumridges, Znumvertices, Znumvisibility, Znumvneighbors, Zpartcoplanar, Zpartneighbor, Zpartinside, Zpartition, Zpartitionall, Zpbalance, Wpbalance, Wpbalance2, Zpostfacets, Zprocessed, Zremvertex, Zremvertexdel, Zrenameall, Zrenamepinch, Zrenameshare, Zsamevertices, Zsearchpoints, Zsetplane, Ztothorizon, Ztotmerge, Ztotpartcoplanar, Ztotpartition, Ztotridges, Ztotverify, Ztotvertices, Ztotvisible, Zverifypart, Wvertexmax, Wvertexmin, Zvertexridge, Zvertexridgetot, Zvertexridgemax, Zvertices, ZEND}; #else enum statistics { /* for zzdef etc. macros */ Zback0, Zbestdist, Zcentrumtests, Zconcaveridges, Zcoplanarhorizon, Zcoplanarpart, Zcoplanarridges, Zdistcheck, Zdistconvex, Zdoc1, Zdoc3, Zflippedfacets, Zgauss0, Zmultiflip, Zmultimatch, Znearlysingular, Znumvisibility, Zpartcoplanar, Zpartition, Zpartitionall, Zprocessed, Zsetplane, Ztotmerge, ZEND}; #endif /* ------------ -ztypes- --------------------- the type of a statistic sets its initial value. The type should be the same as the macro for collecting the statistic */ enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend}; /*------------ -macros ------------- macros: zdef_(type, name, doc, -1) define a statistic (assumes 'qhstat next= 0;') zdef_(type, name, doc, count) printed as name/count zinc_(name) integer statistic is count zadd/wadd_(name, value) integer or real statistic is total value zmax/wmax_(name, value) integer or real statistic is max value zmin/wmin_(name, value) integer or real statistic is min value zval/wval_(name) set or return value of statistic */ #define MAYdebugx /* maydebug() is called frequently to trap an error */ #define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;} #define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);} #define zzval_(id) ((qhstat stats[id]).i) #define wwval_(id) ((qhstat stats[id]).r) #define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \ qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype #if qh_KEEPstatistics #define zinc_(id) {MAYdebugx; qhstat stats[id].i++;} #define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);} #define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);} #define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));} #define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));} #define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));} #define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));} #define zval_(id) ((qhstat stats[id]).i) #define wval_(id) ((qhstat stats[id]).r) #define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \ qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype #else /* !qh_KEEPstatistics */ #define zinc_(id) #define zadd_(id, val) #define wadd_(id, val) #define zmax_(id, val) #define wmax_(id, val) #define zmin_(id, val) #define wmin_(id, val) #define zval_(id) qhstat tempi #define wval_(id) qhstat tempr #define zdef_(type,name,doc,count) #define ZMAXlevel 1 #endif /* -typedef and extern- types are defined below */ typedef struct qhstatT qhstatT; /* global data structure for statistics */ typedef union intrealT intrealT; /* union of int and realT */ #if qh_QHpointer #define qhstat qh_qhstat-> extern qhstatT *qh_qhstat; /* allocated in stat.c */ #else #define qhstat qh_qhstat. extern qhstatT qh_qhstat; /* allocated in stat.c */ #endif /*------------------------------------------- -intrealT- union of integer and real, used for statistics */ union intrealT { int i; realT r; }; /*-------------------------------------------- -qhstatT- global data structure for statistics */ struct qhstatT { intrealT stats[ZEND]; /* integer and real statistics */ unsigned char id[ZEND]; /* id's in print order */ char *doc[ZEND]; /* array of documentation strings */ short int count[ZEND]; /* -1 if none, else index of count to use */ char type[ZEND]; /* type, see ztypes above */ char printed[ZEND]; /* true, if statistic has been printed */ intrealT init[ZTYPEend]; /* initial values by types, set initstatistics */ int next; /* next index for zdef_ */ int precision; /* index for precision problems */ int tempi; realT tempr; }; /* ========== -functions- =========== see also qhull.h -freestatistics free memory used for statistics -newstats returns True if statistics for zdoc -nostatistic true if no statistic to print -stddev compute the standard deviation and average from statistics */ void qh_collectstatistics (void); void qh_freestatistics (void); void qh_initstatistics (void); boolT qh_newstats (int index, int *nextindex); boolT qh_nostatistic (int i); void qh_printallstatistics (FILE *fp, char *string); void qh_printstatistics (FILE *fp, char *string); void qh_printstatlevel (FILE *fp, int id, int start); void qh_printstats (FILE *fp, int index, int *nextindex); realT qh_stddev (int num, realT tot, realT tot2, realT *ave); /**** end stat.h ****/ /* ======= -macros- =========== */ /*----------------------------------------------- -traceN((fp.ferr, "format\n", vars)); calls fprintf if IStracing >= N removing tracing reduces code size but doesn't change execution speed */ #define trace0(args) {if (qh IStracing) fprintf args;} #define trace1(args) {if (qh IStracing >= 1) fprintf args;} #define trace2(args) {if (qh IStracing >= 2) fprintf args;} #define trace3(args) {if (qh IStracing >= 3) fprintf args;} #define trace4(args) {if (qh IStracing >= 4) fprintf args;} #define trace5(args) {if (qh IStracing >= 5) fprintf args;} /* ======= -functions =========== see corresponding .c file for definitions Qhull functions (qhull.c) -qhull construct the convex hull of a set of points -addpoint add point to hull above a facet -buildhull constructs a hull by adding points one at a time -buildtracing for tracing execution of buildhull -errexit2 return exitcode to system after an error for two facets -findgood identify good facets for qh ONLYgood -findgood_all identify good facets for qh PRINTgood -findhorizon find the horizon and visible facets for a point -initialhull construct the initial hull as a simplex of vertices -initialvertices return non-singular set of initial vertices -nextfurthest returns next furthest point for processing -partitionall partitions all points into the outsidesets of facets -partitioncoplanar partition coplanar point to a facet -partitionpoint partitions a point as inside, coplanar or outside a facet -partitionvisible partitions points in visible_list to newfacet_list Global.c internal functions (others in qhull.h) -freebuffers free up global memory buffers -initbuffers initialize global memory buffers -strtod/tol duplicates strtod/tol */ /***** -qhull.c prototypes (alphabetical after qhull) ********************/ void qh_qhull (void); boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist); void qh_buildhull(void); void qh_buildtracing (pointT *furthest, facetT *facet); void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet); int qh_findgood (facetT *facetlist, int goodhorizon); void qh_findgood_all (facetT *facetlist); void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon); void qh_initialhull(setT *vertices); setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints); pointT *qh_nextfurthest (facetT **visible); void qh_partitionall(setT *vertices, pointT *points,int npoints); void qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist); void qh_partitionpoint (pointT *point, facetT *facet); void qh_partitionvisible(boolT allpoints, int *numpoints); /***** -global.c internal prototypes (alphabetical) ***********************/ void qh_freebuffers (void); void qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc); int qh_strtol (const char *s, char **endp); double qh_strtod (const char *s, char **endp); #endif /* qhDEFqhull */ gambit-0.2010.09.01/src/tools/enumpoly/pelsymbl.cc0000644000076500007650000000670011350032206016370 00000000000000/* ** copyright (c) 1995 Birk Huber */ #include "pelsymbl.h" #define HASHSIZE 100 static Sym_ent hashtab[HASHSIZE]; /*----------------------------------------------------------------- empty_symbol_table() free all data structures on the symbol table; ------------------------------------------------------------------*/ void init_symbol_table() { int i; for(i=0;inext; free_Gen_list(np1->def); mem_free(np1->name); mem_free(np1); } } } /*------------------------------------------------------------------- hashing functiion ---------------------------------------------------------------------*/ int hash(char *s) { int hashval=0; while( *s !='\0') hashval+=*s++; return hashval % HASHSIZE; } /* ----------------------------------------------------------------- lookup takes a string and returns the value on the hashtable corresponding to the string, or returns NULL if there is no such entry ----------------------------------------------------------------- */ Sym_ent Slookup(char *s) { Sym_ent np; for(np=hashtab[hash(s)]; np!=0;np=np->next) if (strcmp(s,np->name)== 0) return(np); return 0; } /* -------------------------------------------------------------------- Sym_ent install(char *s, Gen_node t) if s is already on the symbol table and is unlocked its value is freed and replaced by t; if s is already on the symbol table and is locked a warning is printed to stderr, and NULL is returned. otherwise a new_node is created and the values for s and t are placed on the symbol table Error Conditions: if either s or t is NULL then nothing is done and NULL is returned A malloc failure in the attempt to create a newnode is treated as an unrecoverable error. --------------------------------------------------------------------*/ Sym_ent install(char *s, Gen_node t) { Sym_ent np,lookup(); int hashval; if (s==NULL||t==NULL) return NULL; if((np=Slookup(s))==NULL) { np=(Sym_ent)mem_malloc(sizeof(struct Sym_ent_tag)); if (np==NULL) bad_error("malloc bad malloc in install"); np->name=Copy_String(s); hashval=hash(np->name); np->next=hashtab[hashval]; hashtab[hashval]=np; np->lock=0; np->def=t; } else if (np->lock==0){ free_Gen_list(np->def); np->def=t; np->lock=0; } else { fprintf(stderr /* was Pel_Err */,"warning trying to reinstall a reserved symbol (%s)\n",s); return NULL; } return np; } /* --------------------------------------------------------------- Sym_ent lock(Sym_ent s) Sets lock switch on Symbol table entry so that it is marked as belonging to a reserved word (If s is NULL does nothing). return s; Int locked(Sym_ent s) Returns value of lock switch on s if s is nonNULL. If s is NULL returns 0 indicate symbol is unlocked (this case could legitimatly happen if one does try to lock the result of a lookup on a string wich has no value on the symbol table. Such a symbol is undefined and clearly should not be considered reserved). -----------------------------------------------------------------*/ Sym_ent lock(Sym_ent s) { if (s!=NULL) s->lock=1; return s;} int locked(Sym_ent s) { if (s==NULL) return 0; return s->lock;} gambit-0.2010.09.01/src/tools/enumpoly/pelsymbl.h0000644000076500007650000000244411350032206016233 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* ** copyright (c) 1995 Birk Huber */ #ifndef SYMBOL_H #define SYMBOL_H #include #include #include "pelgntyp.h" typedef struct Sym_ent_tag *Sym_ent; struct Sym_ent_tag{ char *name; Gen_node def; Sym_ent next; int lock;}; Sym_ent Slookup(char *); Gen_node Glookup(); Sym_ent install(char *s, Gen_node t); Sym_ent lock(Sym_ent s); int locked(Sym_ent s); void empty_symbol_table(); void init_symbol_table(); #endif /* SYMBOL_H */ gambit-0.2010.09.01/src/tools/enumpoly/pelutils.cc0000644000076500007650000033764311351773322016433 00000000000000/* This file contains the implementation information that had been in globals.h, and also the various implementation files that formerly resided in the Utils subdirectory of the Pelican distribution. */ #include "pelutils.h" /**************************************************************************/ /*********************** implementations from Mem.c ***********************/ /**************************************************************************/ /* ** Mem.c Created 1-27-95 Birk Huber ** ** Memory Management for Pelican Shell. ** ** Maintains storage for the basic unit of storage from which ** lists are built. ** ** A node consists of left,and right (values,type) combinations, and ** a boolean for garbage collection. The values are often pointers to ** other structures wich must be freed when nodes are freed. ** ** The Free_Stack is used to store a list of (known) free nodes, ** The Local_Stack points to a list of pointers to nodes ** which are known to be in use. ** ** Any time a new_node is requested and the Free_Stack is ** empty garbage collection is initiated. Garbage collection ** proceeds by first marking all nodes accessable from the ** Local_Stack and then putting the rest on the free list. ** ** Any time garbage collection fails node_more_store() is called ** to add another block of nodes to the pool of available nodes. ** */ #define BLOCKSIZE 10000 #define YES 0 #define NO 1 #define Node_LT(n) ((n->LT)) #define Node_L(n) ((n->L)) #define Node_RT(n) ((n->RT)) #define Node_R(n) ((n->R)) #define Node_Marked(n) ((n)->Mark) #define Node_Unset_Mark(n)((n)->Mark=NO) #define Node_Set_Mark(n)((n)->Mark=YES) static int node_gc(); /* static int mark(); */ static int node_more_store(); static node node_free(node N); struct node_t { int LT, RT, Mark; union { void *ptr; int ival; double dval; } L, R; }; /* ** */ typedef struct node_block_t *node_block; struct node_block_t { struct node_t store[BLOCKSIZE]; struct node_block_t *next; }; static int N_MALLOC = 0; /*number of mallocs called from module */ static int N_FREE = 0; /*number of frees called from this module */ static node_block Node_Store = 0; /*beginning of node storage */ static node Free_List = 0; /*top of free node list */ static local_v Locals_Stack = 0; /*stack of declared pointers into node storage */ node node_set_ptr(node N, void *v, int tp, int side) { if (N == 0) bad_error("null node to node_set_ptr"); if (side == LEFT) { N->L.ptr = v; N->LT = tp; } else if (side == RIGHT) { N->R.ptr = v; N->RT = tp; } else bad_error("bad side given in node_set_ptr"); return N; } node node_set_int(node N, int v, int tp, int side) { if (N == 0) bad_error("null node to node_set_int"); if (side == LEFT) { N->L.ival = v; N->LT = tp; } else if (side == RIGHT) { N->R.ival = v; N->RT = tp; } else bad_error("bad side given in node_set_int"); return N; } node node_set_double(node N, double v, int tp, int side) { if (N == 0) bad_error("null node to node_set_double"); if (side == LEFT) { N->L.dval = v; N->LT = tp; } else if (side == RIGHT) { N->R.dval = v; N->RT = tp; } else bad_error("bad side given in node_set_double"); return N; } int node_get_int(node N, int side) { if (N == 0) bad_error("null node to node_get_int"); if (side == LEFT) return N->L.ival; else if (side == RIGHT) return N->R.ival; bad_error("bad side given in node_get_int"); return 0; } double node_get_double(node N, int side) { if (N == 0) bad_error("null node to node_get_ptr"); if (side == LEFT) return N->L.dval; else if (side == RIGHT) return N->R.dval; bad_error("bad side given in node_get_double"); return 0; } void *node_get_ptr(node N, int side) { if (N == 0) bad_error("null node to node_get_ptr"); if (side == LEFT) return N->L.ptr; else if (side == RIGHT) return N->R.ptr; bad_error("bad side given in node_get_ptr"); return 0; } int node_set_type(node N, int Tp, int side) { if (N == 0) bad_error("null node to node_get_type"); if (side == LEFT) return N->LT; else if (side == RIGHT) return N->RT=Tp; bad_error("bad side given in node_get_type"); return 0; } int node_get_type(node N, int side) { if (N == 0) bad_error("null node to node_get_type"); if (side == LEFT) return N->LT; else if (side == RIGHT) return N->RT; bad_error("bad side given in node_get_type"); return 0; } node Cons(node N1, node N2) { node Res; LOCS(2); PUSH_LOC(N1); PUSH_LOC(N2); Res = node_new(); node_set_ptr(Res, (void *) N1, NODE, LEFT); node_set_ptr(Res, (void *) N2, NODE, RIGHT); POP_LOCS(); return Res; } node Car(node N1) { if (N1 == 0) return 0; return (node) node_get_ptr(N1, LEFT); } node Cdr(node N1) { if (N1 == 0) return 0; return (node) node_get_ptr(N1, RIGHT); } int node_atomp(node N1) { if ((N1!=0) && (node_get_type(N1, LEFT)) == NODE) return FALSE; else return TRUE; } int node_nullp(node N1) { if (N1 == 0) return TRUE; else return FALSE; } char *mem_strdup(char *str){ /* char *strdup(char *); CAN'T DECLARE BUILTINS UNDER C++ */ N_MALLOC++; return strdup(str); } void *mem_malloc(int sz) { N_MALLOC++; return (void *) malloc(sz); } void mem_free(void *ptr) { N_FREE++; free(ptr); } static node node_free(node N) { Node_LT(N) = NODE; Node_L(N).ptr = 0; Node_RT(N) = NODE; Node_R(N).ptr = Free_List; Free_List = N; return N; } /* ** storage is stored in blocks of size BLOCKSIZEg. whenever ** node_new is called and garbage collection fails to produce ** new nodes (because there is no more free storage) ** node_more_store() is called. ** It is responcible for ** a) claiming another block of nodes with malloc ** b) adding this block to the storage list ** c) putting all the new blocks on the free list. ** finally if this is the first block to be created the locals stack ** must be initialized. */ static int node_more_store() { int i; node_block next_node = 0; next_node = (node_block) malloc(sizeof(struct node_block_t)); if (next_node == 0) { #ifdef LOG_PRINT fprintf(stderr, "malloc failing in node_more_store\n") #endif ; return FALSE; } next_node->next = Node_Store; Node_Store = next_node; for (i = 0; i < BLOCKSIZE; i++) Node_Unset_Mark(node_free(Node_Store->store + i)); return TRUE; } int node_init_store() { if (node_more_store() == FALSE) bad_error("node_init_store failing"); return TRUE; } void node_free_store() { int i; node_block junk; printf("in free_store()\n"); while (Node_Store != 0) { /* free any space held by elements in the block */ for (i = 0; i < BLOCKSIZE; i++) atom_free(Node_Store->store + i); Node_Store = (junk = Node_Store)->next; free((char *) junk); } printf("N_malloc = %d, N_free=%d;=\n \n", N_MALLOC, N_FREE); } /* ** Allocate nodes from free list-- If no nodes available initiate ** a garbage collection. Note: routines which call new-node directly ** must protect their arguments, and localvariables themselve rather ** than make any assumptions about wheather they have been saved. */ node node_new() { node res; if (Free_List != 0) { res = Free_List; Free_List = (node) node_get_ptr(Free_List, RIGHT); node_set_ptr(res, (void *) 0, NODE, LEFT); node_set_ptr(res, (void *) 0, NODE, RIGHT); return res; } if (node_gc() != 0) return node_new(); if (node_more_store() != FALSE) return node_new(); #ifdef LOPG_PRINT fprintf(stderr, "out of nodes: system not giving more memory\n") #endif ; abort(); return node_new(); } /* ** void node_push_local(node *local) ** puts the address of a local variable onto the Locals_Stack stack ** ( of starting points for garbage collection). ** ** void node_pop_local() ** removes one ptr off the Locals_Stack stack. */ void print_locals_stack(void) { local_v ptr; ptr = Locals_Stack; printf("printing local stack \n"); while (ptr != 0) { node_print(*(ptr->val)); ptr = ptr->next; } printf(" done \n"); } void node_push_local(local_v loc, node * val) { #ifdef MEM_DEBUG if (Locals_Stack == loc) bad_error("trying to make circular stack\n"); #endif loc->next = Locals_Stack; loc->val = val; Locals_Stack = loc; } void node_pop_local() { if (Locals_Stack == 0) bad_error("poping empty local stack"); Locals_Stack = Locals_Stack->next; } /* ** Mark all nodes accessable from a node n. ** if n is marked Yes then both its subtrees are already ** marked and should be skipped. ** otherwise cal mark on any pointers to nodes stored in the ** node (is_node is used to check this) */ static int mark(node n) { if ((n != 0) && (Node_Marked(n) == NO)) { Node_Set_Mark(n); if (Node_LT(n) == NODE && Node_L(n).ptr != 0) mark((node) Node_L(n).ptr); else if (Node_LT(n) == NPTR && Node_L(n).ptr != 0) mark(*((node *) Node_L(n).ptr)); if (Node_RT(n) == NODE && Node_R(n).ptr != 0) mark((node) Node_R(n).ptr); else if (Node_RT(n) == NPTR && Node_R(n).ptr != 0) mark(*((node *) Node_R(n).ptr)); return 0; } return 1; } /* ** Collect garbage */ static int node_gc() { int i, free_cnt = 0; node_block next_block = Node_Store; local_v ptr; #ifdef LOG_PRINT fprintf(stdout, "Colecting Garbage .. ") #endif ; fflush(stdout); /*call mark on variables in local list */ ptr = Locals_Stack; while (ptr != 0) { mark(*(ptr->val)); ptr = ptr->next; } /* now put anything that is not already marked on the free_list */ while (next_block != 0) { for (i = 0; i < BLOCKSIZE; i++) { if (Node_Marked(next_block->store + i) == YES) Node_Unset_Mark(next_block->store + i); else { atom_free(next_block->store + i); node_free(next_block->store + i); free_cnt++; } } next_block = next_block->next; } #ifdef LOG_PRINT fprintf(stdout, "Done %d nodes freed\n", free_cnt) #endif ; fflush(stdout); return free_cnt; } /**************************************************************************/ /********************** implementations from error.c **********************/ /**************************************************************************/ #ifdef GAMBIT_EXCEPTIONS ErrorInPelican::~ErrorInPelican() { } std::string ErrorInPelican::GetDescription(void) const { return "Error somewhere in Pelican"; } #endif void bad_error(char *m) /* generates an error message and aborts*/ { #ifdef GAMBIT_EXCEPTIONS throw ErrorInPelican(); #endif #ifdef LOG_PRINT fprintf(stderr /* was Pel_Err */,"%s\n",m) #endif ; exit(1); } void warning(char *m){ #ifdef LOG_PRINT fprintf(stderr /* was Pel_Err */,"Warning:%s\n",m) #endif ;} /**************************************************************************/ /*********************** implementations from Rand.c **********************/ /**************************************************************************/ void srand48(long int seedval); // WARNING: RDM added the following just to get to compile under BCC // I have no idea if this is correct!!! #if !defined(HAVE_SRAND48) void srand48(long int seedval) { srand(seedval); } #endif // HAVE_SRAND48 /* ** rand_seed -- seed the random number generator with seedval. */ void rand_seed(long int seedval){ srand48(seedval);} /* **rand_int -- return a random integer r with low<=r<=high ** it produces double between low and high and rounds ** by adding .5-epsilon and truncating, (if we just add ** .5 then there is a slight chance we could end up with ** high+1.) */ int rand_int(int low, int high){ return (int)(low+drand48()*(high-low)+.499999999999); } /* **rand_double -- return a random integer r with low<=r<=high */ double rand_double(int low, int high){ return (drand48()*(high-low)+low); } /**************************************************************************/ /********************** implementations from Dlist.c **********************/ /**************************************************************************/ void Dlist_empty(node L){ Dlist_first(L)=0;} /* ** invariants: Dnode_next(Dnode_prev(pos)) ==pos ** for all pointers to Dlist node entrees. ** (NOTE: Dnode_next(L) := Dlist_first(L), ** where L is list header) ** ** Dnode_prev(Dnode_next(pos))=pos ** for all non-zero pointers to Dlist node entrees ** and also for list header ** */ node Dlist_add(node L, node data){ node tmp=0; LOCS(2); PUSH_LOC(data); PUSH_LOC(tmp); tmp=node_new(); Dnode_link(tmp)=node_new(); Dnode_data(tmp)=data; Dnode_prev(tmp)=L; Dnode_next(tmp)=Dlist_first(L); if (Dnode_next(tmp)!=0) Dnode_prev(Dnode_next(tmp))=tmp; Dlist_first(L)=tmp; POP_LOCS(); return tmp; } node Dlist_del(node L, node pos){ if (Dnode_next(pos)!=0) Dnode_prev(Dnode_next(pos))=Dnode_prev(pos); if (Dnode_prev(pos)!=L) Dnode_next(Dnode_prev(pos))=Dnode_next(pos); else Dlist_first(L)=Dnode_next(pos); return (node)Dnode_data(pos); } node Dlist_data(node pos){ return (node)Dnode_data(pos);} /* end Dlist.c */ /**************************************************************************/ /******************** implementations from Dmatrix.c **********************/ /**************************************************************************/ /*--------------------------------------------------------------- vector/matrix type a linear array of int, whith auxilary info. *) the number of elements that can be stored is in elt[0] *) the current number of rows is in elt[1] *) the current number of collumbs is in elt[2] The actual data are then stored in row major order from elt[3] on ---------------------------------------------------------------*/ #ifndef DMATRIX_FAST struct Dmatrix_t { int store; int nrows; int ncols; double *coords; }; #endif /*------------------------------------------------------------- vector access macroes (which ignore any rows except for first) -------------------------------------------------------------*/ #define Vstore(V) ((V->store)) /* maximum #elts available */ #define Vlength(V) ((V->nrows)) /* actual #elts stored */ #define Vref1(V,i) (((V->coords)[i-1])) /*acces ith elt (starting at 1) */ #define Vref0(V,i) (((V->coords)[i])) /*acces ith elt (starting at 0) */ #define Vref(V,i) Vref1(V,i) /*------------------------------------------------------------ matrix access macroes -------------------------------------------------------------*/ #define Mstore(V) ((V->store)) /* maximum #elts available */ #define MMrows(V) ((V->store/V->ncols)) /* maximum #rows */ #define Mrows(V) ((V->nrows)) /* number rows stored */ #define Mcols(V) ((V->ncols)) /* number cols stored */ #define Mref1(V,i,j)(((V->coords)[(i-1)*(V->ncols)+j-1])) #define Mref0(V,i,j)(((V->coords)[i*(V->ncols)+j])) #define Mref(V,i,j) Mref1((V),i,j) #ifndef DMATRIX_FAST double DMstore(Dmatrix M) { return Mstore(M); } double DMMrows(Dmatrix M) { return MMrows(M); } double DMrows(Dmatrix M) { return Mrows(M); } double DMcols(Dmatrix M) { return Mcols(M); } double *DMelts(Dmatrix M) { return M->coords; } double *DMref_P(Dmatrix M, int i, int j) { return &(Mref0(M, i, j)); } #endif /* ** Constructor/Destructors for Dmatrixes ** ** Dmatrix Dmatrix_free(int r, int c); ** New Dmatrix cabable of holding r rows, and c collumbs. ** Dmatrix Dmatrix_new(Dmatrix V); */ Dmatrix Dmatrix_new(int r, int c) { Dmatrix V; /* void *mem_malloc(int); */ V = (Dmatrix) mem_malloc(sizeof(struct Dmatrix_t)); if (!V) bad_error("allocation failure in Dmatrix_new()"); V->coords = (double *) mem_malloc(r * c * sizeof(double)); if (!V) bad_error("allocation failure 2 in Dmatrix_new()"); Mstore(V) = r * c; Mrows(V) = r; Mcols(V) = c; return V; } void Dmatrix_free(Dmatrix V) { /* void mem_free(); */ if (V != 0 && V->coords != 0) mem_free((char *) (V->coords)); if (V != 0) mem_free((char *) (V)); } #undef mem_malloc #undef mem_free /* ** Dmatrix_resize(R,r,c) ** if R has enough storage to hold an rxc matrix resets ** row and columb entrees of r to r and c. otherwise ** frees R and reallocates an rxc matrix */ Dmatrix Dmatrix_resize(Dmatrix R, int r, int c) { if (R == 0 || Mstore(R) < (r * c)) { if (R != 0) Dmatrix_free(R); R = Dmatrix_new(r, c); } else { Mrows(R) = r; Mcols(R) = c; } return R; } /* ** Dmatrix_print(M): print an Dmatrix ** if M is null print <<>> and return fail. ** otherwise print matrix and return true. */ Dmatrix Dmatrix_fprint(FILE *fout, Dmatrix M) { int i, j; if (M == 0) { #ifdef LOG_PRINT fprintf(fout,"<<>>") #endif ; return 0; } #ifdef LOG_PRINT fprintf(fout,"<") #endif ; for (i = 1; i <= Mrows(M); i++) { #ifdef LOG_PRINT fprintf(fout,"<") #endif ; for (j = 1; j <= Mcols(M); j++) { #ifdef LOG_PRINT fprintf(fout,"%8.4f", Mref(M, i, j)) #endif ; if (j < Mcols(M)) #ifdef LOG_PRINT fprintf(fout,", ") #endif ; } #ifdef LOG_PRINT fprintf(fout,">") #endif ; if (i < Mrows(M)) #ifdef LOG_PRINT fprintf(fout,"\n") #endif ; } #ifdef LOG_PRINT fprintf(fout,">") #endif ; return M; } /* ** matrix_add(M1,M2,&M3) -- Add two Dmatrixes: ** if M1, and M2 are incompatable (or null) complain and return false. ** if *M3 has too little storage (or is null) free *M3 if nescesary ** and create new storage. */ Dmatrix Dmatrix_add(Dmatrix M1, Dmatrix M2, Dmatrix * M3) { int i, j; Dmatrix R = *M3; if (M1 == 0 || M2 == 0 || Mrows(M1) != Mrows(M2) || Mcols(M1) != Mcols(M2)) { #ifdef LOG_PRINT fprintf(stderr, "matrix_add: dimensions dont match\n") #endif ; return 0; } Dmatrix_resize(R, Mrows(M1), Mcols(M1)); for (i = 1; i <= Mrows(M1); i++) for (j = 1; j <= Mcols(M1); j++) Mref(R, i, j) = Mref(M1, i, j) + Mref(M2, i, j); M3 = &R; return R; } /* **Dmatrix_mull(M1,M2,&M3) -- multiply two Dmatrixes: ** if M1, and M2 are incompatable (or null) complain and return false. ** if *M3 has too little storage (or is null) free *M3 if nescesary ** and create new storage. ** NOT USED YET */ Dmatrix Dmatrix_mull(Dmatrix M1, Dmatrix M2, Dmatrix * M3) { int i, j, k; Dmatrix R = *M3; if (M1 == 0 || M2 == 0 || Mcols(M1) != Mrows(M2)) { #ifdef LOG_PRINT fprintf(stderr, "Dmatrix_mull: incompatible matrices\n") #endif ; return 0; } Dmatrix_resize(R, Mrows(M1), Mcols(M2)); for (i = 1; i <= Mrows(M1); i++) for (j = 1; j <= Mcols(M2); j++) { Mref(R, i, j) = 0; for (k = 1; k <= Mcols(M1); k++) Mref(R, i, j) += Mref(M1, i, k) * Mref(M2, k, j); } M3 = &R; return R; } /* ** Dmatrix_dot(M1,M2,&M3) -- calculate M1*Transpose(M2): ** if M1, and M2 are incompatable (or null) complain and return false. ** if *M3 has too little storage (or is null) free *M3 if nescesary ** and create new storage. */ Dmatrix Dmatrix_dot(Dmatrix M1, Dmatrix M2, Dmatrix M3) { int i, j, k; if (M1 == 0 || M2 == 0 || Mcols(M1) != Mcols(M2)) { #ifdef LOG_PRINT fprintf(stderr, "Dmatrix_dot: incompatible matrices\n") #endif ; return 0; } M3 = Dmatrix_resize(M3, Mrows(M1), Mrows(M2)); for (i = 1; i <= Mrows(M1); i++) for (j = 1; j <= Mrows(M2); j++) { Mref(M3, i, j) = 0; for (k = 1; k <= Mcols(M1); k++) Mref(M3, i, j) += Mref(M1, i, k) * Mref(M2, j, k); } return M3; } /* ** Dmatrix_equal(M1,M2) ** return true if matrices represented by M1 and M2 are equal. ** false otherwise. NOT TESTED YET */ int Dmatrix_equal(Dmatrix M1, Dmatrix M2) { int i, j; if (M1 == 0 && M2 == 0) return 1; if (M1==0||M2==0||(Mrows(M1)!=Mrows(M2))||(Mcols(M1)!=Mcols(M2))) return 0; for (i = 1; i <= Mrows(M1); i++) for (j = 1; j <= Mcols(M1); j++) if (Mref(M1, i, j) != Mref(M2, i, j)) return 0; return 1; } /* ** Dmatrix_GQR ** Use givens QR on a sqaure matrix: ** after completion Q should be orthogonal, R triangular ** and Q*A = original matrix A */ void Dmatrix_GQR(Dmatrix Q,Dmatrix A) /* A->ch<=A->rh=Q->rh=Q->ch */ { int i,j,k; int r,c; double s,s1,s2; double t1,t2; r=Mrows(A); c=Mcols(A); for(i=1;i<=r;i++){ for(k=1;k<=r;k++)Mref(Q,i,k)=0.0; Mref(Q,i,i)=1.0;} for (i=1;i<=c;i++) for (k=i+1;k<=r;k++) /* performing givens rotations to zero A[k][i] */ if (Mref(A,k,i)!=0){ s=sqrt(Mref(A,i,i)*Mref(A,i,i)+ Mref(A,k,i)*Mref(A,k,i)); s1=Mref(A,i,i)/s; s2=Mref(A,k,i)/s; for(j=1;j<=c;j++) { t1=Mref(A,i,j); t2=Mref(A,k,j); Mref(A,i,j)=s1*t1+s2*t2; Mref(A,k,j)=-s2*t1+s1*t2;} /* actually doing givens row rotations on transpose Q */ for(j=1;j<=r;j++){ t1=Mref(Q,j,i); t2=Mref(Q,j,k); Mref(Q,j,i)=s1*t1+s2*t2; Mref(Q,j,k)=-s2*t1+s1*t2;} } } /* ** Dmatrix_Solve, Solve a square matrix in place */ #define LHS(i,j) Mref(LHS,i,j) #define RHS(i) Vref(RHS,i) void Dmatrix_Solve(Dmatrix LHS, Dmatrix RHS,int n){ int i,j,k,m=n; double s,s1,s2,t1,t2; /* ** Use Givens rotations to triangularize LHS,i.e.LHS becomes Q*LHS. ** (triangular) ** and also apply same givens rotations to RHS i.e. RHS becomes Q*RHS. */ for (i=1;i<=n;i++){ for (k=i+1;k<=m;k++){ if (LHS(k,i)!=0.0){ /* compute rotation */ s=sqrt(LHS(i,i)*LHS(i,i)+LHS(k,i)*LHS(k,i)); s1=LHS(i,i)/s; s2=LHS(k,i)/s; /* apply rotation to LHS */ for(j=1;j<=n;j++) { t1=LHS(i,j); t2=LHS(k,j); LHS(i,j)=s1*t1+s2*t2; LHS(k,j)=-s2*t1+s1*t2; } /* apply rotation to RHS */ t1=RHS(i); t2=RHS(k); RHS(i)=s1*t1+s2*t2; RHS(k)=-s2*t1+s1*t2; } } } /* ** Back solve R*X=Y ** R=top square portion of LHS. (2nx2nupper triangular) ** Y=top 2n entrees of RHS. ** results in X which solves original least squares problem. */ for(j=n;j>=1;j--){ t1=RHS(j); for(i=j+1;i<=n;i++) t1-=LHS(j,i)*RHS(i); t1=t1/LHS(j,j); RHS(j)=t1; } } #undef LHS #undef RHS /* end Dmatrix.c */ /**************************************************************************/ /********************* implementations from Imatrix.c *********************/ /**************************************************************************/ #ifndef min #define min(i,j) ((i) < (j) ? (i): (j)) #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #ifndef IMATRIX_FAST /*--------------------------------------------------------------- vector/matrix type a linear array of int, whith auxilary info. *) the number of elements that can be stored is in elt[0] *) the current number of rows is in elt[1] *) the current number of collumbs is in elt[2] The actual data are then stored in row major order from elt[3] on ---------------------------------------------------------------*/ struct Imatrix_t { int store; /* maximum number of helts reserved */ int topc; /* effective number of columbs */ int topr; /* effective number of rows */ int ncols; /* number of elts between first elts of rows */ int *elts; /* ptr to first elt of block of space */ }; /* ** a couple of functions which are defined in files that ** I don't want to include right now, when things stableize ** bad_error -- used mainly to stop things when a function ** is passed bad input, as things stablizes ** less catastrophic reactions may be introduced. ** mem_alloc, ** mem_free -- call malloc and free with some extra book-keeping. */ #endif /* void bad_error(char *); char *mem_malloc(size_t); void mem_free(char *); */ /*------------------------------------------------------------- vector access macroes (which ignore any rows except for first) -------------------------------------------------------------*/ #define ImatrixVstore(V) (((V)->store)) /* maximum #elts available */ #define ImatrixVlength(V) (((V)->topc)) /* actual #elts stored */ #define ImatrixVref1(V,i) (((V)->elts[i-1]))/* acces ith elt (starting at 1)*/ #define ImatrixVref0(V,i) (((V)->elts[i]))/* acces ith elt (starting at 0) */ #define ImatrixVref(V,i) ImatrixVref1(V,i) /*------------------------------------------------------------ matrix access macroes -------------------------------------------------------------*/ #define ImatrixMstore(V) (((V)->store)) /* maximum #elts available */ #define ImatrixMMrows(V) (((V)->store/(V)->ncols)) /* maximum #rows */ #define ImatrixMrows(V) (((V)->topr)) /* number rows stored */ #define ImatrixMcols(V) (((V)->topc)) /* number cols stored */ #define ImatrixMNcols(V) (((V)->ncols)) /* number cols stored */ #define ImatrixMref1(V,i,j) ((((V))->elts[(i-1)*((V)->ncols)+j-1])) #define ImatrixMref0(V,i,j) (((V)->elts[(i*(V)->ncols)+j])) #define ImatrixMref(V,i,j) ImatrixMref1(V,i,j) #ifndef IMATRIX_FAST int IMstore(Imatrix M) { return ImatrixMstore(M); } int IMMrows(Imatrix M) { return ImatrixMMrows(M); } int IMrows(Imatrix M) { return ImatrixMrows(M); } int IMcols(Imatrix M) { return ImatrixMcols(M); } int *IMref1(Imatrix M, int i, int j) { return &(ImatrixMref1(M, i, j)); } #endif /* ** Constructor/Destructors for Imatrixes ** ** Imatrix Imatrix_free(int r, int c); ** New Imatrix cabable of holding r rows, and c collumbs. ** Imatrix Imatrix_new(Imatrix V); */ Imatrix Imatrix_new(int r, int c) { Imatrix V; V = (Imatrix) mem_malloc(sizeof(struct Imatrix_t)); if (!V) bad_error("allocation failure 1 in Imatrix_new()"); V->elts = (int *) mem_malloc(r * c * sizeof(int)); if (!V) bad_error("allocation failure 2 in Imatrix_new()"); V->store = r * c; V->topc = V->ncols = c; V->topr = r; return V; } void Imatrix_free(Imatrix V) { if (V != 0) { if (V->elts != 0) mem_free((char *) (V->elts)); mem_free((char *) (V)); } } /* ** Imatrix_resize(R,r,c) ** Reset R to hold an r,by c matrix. ** if R has enough storage to hold an rxc matrix resets ** row and columb entrees of r to r and c. otherwise ** frees R and reallocates an rxc matrix ** DOES NOT PRESERVE INDECIES OF EXISTING DATA */ Imatrix Imatrix_resize(Imatrix R, int r, int c) { if (R == 0 || ImatrixMstore(R) < (r * c)) { if (R != 0) Imatrix_free(R); R = Imatrix_new(r, c); } else { ImatrixMrows(R) = r; ImatrixMcols(R) = c; ImatrixMNcols(R) = c; } return R; } Imatrix Imatrix_submat(Imatrix R, int r, int c) { if (R == 0 || c > ImatrixMNcols(R) || r > ImatrixMrows(R) * ImatrixMNcols(R)) { bad_error("bad subscripts or zero matrix in Imatrix_submat()"); } else { ImatrixMrows(R) = r; ImatrixMcols(R) = c; } return R; } /* ** Imatrix_print(M): print an Imatrix ** if M is null print <<>> and return fail. ** otherwise print matrix and return true. */ Imatrix Imatrix_fprint(FILE *fout,Imatrix M) { int i, j; if (M == 0) { #ifdef LOG_PRINT fprintf(fout,"<>\n") #endif ; return 0; } #ifdef LOG_PRINT fprintf(fout,"<") #endif ; for (i = 1; i <= ImatrixMrows(M); i++) { for (j = 1; j <= ImatrixMcols(M); j++) { #ifdef LOG_PRINT fprintf(fout,"%d", ImatrixMref(M, i, j)) #endif ; if (j < ImatrixMcols(M)) #ifdef LOG_PRINT fprintf(fout,", ") #endif ; } if (i < ImatrixMrows(M)) #ifdef LOG_PRINT fprintf(fout,";\n") #endif ; } #ifdef LOG_PRINT fprintf(fout,">\n") #endif ; return M; } /* ** matrix_add(M1,M2,&M3) -- Add two Imatrixes: ** if M1, and M2 are incompatable (or null) complain and return false. ** if *M3 has too little storage (or is null) free *M3 if nescesary ** and create new storage. */ Imatrix Imatrix_add(int i1,Imatrix M1,int i2, Imatrix M2, Imatrix M3) { int i, j; Imatrix R = M3; if (M1 == 0 || M2 == 0 || ImatrixMrows(M1) != ImatrixMrows(M2) || ImatrixMcols(M1) != ImatrixMcols(M2)) { #ifdef LOG_PRINT fprintf(stderr, "matrix_add: dimensions dont match\n") #endif ; return 0; } R=Imatrix_resize(R, ImatrixMrows(M1), ImatrixMcols(M1)); for (i = 1; i <= ImatrixMrows(M1); i++) for (j = 1; j <= ImatrixMcols(M1); j++) ImatrixMref(R, i, j) =i1* ImatrixMref(M1, i, j) + i2*ImatrixMref(M2, i, j); return R; } /* **Imatrix_mull(M1,M2,&M3) -- multiply two Imatrixes: ** if M1, and M2 are incompatable (or null) complain and return false. ** if *M3 has too little storage (or is null) free *M3 if nescesary ** and create new storage. ** NOT USED YET */ Imatrix Imatrix_mul(Imatrix M1, Imatrix M2, Imatrix M3) { int i, j, k; Imatrix R; if (M1 == 0 || M2 == 0 || ImatrixMcols(M1) != ImatrixMrows(M2)) { #ifdef LOG_PRINT fprintf(stderr, "Imatrix_mull: incompatible matrices\n") #endif ; return 0; } if (M3!=M1&&M3!=M2) R=Imatrix_resize(M3, ImatrixMrows(M1), ImatrixMcols(M2)); else R=Imatrix_new(ImatrixMrows(M1),ImatrixMcols(M2)); for (i = 1; i <= ImatrixMrows(M1); i++) for (j = 1; j <= ImatrixMcols(M2); j++) { ImatrixMref(R, i, j) = 0; for (k = 1; k <= ImatrixMcols(M1); k++) ImatrixMref(R, i, j) += ImatrixMref(M1, i, k) * ImatrixMref(M2, k, j); } if (M3==M1&&M3==M2) Imatrix_free(M3); return R; } /* ** Imatrix_dot(M1,M2,&M3) -- calculate M1*Transpose(M2): ** if M1, and M2 are incompatable (or null) complain and return false. ** if *M3 has too little storage (or is null) free *M3 if nescesary ** and create new storage. */ Imatrix Imatrix_dot(Imatrix M1, Imatrix M2, Imatrix M3) { int i, j, k; if (M1 == 0 || M2 == 0 || ImatrixMcols(M1) != ImatrixMcols(M2)) { #ifdef LOG_PRINT fprintf(stderr, "Imatrix_dot: incompatible matrices\n") #endif ; return 0; } M3 = Imatrix_resize(M3, ImatrixMrows(M1), ImatrixMrows(M2)); for (i = 1; i <= ImatrixMrows(M1); i++) for (j = 1; j <= ImatrixMrows(M2); j++) { ImatrixMref(M3, i, j) = 0; for (k = 1; k <= ImatrixMcols(M1); k++) ImatrixMref(M3, i, j) += ImatrixMref(M1, i, k) * ImatrixMref(M2, j, k); } return M3; } /* ** dot_Ivector(M1,M2) -- vector dot product (integer valued) ** calculate dot product of first rows of M1, and M2. ** if M1, and M2 have are incompatable(or null) complain and return 0. ** NOT USED YET */ int dot_Ivector(Imatrix M1, Imatrix M2) { int k, d = 0; if (M1 == 0 || M2 == 0 || ImatrixMcols(M1) != ImatrixMcols(M2)) { #ifdef LOG_PRINT fprintf(stderr, "dot_Ivector: incompatible or null vectors\n") #endif ; return 0; } for (k = 1; k <= ImatrixMcols(M1); k++) d += ImatrixVref(M1, k) * ImatrixVref(M2, k); return d; } /* ** Imatrix_equal(M1,M2) ** return true if matrices represented by M1 and M2 are equal. ** false otherwise. */ int Imatrix_equal(Imatrix M1, Imatrix M2) { int i, j; if (M1 == 0 && M2 == 0) return TRUE; if (M1 == 0 || M2 == 0 || (ImatrixMrows(M1) != ImatrixMrows(M2)) || (ImatrixMcols(M1) != ImatrixMcols(M2))) { printf("in Imatrix_equal comparison failing\n"); return FALSE; } for (i = 1; i <= ImatrixMrows(M1); i++) for (j = 1; j <= ImatrixMcols(M1); j++) if (ImatrixMref(M1, i, j) != ImatrixMref(M2, i, j)) return FALSE; return TRUE; } int Imatrix_order(Imatrix M1, Imatrix M2) { int i, j, c = 0; if (M1 == 0 && M2 == 0) return TRUE; if (M1 == 0 || M2 == 0 || (ImatrixMrows(M1) != ImatrixMrows(M2)) || (ImatrixMcols(M1) != ImatrixMcols(M2))) { printf("in Imatrix_equal comparison failing\n"); return FALSE; } for (i = 1; i <= ImatrixMrows(M1); i++) for (j = 1; j <= ImatrixMcols(M1); j++) if ((c = ImatrixMref(M1, i, j) - ImatrixMref(M2, i, j)) != 0) return c; return 0; } int Imatrix_gcd_reduce(Imatrix M) { int i, j, g = 0, gcd(int, int); if (M == 0) return 1; for (i = 1; i <= ImatrixMrows(M); i++) for (j = 1; j <= ImatrixMcols(M); j++) { if (g == 0 && ImatrixMref(M, i, j) != 0) g = abs(ImatrixMref(M, i, j)); else if (ImatrixMref(M, i, j) != 0) g = abs(gcd(g, ImatrixMref(M, i, j))); } for (i = 1; i <= ImatrixMrows(M); i++) for (j = 1; j <= ImatrixMcols(M); j++) ImatrixMref(M, i, j) = ImatrixMref(M, i, j) / g; return g; } int gcd(int a, int b) { int c; if (b == 0) return a; c = a % b; if (c == 0) return b; else return gcd(b, c); } /* ** int Imatrix_rref(Imatrix N, int *det) ** replaces N by its reduced row echelon form (upper triangular). ** returns the rank of the matrix, and puts the determinant ** of the first full rank maximal minor in det. ** ALGORITHM 9.1 of Algorithms for Computer Algebra, ** Geddes,Czapor,Labahn ** NOTE: I have actually changed this to reduce by the gcd when posible ** to protect against over flow. (for the C-integer version). */ #define M(i,j) (ImatrixMref(N,i,j)) int Imatrix_rref(Imatrix N,int *det){ int divisor=1,sign=1,r=1,p,k,j,i,g; for(k=1;k<=ImatrixMcols(N)&&r<=ImatrixMrows(N);k++){ for(p=r; p<=ImatrixMrows(N)&&M(p,k)==0;p++); if (p<=ImatrixMrows(N)) { for(j=k;j<=ImatrixMcols(N);j++){i=M(p,j); M(p,j)=M(r,j); M(r,j)=i;} if (r!=p) sign*=-1; for(i=r+1;i<=ImatrixMrows(N);i++){ g=gcd(M(i,k),M(r,k)); for(j=k+1;j<=ImatrixMcols(N);j++){ M(i,j)=(M(r,k)*M(i,j)-M(r,j)*M(i,k))/divisor; } M(i,k)=0; } divisor=M(r,k); r++; } } *det=sign*divisor; return r-1; } /* ** int Imatrix_backsolve(Imatrix N, Imatrix S) ** finds a solution to a triangular system of equations with more ** equtions then unknowns */ int Imatrix_backsolve(Imatrix N, Imatrix S){ int p,j,g,k; if (N==0 || S==0 || IMcols(N)!=IMcols(S)||IMcols(N)<=IMrows(N)) bad_error("bad dimensions in backsolve"); /* ** find first missing pivot (in row p; p=IMrows(N)+1 if no missing pivots */ for(p=1;p<=ImatrixMrows(N) && ImatrixMref(N,p,p)!=0;p++) /* null body*/; /* ** now set up for a solution to the AX=0 problem with A a p-1xp matrix whoose ** first pxp minor is nonsingular (use simple minded back substitution) */ for(j=1;j<=ImatrixMcols(N);j++) ImatrixVref(S,j)=0; ImatrixVref(S,p)=1; for (j=p-1;j>=1;j--){ for(k=j+1;k<=p;k++) ImatrixVref(S,j)-=ImatrixMref(N,j,k)*ImatrixVref(S,k); g=gcd(ImatrixVref(S,j),ImatrixMref(N,j,j)); ImatrixVref(S,j)=ImatrixVref(S,j)/g; g=(ImatrixMref(N,j,j)/g); if (ImatrixVref(S,j)!=0) for(k=j+1;k<=p;k++) ImatrixVref(S,k)*=g; } return 1; } #undef M /* ** Imatrix_hermite: ** Input: S an n by m Imatrix. ** Output: True ** ** Sidefects: U points to a unitary nxn matrix ** S gets replaced by its hermite normal form (U*S) ** ** Method: ** U = Inxn ** c = 1 ** while (c<=n) do ** find mc>=c such that abs(S(mc,c)) has minimum non-zero value ** if (mc!=c) then switch rows mc and c (in S, and U) ** if (S(c,c)<0) then multiply row c by -1 ** if (S(c,c)!=0) then ** for i in c+1:n add S(i,c)/S(c,c) times row c to row i; ** end(if) ** if S(i,c)==0 for all i in c+1 ... n set c=c+1 ** end(while) ** */ int Imatrix_hermite(Imatrix S, Imatrix U){ int c=1,mc,i,j,m,n,done,sign; int t=0,mv=0; m=ImatrixMcols(S); n=ImatrixMrows(S); if (S==0 || U==0 || ImatrixMrows(U)!=n || ImatrixMrows(U)!=n) bad_error("Incompatable matrices in Imatrix_hermite"); /* Initialize U to nxn identity */ U=Imatrix_resize(U,n,n); for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if (i==j) ImatrixMref(U,i,j)=1; else ImatrixMref(U,i,j)=0; } } while(c<=n){ /* find minimum entry in col c */ mv=abs(ImatrixMref(S,c,c)); mc=c; for(i=c+1;i<=n;i++){ t=abs(ImatrixMref(S,i,c)); if(mv==0 || (mv>t && t!=0)){ mv=t; mc=i; } } /* if nescesary pivot to put min in row c and multiply by+-1 to ensure diagonal entry is positive */ if (mc!=c||ImatrixMref(S,mc,c)<0){ if (ImatrixMref(S,mc,c)<0) sign=-1; else sign=+1; for(j=c;j<=m;j++){ t=ImatrixMref(S,mc,j); ImatrixMref(S,mc,j)=ImatrixMref(S,c,j); ImatrixMref(S,c,j)=sign*t; } for(j=1;j<=n;j++){ t=ImatrixMref(U,mc,j); ImatrixMref(U,mc,j)=ImatrixMref(U,c,j); ImatrixMref(U,c,j)=sign*t; } } /* if collumb is not zero do a reduction step */ done=TRUE; if (ImatrixMref(S,c,c)!=0){ for(i=c+1;i<=n;i++){ t=ImatrixMref(S,i,c)/ImatrixMref(S,c,c); for(j=c;j<=m;j++){ ImatrixMref(S,i,j)-=t*ImatrixMref(S,c,j); } for(j=1;j<=n;j++){ ImatrixMref(U,i,j)-=t*ImatrixMref(U,c,j); } if (ImatrixMref(S,i,c)!=0) done=FALSE; } } /* if all entrees of col c bellow row c are zero go tonext col */ if (done==TRUE) c++; } return TRUE; } Imatrix Imatrix_dup(Imatrix M,Imatrix N){ Imatrix R; int i,j; if (M==0) return 0; if (M==N) bad_error("Imatrix_dup: source and destination equal"); R=Imatrix_resize(N,ImatrixMrows(M),ImatrixMcols(M)); for(i=1;i<=ImatrixMrows(M);i++) for(j=1;j<=ImatrixMcols(M);j++) ImatrixMref(R,i,j)=ImatrixMref(M,i,j); return R; } int Imatrix_is_zero(Imatrix M){ int i,j; if (M==0) return TRUE; for(i=1;i<=IMrows(M);i++){ for(j=1;j<=IMcols(M);j++){ if (*IMref(M,i,j)!=0) return FALSE; } } return TRUE; } /* end Imatrix.c */ /**************************************************************************/ /********************** implementations from Lists.c **********************/ /**************************************************************************/ void bad_error(char *); void mem_free(void *); node list_push(node item,node *stack){ *stack=Cons(item,*stack); return item; } int list_length(node L){ int ct=0; while(L!=0){ ct++; L=Cdr(L); } return ct; } node list_pop(node *stack){ node temp; temp=Car(*stack); *stack=Cdr(*stack); return temp; } node list_first(node list){ return Car(list); } node list_rest(node list){ return Cdr(list); } int list_empty(node list){ if (list==0) return TRUE; else return FALSE; } /* ** Inserts a node g onto a list L in order (according to a comparison ** function comp) -- IF There is allready and equivalent object on ** the list and uniq is TRUE it is not inserted, and a value of zero ** is returned, otherwise it is inserted and a value of 1 is returned. */ int list_insert(node g, node * L, int (*comp) (node, node), int uniq) { int flg = 1; node ptr = *L; LOCS(2); PUSH_LOC(*L); PUSH_LOC(g); if ((*L == 0) || ((flg = comp(g, Car(*L))) >= 0)) { if (uniq==FALSE || flg != 0) *L = Cons(g, *L); } else { while ((Cdr(ptr) != 0) && ((flg = comp(g, Car(Cdr(ptr))))< 0)) { ptr = (node) Cdr(ptr); } if (uniq==FALSE || flg != 0) node_set_ptr(ptr,Cons(g, Cdr(ptr)), NODE, RIGHT); } POP_LOCS(); return flg; } /* ** list remove -- remove a specific elt from a list */ int list_Imatrix_comp(node g1, node g2) { if (g1 == 0 || g2 == 0 || node_get_type(g1, LEFT) != IMTX || node_get_type(g2, LEFT) != IMTX) { bad_error("Non-IMTX nodes in sexpr_IMTX_comp()"); } return Imatrix_order((struct Imatrix_t *) Car(g1), (struct Imatrix_t *) Car(g2)); } node list_cat(node l1,node l2){ node ptr=l1; if (ptr==0) return l2; while(Cdr(ptr)!=0) ptr=Cdr(ptr); node_set_ptr(ptr,(void *)l2,NODE,RIGHT); return l1; } void xpl_fprint(FILE *fout,node L){ node ptr; Dmatrix P; int i; #ifdef LOG_PRINT fprintf(fout, "%% Solution list :\n"); fprintf(fout, "%% Re(H) , Im(H) , Re(Xi) , Im(Xi) , T \n"); fprintf(fout, "%%\n"); fprintf(fout,"{\n") #endif ; ptr=L; while(ptr!=0){ P=(Dmatrix)(Car(Car(ptr))); #ifdef LOG_PRINT fprintf(fout,"<"); fprintf(fout,"%12g, %12g,",DVref(P,1),DVref(P,2)) #endif ; for(i=3;i",DVref(P,i)) #endif ; ptr=Cdr(ptr); if (ptr!=0) #ifdef LOG_PRINT fprintf(fout,",") #endif ; #ifdef LOG_PRINT fprintf(fout,"\n") #endif ; } #ifdef LOG_PRINT fprintf(fout,"};") #endif ; } /* end Lists.c */ /**************************************************************************/ /********************** implementations from Pconfig.c ********************/ /**************************************************************************/ /* ** Pconfig.c Birk Huber 2-1-1994 ** ** Module for points and point configurations in affine space. ** ** A point are represented by a node with a label(cstring) on the ** left and a vector of coordinates(Imatrix) on the right. ** ** ----------------------- ** | PNT | IMTX | ** ----------------------- ** |(char *) | Imatrix | ------> structure holding coords ** ----------------------- ** |------------------------> string ** ** A point configuration is represented by a node with a list of ** points on the right and the number of points in the list ** stored on the ** left. ** ** ----------------------- ** | PCFG | NODE | ** ----------------------- ------------------ ** | int | Imatrix | ------>| NODE | NODE | ** ----------------------- ------------------ ** | node | node | -----> ** ------------------ ** | ** point 1 */ node pcfg_start(node P){ return Cdr(P);} node pcfg_next_pnt(node *ptc){ node pt; pt=Car(*ptc); *ptc=Cdr(*ptc); return pt;} /* ** node pnt_new(char *s,Imatrix m) ** input: a string s ** an integer matrix m ** output: a point with lable s, and coordinates m */ node pnt_new(char *s, Imatrix m) { node R; R = node_new(); node_set_ptr(R, s, PNT, LEFT); node_set_ptr(R, m, IMTX, RIGHT); return R; } /* ** pnt_free ** input: a node ** output: none ** effects: frees space allocated for lable and coordinates. ** resets fields of node to null nodeptrs. ** error : checks that n is a non-null pnt. */ void pnt_free(node n) { if (n==0||node_get_type(n, LEFT) == PNT) { mem_free((char *) node_get_ptr(n, LEFT)); Imatrix_free((Imatrix) node_get_ptr(n, RIGHT)); node_set_ptr(n, (void *) 0, NODE, RIGHT); node_set_ptr(n, (void *) 0, NODE, LEFT); } else bad_error("error: pnt_free() called on non-point\n"); } /* ** default display for points. */ int pnt_print(node n) { if (n==0||node_get_type(n, LEFT) == PNT) { printf("("); printf("%s", (char *) node_get_ptr(n, LEFT)); printf(","); Imatrix_print((Imatrix) node_get_ptr(n, RIGHT)); printf(")\n"); return 0; } bad_error("error: pnt_print() called on non-point\n"); return 1; /*bad error causes abort */ } /* ** pnt_is_point ** input: a node n ** output: TRUE if n is a point (and non-null) ** FALSE otherwise */ int pnt_is_point(node n){ if (n!=0&&node_get_type(n,LEFT)==PNT) return TRUE; else return FALSE; } /* ** pnt_comp_lbl ** input: two points; ** output: value of strcmp on the lables of pt1 and pt2. ** error conditions: checks that g1, and g2 are (non-null) points */ int pnt_comp_lbl(node g1, node g2){ if ((pnt_is_point(g1)!=TRUE)||(pnt_is_point(g2)!=TRUE)){ bad_error("Non-PNT nodes in pnt_comp_lbl()"); } return strcmp(pnt_lable(g2),pnt_lable(g1)); } /* ** pnt_comp_rand ** input: two points ** output: 1 or -1 randomly chosen. ** error conditions: checks that g1 and g2 are (non-null)points ** ** NOTE: this is used to randomize point lists */ int pnt_comp_rand(node g1, node g2){ if ((pnt_is_point(g1)!=TRUE)||(pnt_is_point(g2)!=TRUE)){ bad_error("Non-PNT nodes in pnt_comp_rand()"); } if (rand_int(0,1)==0) return -1; else return 1; } int pnt_comp_const(node g1, node g2){ if ((pnt_is_point(g1)!=TRUE)||(pnt_is_point(g2)!=TRUE)){ bad_error("Non-PNT nodes in pnt_comp_rand()"); } return 1; } /* ** pnt_lable(node n); ** input: a point n ** outpur: the lable associated with n ** error: checks that n is a (non-null) point */ char *pnt_lable(node n) { if (n == 0 || node_get_type(n, LEFT) != PNT) { bad_error("error: pnt_label() called on non-point\n"); /* will cause an exit */ } return (char *) node_get_ptr(n, LEFT); } /* ** POINT CONFIGURATIONS */ /* ** pcfg_new ** input: none ** output: an empty point configuration. */ node pcfg_new() { node g; g = node_new(); node_set_int(g, 0, PCFG, LEFT); node_set_ptr(g, (void *) 0, NODE, RIGHT); return g; } node pcfg_print(node n) { if (n != 0 && node_get_type(n, LEFT) == PCFG) { printf("<"); node_print((node)node_get_ptr(n, RIGHT)); printf(">"); } else bad_error("error: pcfg_print() called on non-PCFG\n"); return n; } node pcfg_print_short(node n) { if (n == 0 || node_get_type(n, LEFT) != PCFG) bad_error("error: pcfg_print_short() called on non-PCFG\n"); n = (node) node_get_ptr(n, RIGHT); printf("<"); while (n != 0) { printf("%s ", (char *) node_get_ptr(Car(n), LEFT)); n = (node) node_get_ptr(n, RIGHT); } printf(">"); return n; } /* ** pcfg_add ** input: a point "point" ** a point config "config" ** output: TRUE on successfull completion ** (right now failure causes the program to abort) ** side effects: point is added into config ** (which is kept in order according to point lables) */ int pcfg_add(node point, node config) { node ptr; LOCS(1); PUSH_LOC(config); if (config == 0 || point == 0 || node_get_type(config, LEFT) != PCFG || node_get_type(point, LEFT) != PNT){ bad_error("error: pcfg_add() called on non-PCFG\n"); } ptr=Cdr(config); list_insert(point,&ptr,&(pnt_comp_lbl),FALSE); node_set_ptr(config,ptr,NODE,RIGHT); node_set_int(config, node_get_int(config, LEFT) + 1, PCFG, LEFT); POP_LOCS(); return TRUE; } /* ** pcfg_remove ** input: a point "point" ** a point configuration "config" ** a pointer ptr locating "point" in "config" i.e. ** output: TRUE if point is in config ** FALSE if point is not in config ** side effect: if point is in config it is removed from config. ** error conditions: checks that config is non-null pcfg ** pnt is non-null pnt ** Note: ptr should point to the cons node for the point before ** "point" in config's point list, if it doesn't then ** pcfg_remove will find the previous point itself ** */ int pcfg_remove(node point, node config, node ptr) { if (config == 0 ||point == 0|| node_get_type(config, LEFT) != PCFG || node_get_type(point, LEFT) != PNT) bad_error("error: pcfg_add() called on non-PCFG\n"); /* check if location given for point is really right*/ if (Car(Cdr(ptr))!=point) ptr=0; /* find location of point if it is not allready known*/ if (ptr==0) for(ptr=Cdr(config); Car(ptr)!=point && ptr!=0; ptr=Cdr(ptr)){ ; /* null body*/ } if (ptr==0) return FALSE; node_set_ptr(ptr,Cdr(Cdr(ptr)),NODE,RIGHT); node_set_int(config,node_get_int(config,LEFT)-1,PCFG,LEFT); return TRUE; } /* **pcfg_in(node point, node config); ** test if point is in config. point must be given by a pointer ** to a point in config. ** ** Warning: Point must be given by a pointer to a point in config. ** Point_config_in DOES NOT TELL wheather their is a point ** in Config with same coords/lable. */ int pcfg_in(node point, node config) { if (config == 0 || point == 0 || node_get_type(config, LEFT) != PCFG || node_get_type(point, LEFT) != PNT) bad_error("error: pcfg_in() called on non-PCFG\n"); while ((config = Cdr(config)) != 0) if (point == Car(config)) return TRUE; return FALSE; } /* ** Imatrix pcfg_coords(node n, Imatrix R) ** returns a matrix whoose rows are the coordinates of ** points in the configuration. Space for the matrix is ** allocated from R if possible, otherwise R is freed and ** space realocated. */ Imatrix pcfg_coords(node n, Imatrix R) { int i, j; node ptr = n; if (n == 0 || node_get_type(n, LEFT) != PCFG) bad_error("error: pcfg_coords() called on non-PCFG\n"); R = Imatrix_resize(R, pcfg_npts(n), pcfg_dim(n)); for (i = 1; i <= pcfg_npts(n); i++) { ptr = Cdr(ptr); for (j = 1; j <= pcfg_dim(n); j++) *(IMref(R, i, j)) = *(IVref(pnt_coords(Car(ptr)), j)); } return R; } /* ** Imatrix pcfg_M(node n, Imatrix R) ** returns a matrix whoose rows are the coordinates of ** points in the configuration, after translation to put the ** first point at the origen. Space for the matrix is ** allocated from R if possible, otherwise R is freed and ** space realocated. */ Imatrix pcfg_M(node n, Imatrix R) { int i, j; Imatrix P0; node ptr = n; if (n == 0 || node_get_type(n, LEFT) != PCFG) bad_error("error: pcfg_M called on non-PCFG\n"); R = Imatrix_resize(R, pcfg_npts(n) - 1, pcfg_dim(n)); ptr = Cdr(ptr); P0 = pnt_coords(Car(ptr)); for (i = 1; i <= pcfg_npts(n) - 1; i++) { ptr = Cdr(ptr); for (j = 1; j <= pcfg_dim(n); j++) *(IMref(R, i, j)) = *(IVref(pnt_coords(Car(ptr)), j)) - *(IVref(P0, j)); } return R; } /* ** node pcfg_face(node PC, Imatrix norm); ** returns the point configuration consisting of points ** of PC which lie on the face suported by N. */ node pcfg_face(node PC, Imatrix norm) { node Face = 0, ptr = 0; Imatrix M = 0, D = 0; int s, i; LOCS(2); /* save locals */ PUSH_LOC(PC); PUSH_LOC(Face); M = pcfg_coords(PC, M); D = Imatrix_dot(norm, M, D); s = *IMref(D, 1, 1); for (i = 2; i <= IMcols(D); i++) if (*IMref(D, 1, i) < s) s = (*IMref(D, 1, i)); Face = pcfg_new(); ptr = PC; for (i = 1; i <= IMcols(D); i++) { ptr = Cdr(ptr); if (*IMref(D, 1, i) == s) pcfg_add(Car(ptr), Face); } Imatrix_free(D); Imatrix_free(M); POP_LOCS(); return Face; } /* ** is_normal_good(Imatrix normal, Imatrix N) ** determine if the (inner normal) associated to a facet ** satasfies the sign conditions specified in N. ** ** each coordinate of the (inner)normal satasfy the condition ** specified by the corresponding coordinate of N: ** 1: normal[i] must be non-negative ** 2: normal[i] must be positive ** -1: normal[i] must be non-positive ** -2: normal[i] must be negative ** 0: no condition required of normal[i] */ int is_normal_good(Imatrix normal, Imatrix N) { int i; if (N == 0) return TRUE; for (i = 1; i <= IVlength(N); i++) { if (*(IVref(N, i)) == 0) /* Skip */ ; else if (*(IVref(N, i)) * (*IVref(normal, i)) < 0) return FALSE; else if ((*(IVref(normal, i)) == 0) && (abs(*IVref(N, i)) == 2)) return FALSE; } return TRUE; } /* end Pconfig.c */ /**************************************************************************/ /******************** implementations from Pcomplex.c *********************/ /**************************************************************************/ #ifndef PI #define PI (double)3.14159265358979323846264338328 #endif fcomplex Cadd(fcomplex a,fcomplex b) { fcomplex c; c.r=a.r+b.r; c.i=a.i+b.i; return c; } fcomplex Csub(fcomplex a,fcomplex b) { fcomplex c; c.r=a.r-b.r; c.i=a.i-b.i; return c; } fcomplex Cmul(fcomplex a,fcomplex b) { fcomplex c; c.r=a.r*b.r-a.i*b.i; c.i=a.i*b.r+a.r*b.i; return c; } fcomplex ItoC(int i) { fcomplex c; c.r=i; c.i=0.0; return c; } fcomplex DtoC(double i) { fcomplex c; c.r=i; c.i=0.0; return c; } fcomplex Complex(double re, double im) { fcomplex c; c.r=re; c.i=im; return c; } fcomplex Conjg(fcomplex z) { fcomplex c; c.r=z.r; c.i = -z.i; return c; } fcomplex Cdiv(fcomplex a,fcomplex b) { fcomplex c; double r,den; if (fabs(b.r) >= fabs(b.i)) { r=b.i/b.r; den=b.r+r*b.i; c.r=(a.r+r*a.i)/den; c.i=(a.i-r*a.r)/den; } else { r=b.r/b.i; den=b.i+r*b.r; c.r=(a.r*r+a.i)/den; c.i=(a.i*r-a.r)/den; } return c; } fcomplex Cpow(fcomplex a, int d) { int i; fcomplex c; c.r=1.0; c.i=0.0; if (d<0) { a=Cdiv(c,a); d*=-1;} for (i=1;i<=d;i++) c=Cmul(c,a); return c; } double Cabs(fcomplex z) { double x,y,ans,temp; x=fabs(z.r); y=fabs(z.i); if (x == 0.0) ans=y; else if (y == 0.0) ans=x; else if (x > y) { temp=y/x; ans=x*sqrt(1.0+temp*temp); } else { temp=x/y; ans=y*sqrt(1.0+temp*temp); } return ans; } fcomplex Csqrt(fcomplex z) { fcomplex c; double x,y,w,r; if ((z.r == 0.0) && (z.i == 0.0)) { c.r=0.0; c.i=0.0; return c; } else { x=fabs(z.r); y=fabs(z.i); if (x >= y) { r=y/x; w=sqrt(x)*sqrt(0.5*(1.0+sqrt(1.0+r*r))); } else { r=x/y; w=sqrt(y)*sqrt(0.5*(r+sqrt(1.0+r*r))); } if (z.r >= 0.0) { c.r=w; c.i=z.i/(2.0*w); } else { c.i=(z.i >= 0) ? w : -w; c.r=z.i/(2.0*c.i); } return c; } } fcomplex RCmul(double x, fcomplex a) { fcomplex c; c.r=x*a.r; c.i=x*a.i; return c; } void printC(fcomplex c) { if (c.r!=0 && c.i !=0) { if (c.i>0) printf("(%g+%g*I)",c.r,c.i); else printf("(%g-%g*I)",c.r,fabs(c.i)); } else if (c.r!=0) printf("%g",c.r); else if (c.i!=0) printf("(%g*I)",c.i); else printf("0.0"); } /*------------------------------------------------------------------------- function (fcomplex) Croot arguments: n an integer; z a complex number; returns: a primitive nth root of z; -----------------------------------------------------------------------*/ fcomplex RootOfOne(int j, int n) { fcomplex C; C=Complex(cos((2.0*PI*j)/n),sin((2.0*PI*j)/n)); return C;} /*------------------------------------------------------------------------- function (fcomplex) Croot arguments: n an integer; z a complex number; returns: a primitive nth root of z; -----------------------------------------------------------------------*/ fcomplex Croot(fcomplex z, int n) { fcomplex w; double mod,arg,ni=1.0/n; if ((z.i==0)&&(z.r==0)) w=Complex(0.0,0.0); else{ mod=Cabs(z); if (fabs(z.i)>=fabs(z.r)){ arg=acos(z.r/mod); if (z.i<0) arg=-1*arg;} else { arg=asin(z.i/mod); if (z.r<0) arg=PI-arg;} arg=arg/n; mod=fabs(pow(mod,ni)); w=Complex(cos(arg),sin(arg)); w=RCmul(mod,w); } return w;} /* end Pcomplex.c */ /**************************************************************************/ /*********************** implementations from Poly.c **********************/ /**************************************************************************/ void bad_error(char *); int *poly_exp(monomial m, int i){ if (m==0 || i<1 || m->R->n < i ) { printf("i=%d, n=%d\n",i,m->R->n); bad_error("index out of bounds in monomial"); } return &(m->exps[i-1]); } int poly_deg(polynomial1 p){ int i,n,deg=0,tdeg; n=p->R->n; for(i=0;iexps[i]; while((p=p->next)!=0){ tdeg=0; for(i=0;iexps[i]; if (tdeg>deg) deg=tdeg; } return deg; } int *poly_homog(polynomial1 p){ return &(p->homog); } void ring_set_var(Pring R, int n, char *lable){ strncpy(R->vars[n],lable,RING_VAR_L); } char *ring_var(Pring R,int i){return R->vars[i];} void ring_set_def(Pring R, char *lable){ strncpy(R->def,lable,RING_VAR_L); } char *ring_def(Pring R){return R->def;} int poly_dim(monomial m){ if (m==0) bad_error("null monomial in poly_def"); return m->R->n; } int ring_dim(Pring R){ if (R==0) bad_error("null Ring in ring_dim"); return R->n; } int *poly_def(monomial m){ if (m==0) bad_error("null monomial in poly_def"); return &(m->def); } fcomplex *poly_coef(monomial m){ if (m==0) bad_error("null monomial in poly_coef"); return &(m->coef); } monomial poly_next(monomial m){ if (m==0) bad_error("null monomial in poly_next"); return m->next; } monomial poly_set_next(monomial m,monomial m2){ if (m==0) bad_error("null monomial in poly_next"); return (m->next=m2); } Pring poly_ring(monomial m){ if (m==0) bad_error("null monomial in poly_next"); return m->R; } Pring makePR(int n) { int i; Pring a; a=(Pring)mem_malloc(sizeof(struct Pring_tag)); if (a==0) bad_error("malloc failed 1 in make_PR"); a->n=n; a->vars=(char **)mem_malloc(n*sizeof(char *)); if (a->vars==0) bad_error("malloc failed 2 in make_PR"); for(i=0;ivars[i]=(char *)mem_malloc(RING_VAR_L*sizeof(char)); if (a->vars==0) bad_error("malloc failed 3 in make_PR"); } a->def=(char *)mem_malloc(RING_VAR_L*sizeof(char)); if (a->vars==0) bad_error("malloc failed 4 in make_PR"); return a; } Pring free_Pring(Pring R) { int i; mem_free(R->def); for (i=0;in;i++){ mem_free(R->vars[i]);} mem_free( (char *) R->vars); mem_free( R); return 0; } polynomial1 makeP(Pring R) { polynomial1 m; int i,n; n=R->n; m=(polynomial1)mem_malloc(sizeof(struct mono_tag)); if (m==0){ printf("malloc 1 failed: makeP\n"); exit(2); } m->R=R; m->exps=(int *)mem_malloc(n*sizeof(int)); if (m->exps==0){printf(" malloc 2 failed: makeP\n"); exit(2);} for(i=0;iexps[i]=0; m->coef=Complex(0.0,0.0); m->def=0; m->next=0; return m; } polynomial1 freeP(polynomial1 p) { polynomial1 m=p; while (m!=0){ p=p->next; mem_free((char *)m->exps); mem_free((char *)m); m=p; } return 0; } polynomial1 copyM(polynomial1 p) { polynomial1 p1; int i; if (p==0) return 0; p1=makeP(p->R); p1->coef=p->coef; p1->def=p->def; for (i=0;iR->n;i++) p1->exps[i]=p->exps[i]; return p1; } polynomial1 copyP(polynomial1 p) { polynomial1 p1,p2; int i; if (p==0) return 0; p1=makeP(p->R); p2=p1; while (p!=0){ if (p->next!=0) p2->next=makeP(p->R); p2->coef=p->coef; p2->def=p->def; for (i=0;iR->n;i++) p2->exps[i]=p->exps[i]; p=p->next; p2=p2->next; } return p1; } void printP(polynomial1 P) { int i,zt=0; /* DEBUG */ /* printf(" In "); */ while (P!=0){ if (P->coef.i!=0 || P->coef.r!=0){ printC(P->coef); zt=1; /* printf("("); */ for (i=0;iR->n;i++) { /* printf("\n(P->exps([%d])= %d\n", i,P->exps[i]); */ /* printf("%d", P->exps[i]); if (i == P->R->n - 1) printf(")"); else printf(","); */ if (P->exps[i]!=0) { zt=1; printf("*%s",P->R->vars[i]); if (P->exps[i]!=1) { /* printf("^{without P->def-loop}"); */ if (P->exps[i]>0) printf("^%d",P->exps[i]); else printf("(%d)",P->exps[i]); } } } if (P->def!=0){ printf("*%s\n",P->R->def); if (P->def !=1) { printf("^{with P->def-loop}"); if (P->def >0) printf("%d ",P->def); else printf("(%d){second} ",P->def); } } /* if (P->next != 0) printf("+{new mono}\n"); */ if (P->next != 0) printf(" + "); } P=P->next; } if (zt==0) printf("0.0nana"); /* DEBUG */ /* printf(" Out "); */ } int orderMM(polynomial1 P1,polynomial1 P2) { int i,d; if (P1==0 && P2==0) return 0; else if (P1==0) return -1; else if (P2==0) return 1; if (P1->R != P2->R) bad_error("error in order: monomials must belong to same ring"); d=P1->def-P2->def; if (d>0) return 1; else if (d<0) return -1; for (i=0;iR->n;i++) { d=P1->exps[i]-P2->exps[i]; if (d>0) return 1; else if (d<0) return -1; } return 0; } int orderPP(polynomial1 P1,polynomial1 P2) { int i,d; while (P1!=0 && P2!=0){ d=P1->def-P2->def; if (d>0) return 1; else if (d<0) return -1; for (i=0;iR->n;i++) { d=P1->exps[i]-P2->exps[i]; if (d>0) return 1; else if (d<0) return -1; } P1=P1->next; P2=P2->next; } if (P1!=0) return 1; else if (P2 !=0) return -1; else return 0; } polynomial1 ItoP(int c,Pring R) { polynomial1 p; p=makeP(R); p->coef.r=c; return p; } polynomial1 DtoP(double c, Pring R) { polynomial1 p; p=makeP(R); p->coef.r=c; return p; } polynomial1 CtoP(fcomplex c, Pring R) { polynomial1 p; p=makeP(R); p->coef=c; return p; } polynomial1 addPPP(polynomial1 P1, polynomial1 P2, polynomial1 P3) { polynomial1 pt; struct mono_tag A; int d,i; pt=&(A); if (P1==0){ if (P3==0) freeP(P3); return copyP(P2); } if (P2==0){ if (P3==0) freeP(P3); return copyP(P1); } /* if (P1->R != P2->R) bad_error(" polynomial1s in addPPP must have equal rings"); */ A.R=P1->R; A.next=0; while(P1!=0&&P2!=0){ d=orderMM(P1,P2); if (d==0) { A.coef=Cadd(P1->coef,P2->coef); if (Cabs(A.coef)!=0){ pt->next=makeP(A.R); pt=pt->next; pt->coef=A.coef; pt->def=P1->def; for(i=0;in;i++)pt->exps[i]=P1->exps[i]; } P1=P1->next; P2=P2->next; } else if (d==-1){ pt->next=makeP(A.R); pt=pt->next; pt->coef=P2->coef; for(i=0;in;i++)pt->exps[i]=P2->exps[i]; pt->def=P2->def; P2=P2->next; } else { pt->next=makeP(A.R); pt=pt->next; pt->def = P1->def; pt->coef=P1->coef; for(i=0;in;i++)pt->exps[i]=P1->exps[i]; P1=P1->next; } } if (P1!=0) pt->next=copyP(P1); else if (P2!=0) pt->next=copyP(P2); if (P3!=0) freeP(P3); if (A.next==0) A.next=makeP(A.R); return A.next; } polynomial1 subPPP(polynomial1 P1, polynomial1 P2, polynomial1 P3) { polynomial1 pt; struct mono_tag A; int d,i; pt=&(A); if (P1!=0 || P2!=0){ if (P1->R != P2->R) bad_error(" polynomial1s in addPPP must have equal rings"); A.R=P1->R; A.next=0; while(P1!=0&&P2!=0){ d=orderMM(P1,P2); if (d==0) { A.coef=Csub(P1->coef,P2->coef); if (Cabs(A.coef)!=0){ pt->next=makeP(A.R); pt=pt->next; pt->coef=A.coef; pt->def=P1->def; for(i=0;in;i++)pt->exps[i]=P1->exps[i]; } P1=P1->next; P2=P2->next; } else if (d==-1){ pt->next=makeP(A.R); pt=pt->next; pt->coef=RCmul(-1.0,P2->coef); pt->def=P2->def; for(i=0;in;i++)pt->exps[i]=P2->exps[i]; P2=P2->next; } else { pt->next=makeP(A.R); pt=pt->next; pt->coef=RCmul(1.0,P1->coef); pt->def=P1->def; for(i=0;in;i++)pt->exps[i]=P1->exps[i]; P1=P1->next; } } } if (P1!=0) pt->next=copyP(P1); else if (P2!=0) pt->next=mulCPP(Complex(-1.0,0.0),P2,0); if (P3!=0) freeP(P3); if (A.next==0) A.next=makeP(A.R); return A.next; } polynomial1 mulCPP(fcomplex c, polynomial1 P1, polynomial1 P2) { polynomial1 p; if (P1==0) { if (P2!=0) freeP(P2); return 0;} if (P2!=P1 ) { if ( P2 !=0) freeP(P2); P2=copyP(P1);} p=P2; while (p!=0){ p->coef=Cmul(c,p->coef); p=p->next; } return P2; } polynomial1 divCPP(fcomplex c, polynomial1 P1, polynomial1 P2) { polynomial1 p; if (P1==0) { if (P2!=0) freeP(P2); return 0;} if (P2!=P1 ) { if ( P2 !=0) freeP(P2); P2=copyP(P1);} p=P2; while (p!=0){ p->coef=Cdiv(p->coef,c); p=p->next; } return P2; } polynomial1 mulMPP(polynomial1 mi, polynomial1 P1, polynomial1 P2) { polynomial1 p,m=mi; int i,free_m=0; m->R=P1->R; if (P1==0||m==0) { if (P2!=0) freeP(P2); return 0;} if (P1->R!=m->R){ printf("\nRings must be equal in mulMPP"); if (P2!=0) freeP(P2); return 0;} if (P2==m) free_m = 1; if (P2!=P1 ) { if ( P2 !=0 && P2 !=m) freeP(P2); P2=copyP(P1);} p=P2; while (p!=0){ p->coef=Cmul(m->coef,p->coef); p->def+=m->def; for(i=0;iR->n;i++) p->exps[i]+=m->exps[i]; p=p->next; } if (free_m==1) freeP(m); return P2; } polynomial1 divMPP(polynomial1 mi, polynomial1 P1, polynomial1 P2) { polynomial1 p,m=mi; int i,free_m=0; if (P1==0||m==0) { if (P2!=0) freeP(P2); return 0;} if (P1->R!=m->R){ printf("Rings must be equal in divMPP"); if (P2!=0) freeP(P2); return 0;} if (m->next!=0){ printf("divisor must be a monomial in divMPP"); if (P2!=0) freeP(P2); return 0;} if (P2==m) free_m = 1; if (P2!=P1 ) { if ( P2 !=0 && P2 !=m) freeP(P2); P2=copyP(P1);} p=P2; while (p!=0){ p->coef=Cdiv(p->coef,m->coef); p->def-=m->def; for(i=0;iR->n;i++) p->exps[i]-=m->exps[i]; p=p->next; } if (free_m==1) freeP(m); return P2; } polynomial1 mulPPP(polynomial1 P1, polynomial1 P2, polynomial1 P3) { polynomial1 pt2,pt3=0; if (P1==0 || P2==0) { if (P3!=0) freeP(P3); return 0; } /* if (P1->R != P2->R) { if (P3!=0) freeP(P3); bad_error("error in addPP: unequal rings"); } */ while(P1!=0) { pt2=mulMPP(P1,P2,0); pt3=addPPP(pt2,pt3,pt3); freeP(pt2); /* this realy should be done more efficiently */ P1=P1->next; } if (P3!=0) free(P3); return pt3; } polynomial1 expIPP(int x, polynomial1 P, polynomial1 P3) { polynomial1 m,tmp; int i; if (P==0) bad_error("undefined poly in powPIP"); if (x==0) {m=makeP(P->R); m->coef.r=1.0; if (P3!=0) freeP(P3); return m;} if (P->next==0) { m=copyP(P); m->coef=Cpow(m->coef,x); m->def*=x; for(i=0;iR->n;i++) m->exps[i]*=x; if(P3!=0) freeP(P3); return m;} if (x<0) bad_error("powPIP can not raise a polynomial1 to a negative power"); m=copyP(P); for(i=2;i<=x;i++) { tmp=mulPPP(m,P,0); freeP(m); m=tmp;} if (P3!=0) freeP(P3); return m; } polynomial1 unliftP(polynomial1 p) { polynomial1 p1,p2; int i; if (p==0) return 0; p1=makeP(p->R); p2=p1; while (p!=0){ if (p->next!=0) p2->next=makeP(p->R); p2->coef=p->coef; p2->def=0; for (i=0;iR->n;i++) p2->exps[i]=p->exps[i]; p=p->next; p2=p2->next; } return p1; } polynomial1 Homogenize(polynomial1 pi,Pring R) { polynomial1 pt,p; int i = 0; int d = 0; int dp = 0; if (pi==0) bad_error("Homogenize called on null polynomial1"); p=copyP(pi); pt=p; while (pt!=0){ d=0; for (i=0;iR->n-1;i++) d+=pt->exps[i]; if (p==pt) dp=d; else if (dpR=R; pt=pt->next; } pt=p; while (pt!=0){ d=0; for (i=0;iR->n-1;i++) d+=pt->exps[i]; pt->exps[p->R->n-1]=dp-d; pt=pt->next; } return p;} polynomial1 Prog_Eq(Pring R){ polynomial1 p,pt; int i; pt=(p=ItoP(-1,R)); for(i=0;in;i++) { pt->next=ItoP(1,R); pt=pt->next; pt->exps[i]=2; } return p; } /* end Poly.c */ /**************************************************************************/ /********************** implementations from utime.c **********************/ /**************************************************************************/ int set_mark(){ return clock(); } int read_mark(int timeset){ return (clock()-timeset) / CLOCKS_PER_SEC; } /* end utime.c */ /**************************************************************************/ /*********************** implementations from Aset.c **********************/ /**************************************************************************/ /* ** An Aset is an r-tupple of point configurations. It represents ** the support set of a polynomial system, and is a presentation for ** the minkowski sum of the convex hulls of its constituent ** point configurations. ** ** Asets are constructed from nodes as follows: ** _____________ ____________ _____________ ------------ **| ASET | NODE | | INT | NODE | | NODE | NODE | | NODE | NODE ** ------------- ------------ ------------- ------------ **| R | node-|-->| D | node |-->| node | node |->...| node | NULL ** ------------- ------------ --|---------- --|--------- ** point config 1. point config R ** ** */ #define R(A) (node_get_int(A,LEFT)) #define D(A) ((int)node_get_int((node)node_get_ptr(A,RIGHT),LEFT)) #define St(A) ((node)(node_get_ptr(A,RIGHT))) #define C(P) ((node)(node_get_ptr(P,LEFT))) node aset_new(int r, int d) { node A = 0, ptr = 0; LOCS(2); PUSH_LOC(A); PUSH_LOC(ptr); A = node_new(); node_set_int(A, r, ASET, LEFT); node_set_ptr(A, node_new(), NODE, RIGHT); node_set_int((node) Cdr(A), d, INT, LEFT); while ((r--) > 0) ptr = Cons(pcfg_new(), ptr); node_set_ptr((node) Cdr(A), ptr, NODE, RIGHT); POP_LOCS(); return A; } int aset_r(node A) { return R(A); } int aset_dim(node A) { return D(A); } int aset_npts(node A) { int i = 0; A = St(A); while ((A = Cdr(A)) != 0) i += pcfg_npts(Car(A)); return i; } node aset_start_cfg(node ptr) { return Cdr(ptr); } node aset_next_cfg(node * ptr) { *ptr = Cdr(*ptr); return Car(*ptr); } node aset_start_pnt(node ptr) { return Cdr(ptr); } node aset_next_pnt(node * ptr) { *ptr = Cdr(*ptr); return Car(*ptr); } int aset_add(node A, int R, node point) { node ptr = A; LOCS(1); PUSH_LOC(A); if (A == 0) bad_error("Null Aset in aset_add()"); if (point == 0) bad_error("Null point in aset_add()"); if (R >= 1 && R(A) >= R) { ptr = St(A); while ((R--) > 0) ptr = Cdr(ptr); pcfg_add(point, Car(ptr)); } else bad_error("index out of bounds in aset_add()"); POP_LOCS(); return 1; } node aset_new_pt(int N, char *lable) { Imatrix C; node point; C = Ivector_new(N); point = pnt_new(lable, C); return point; } int aset_pnt_set(node point, int i, int j) { return (*IVref((Imatrix) Cdr(point), i) = j); } int aset_pnt_get(node point, int i) { return *IVref((Imatrix) Cdr(point), i); } int aset_unlift(node A) { int d; node ptp, ptc; d = aset_dim(A); A = St(A); while ((ptc = aset_next_cfg(&A)) != 0) while ((ptp = aset_next_pnt(&ptc)) != 0) aset_pnt_set(ptp, d, 0); return 1; } int aset_randlift(node A, int seed, int L, int U) { int d; node ptp, ptc; rand_seed(seed); d = aset_dim(A); A = St(A); while ((ptc = aset_next_cfg(&A)) != 0) while ((ptp = aset_next_pnt(&ptc)) != 0) aset_pnt_set(ptp, d, rand_int(L, U)); return 1; } node aset_print(node A) { int R,D,N,i,first=1; Imatrix Coords; node ptr,ptc; if (A != 0 && node_get_type(A, LEFT) == ASET) { R = R(A); D = D(A); ptr = St(A); while ((ptr = (node) Cdr(ptr)) != 0) { first=1; ptc=C(ptr); N=pcfg_npts(ptc); while((ptc=Cdr(ptc))!=0){ if (first==1){ printf(" <"); first=0; } else printf(" "); Coords=pnt_coords(Car(ptc)); printf("<"); for(i=1;i<=D;i++) { printf(" %d",*IVref(Coords,i)); if (i0) printf(" >, "); else { printf(" >>"); if (--R > 0) printf(","); else printf(" "); } printf(" %% %s \n",(char *)pnt_lable(Car(ptc))); } } } else if (A != 0) bad_error("error: aset_print() called on non-ASET\n"); return A; } node aset_print_short(node A) { int R,N,first=1; node ptr,ptc; if (A != 0 && node_get_type(A, LEFT) == ASET) { R = R(A); ptr = St(A); printf("{ "); while ((ptr = (node) Cdr(ptr)) != 0) { first=1; ptc=C(ptr); N=pcfg_npts(ptc); while((ptc=Cdr(ptc))!=0){ if (first==1){ printf("{"); first=0; } printf(" %s",(char *)pnt_lable(Car(ptc))); if (--N ==0) printf("}"); else printf(","); } if (--R>0)printf(","); else printf(" }"); } } else if (A != 0) bad_error("error: aset_print() called on non-ASET\n"); return A; } node aset_face(node A, Imatrix N) { node ptr = A, ptc = 0, res = 0, rptr = 0; LOCS(2); PUSH_LOC(A); PUSH_LOC(res); res = aset_new(aset_r(A), aset_dim(A)); ptr = St(A); rptr = St(res); while ((ptc = aset_next_cfg(&ptr)) != 0) { rptr = Cdr(rptr); node_set_ptr(rptr, pcfg_face(ptc, N), NODE, LEFT); } POP_LOCS(); return res; } Imatrix aset_type(node A, Imatrix T) { int r = 1, i; Imatrix M = 0; node ptr, ptc; LOCS(1); PUSH_LOC(A); ptr = aset_start_cfg(A); T = Imatrix_resize(T, 1, aset_r(A)); while ((ptc = aset_next_cfg(&ptr)) != 0) { M = pcfg_M(ptc, M); for (i = 1; i <= IMrows(M); i++) *IMref(M, i, IMcols(M)) = 0; *IVref(T, r++) = Imatrix_rref(M, &i); } Imatrix_free(M); POP_LOCS(); return T; } Imatrix aset_M(node A, Imatrix M) { node ptc, ptr, ptp, pt0; int j, r = 1; M = Imatrix_resize(M, aset_npts(A) - aset_r(A), aset_dim(A) - 1); ptr = St(A); while ((ptc = aset_next_cfg(&ptr)) != 0) { pt0 = aset_next_pnt(&ptc); while ((ptp = aset_next_pnt(&ptc)) != 0) { for (j = 1; j <= aset_dim(A) - 1; j++) *IMref(M, r, j) = aset_pnt_get(ptp, j) - aset_pnt_get(pt0, j); r++; } } return M; } /* end Aset.c */ /**************************************************************************/ /********************** implementations from Types.c **********************/ /**************************************************************************/ static int level=0; node node_print(node N) { /*DEBUG */ /* printf("Entering node_print with node_type = %d.\n", node_get_type(N,LEFT)); */ if (node_nullp(N) == TRUE) return N; switch (node_get_type(N, LEFT)) { case IDF: case STR: case ERR: printf("%s", (char *) node_get_ptr(N, LEFT)); break; case IMTX: Imatrix_print((Imatrix)node_get_ptr(N, LEFT)); break; case DMTX: Dmatrix_print((Dmatrix)node_get_ptr(N, LEFT)); break; case PNT: pnt_print(N); break; case PCFG: pcfg_print_short(N); break; case ASET: /* aset_print_short(N); */ aset_print(N); break; case DBL: printf("%f ", node_get_double(N, LEFT)); break; case INT: printf("%d ", node_get_int(N, LEFT)); break; case CELL: printf(""); break; case NODE: if (level++==0)printf("( "); if (node_atomp(Car(N))==FALSE) printf("("); node_print((node) Car(N)); if (node_atomp(Cdr(N))==TRUE&&node_nullp(Cdr(N))==FALSE) printf(" . "); else printf(" "); node_print((node) Cdr(N)); if ((node_atomp(Cdr(N))==TRUE)||(node_nullp(Cdr(N))==TRUE)){ printf(" )"); } level--; break; case PROC: printf("%ld",(long)node_get_ptr(N,LEFT)); break; default: printf("Unknown type %d in Node_Print\n", node_get_type(N, LEFT)); break; } return N; } node atom_int(int val) { node R; R = node_new(); node_set_int(R, val, INT, LEFT); return R; } node atom_double(double val) { node R; R = node_new(); node_set_double(R, val,DBL, LEFT); return R; } node atom_id(char *val) { node R; R = node_new(); node_set_ptr(R, mem_strdup(val), IDF, LEFT); return R; } node atom_proc(node (*prc)(node)) { node R; R = node_new(); node_set_ptr(R, (void *)prc, PROC, LEFT); return R; } node ERRND(char *s) { node ans; ans=node_new(); node_set_ptr(ans,mem_strdup(s),ERR,LEFT); return ans; } node atom_new(char *val, int tp) { node R; R = node_new(); node_set_ptr(R, val, tp, LEFT); return R; } void atom_free(node N) { if (node_nullp(N) == TRUE) return; if (node_atomp(N) != TRUE) return; switch (node_get_type(N, LEFT)) { case ERR: case STR: case IDF: mem_free((char *) node_get_ptr(N, LEFT)); break; case IMTX: Imatrix_free((Imatrix)node_get_ptr(N, LEFT)); break; case DMTX: Dmatrix_free((Dmatrix)node_get_ptr(N, LEFT)); break; case PNT: pnt_free(N); break; case CELL: case ASET: case PCFG: case INT: case NPTR: break; default: printf("Unknown type %d in atom_free\n", node_get_type(N, LEFT)); break; } } int numericP(int t){ switch(t){ case INT: case DBL: case CMPX: case POLY: return TRUE; break; default: return FALSE; } return FALSE; } /* end Types.c */ /**************************************************************************/ /********************* implementations from globals.c *********************/ /**************************************************************************/ #define IN_GLOBALS_C TRUE /* - THIS DIDN'T WORK #define Pel_Out stdout #define Pel_Err stderr #define Pel_In stdin #define Pel_Log stdout */ /* FILE *Pel_Out; FILE *Pel_Err; FILE *Pel_In; FILE *Pel_Log; */ /* Pel_Out = stdout; Pel_Err = stderr; Pel_In = stdin; Pel_Log = stdout; */ /* FILE *Pel_Out = stdout; FILE *Pel_Err = stderr; FILE *Pel_In = stdin; FILE *Pel_Log = stdout; */ char *Pel_LogName = 0; char *FilePrefix = 0; int Cont_Alg=1; int Show_Sys=TRUE; int Show_Xpl=TRUE; /* end globals.c */ /**************************************************************************/ /********************* implementations from Dtypes.c **********************/ /**************************************************************************/ #define S(i) (DVref(S,i)) void xpnt_unscale(xpnt X,Dvector S){ int n,i; fcomplex ctmp; n=(int)xpnt_n(X); for(i=1;i<=n;i++){ ctmp=RCmul(S(i),xpnt_xi(X,i)); xpnt_xi_set(X,i,ctmp); } } #undef S /* ** xpnt_affine ** rescale an xpnt so that its homogenization coordinate has ** value 1 (if possible) otherwise its first non-zero coordinate ** is set to 1. */ void xpnt_affine(xpnt X){ int n,i; fcomplex ctmp; n=(int)xpnt_n(X); if (Cabs(xpnt_h(X))!=0.0){ for(i=1;i<=n;i++){ ctmp=Cdiv(xpnt_xi(X,i),xpnt_h(X)); xpnt_xi_set(X,i,ctmp); } xpnt_h_set(X,Complex(1.0,0.0)); } } /* ** xpnt_normalize ** rescale an xpnt so that it has norm 1 (not including t coord). */ void xpnt_normalize(xpnt X){ int n,i; double abs=0.0; fcomplex ctmp; n=(int)xpnt_n(X); for(i=1;i<=2*n+2;i++){ abs+= DVref(X,i)*DVref(X,i); } abs=1/sqrt(abs); for(i=1;i<=n;i++){ ctmp=RCmul(abs,xpnt_xi(X,i)); xpnt_xi_set(X,i,ctmp); } } /***********************************************************************/ /***************** implementation code from Extremal.h *****************/ /***********************************************************************/ /* ** global storage for Lin prog solver */ int LP_M=0, LP_N=0; Dmatrix LP_A=0, LP_B=0, LP_C=0, LP_X=0,LP_Q=0, LP_R=0, LP_T1=0, LP_T2=0; Ivector LP_basis=0, LP_nonbasis=0; extern double RS_zt; #define X(i) (DVref(LP_X,i)) #define A(i,j) (DMref(LP_A,i,j)) #define B(i) (DVref(LP_B,i)) #define DtypesC(i) (DVref(LP_C,i)) /* ** int pcfg_vertex(node pnt,node PC) ** ** ** return TRUE if pnt is a vertex of PC, ** FALSE otherwise (also if pnt not in PC) ** ** Notes) a)should check its arguments. ** b)ratio,LP,and basis should be pointers to matrices ** of the appropriate type, (they can be 0 to begin ** with). After completion they will point to the space ** allocated for the linear program, this allows vertex ** to be called a number of times without having to ** constantly reallocate blocks of space. ** c)ignores lifting values. ** */ int pcfg_vertex(node pnt, node PC) { int i, j, N, D; node ptr; N = pcfg_npts(PC)-1; D = pcfg_dim(PC)-1; /* ignore last coord ... treat it as a lifting value*/ /* ** initialize basis,nonbasis,X and DtypesC */ for (i = 1; i <= N; i++){ *IVref(LP_nonbasis,i)=i; X(i)=0.0; DtypesC(i)=0.0; } for (i=1; i<= D+1; i++){ *IVref(LP_basis,i)=N+i; X(N+i)=1.0; DtypesC(N+i)=1.0; } /* load matrix for linear program */ ptr = PC; for (i = 1; i <= N; i++) { ptr = Cdr(ptr); if (Car(ptr)==pnt) ptr=Cdr(ptr); /* positive and negative coeficients for points */ for (j = 1; j <= D; j++) { A( j, i) = *IVref(pnt_coords(Car(ptr)), j); } A( D+1,i)=1.0; } for (i=N+1;i<=D+N+1;i++){ for (j=1;j<=D+1;j++) A(j,i)=0.0; } A(D+1,N+1)=1.0; B(D+1)=1.0; for(i=1;i<=D;i++){ A(i,N+1+i)=1.0; B(i)=*IVref(pnt_coords(pnt),i); X(N+1+i)=B(i); } Rsimp(LP_A,LP_B,LP_C,LP_X,LP_basis,LP_nonbasis,LP_R,LP_Q,LP_T1,LP_T2); for(i=N+1;i<=N+1+D;i++) if (X(i)>RS_zt) return TRUE; return FALSE; } #undef X #undef A #undef B #undef DtypesC /* ** pcfg_extremal(node PC) ** Input: A point configuration PC. ** Outut: Same point configuration PC. ** Side Effects: All non-extremal points are removed from PC. ** ** Method: Calls pcfg_vertex on each point to see if it ** is a vertex and removes those that arent. ** ** note: ** The main loop maintains the following invariant conditions ** Car(ptr_nxt) is point being checked ** Cdr(ptr_old) = ptr_nxt */ node pcfg_extremal(node PC) { node ptr_old, ptr_nxt; int N,D; /* allocate space for the linear program and initialize */ N = pcfg_npts(PC)-1; D = pcfg_dim(PC)-1; /* ignore last coord ... treat it as a lifting value*/ LP_M = D+1; LP_N = N+D+1; LP_A = Dmatrix_resize(LP_A, LP_M, LP_N); LP_B = Dmatrix_resize(LP_B, 1, LP_M); LP_C = Dmatrix_resize(LP_C, 1, LP_N); LP_X = Dmatrix_resize(LP_X, 1, LP_N); LP_Q = Dmatrix_resize(LP_Q, LP_M, LP_M); LP_R = Dmatrix_resize(LP_R, LP_M, LP_M); LP_T1 = Dmatrix_resize(LP_T1,1, LP_M); LP_T2 = Dmatrix_resize(LP_T2,1, LP_M); LP_basis = Imatrix_resize(LP_basis,1, LP_M); LP_nonbasis = Imatrix_resize(LP_nonbasis,1, LP_N-LP_M); ptr_nxt=Cdr(PC); ptr_old=PC; while(ptr_nxt != 0) { if (pcfg_vertex(Car(ptr_nxt), PC) != TRUE){ pcfg_remove(Car(ptr_nxt),PC,ptr_old); } else ptr_old= ptr_nxt; ptr_nxt = Cdr(ptr_nxt); } Dmatrix_free(LP_A); LP_A=0; Dmatrix_free(LP_B); LP_B=0; Dmatrix_free(LP_C); LP_C=0; Dmatrix_free(LP_X); LP_X=0; Dmatrix_free(LP_Q); LP_Q=0; Dmatrix_free(LP_R); LP_R=0; Dmatrix_free(LP_T1); LP_T1=0; Dmatrix_free(LP_T2); LP_T2=0; Imatrix_free(LP_basis); LP_basis=0; Imatrix_free(LP_nonbasis); LP_nonbasis=0; return PC; } node aset_extremal(node A) { node ptr, ptc; LOCS(1); PUSH_LOC(A); ptr = aset_start_cfg(A); while ((ptc = aset_next_cfg(&ptr)) != 0) { pcfg_extremal(ptc); } POP_LOCS(); return A; } /***********************************************************************/ /****************** implementation code from RSimp.c *******************/ /***********************************************************************/ /* ** Rsimp revised simplex method (Using Bland's rule) ** and a qr factorization to solve the linear equations ** ** Adapted from algorithms presented in ** Linear Approximations and Extensions ** (theory and algorithms) ** Fang & Puthenpura ** Prentice Hall, Engelwood Cliffs NJ (1993) ** and ** Linear Programming ** Chvatal ** Freeman and Company, New York, 1983 ** ** (developed first in Octave, many thanks to the author) ** ** ** Solve the problem ** minimize C'x, ** subject to A*x=b, x>=0 ** for x,c,b n-vectors, and A an m,n matrix with full row rank ** ** Assumptions: ** A mxn matrix with full row rank. ** b an m matrix. ** c an n-vector. ** x an n-vector holding a basic feasible solution, ** basis m-vector holding indices of the basic variables in x ** nonbasis n-m vector holding the indices not appearing in x. ** ** Returns: ** FAIL if algorithm doesn't terminate. ** UNBD if problem is unbounded ** OPT if optimum found ** efects: ** A,b,c unchanged. ** x basis, nonbasis, hold info describing last basic feasible ** solution. ** Q,R hold qrdecomp of last basis matrix. ** t1,t2 undefined. ** ** */ /* #include "pelutils.h" */ #define verbose 0 #define OPT 0 #define UNBD 1 #define FAIL -1 #define zero_tol RS_zt #define nonbasis(j) (*IVref(nonbasis,j)) #define basis(j) (*IVref(basis,j)) #define AN(i,j) (DMref(A,i,nonbasis(j))) #define AB(i,j) (DMref(A,i,basis(j))) #define CB(i) (DVref(c,basis(i))) #define CN(i) (DVref(c,nonbasis(i))) #define XB(i) (DVref(x,basis(i))) #define XN(i) (DVref(x,nonbasis(i))) #define Y(i) (DVref(t1,i)) #define W(i) (DVref(t2,i)) #define DtypesD(i) (DVref(t2,i)) #define DtypesR(i,j) (DMref(DtypesR,i,j)) #define Q(i,j) (DMref(Q,i,j)) double RS_zt=0.0000001; int Rsimp(Dmatrix A, Dvector b, Dvector c, Dvector x,Ivector basis,Ivector nonbasis, Dmatrix DtypesR, Dmatrix Q, Dvector t1, Dvector t2){ int m,n,i,j,k,l,q,qv; int max_steps=20; double r,a,at; m=(int)DMrows(A); n=(int)DMcols(A); max_steps=4*n; /* ** Dimension assumptions: ** A(m,n) x(n) c(n) b(m) Q(mxm) DtypesR(m,m) t1(m) t2(m) ** basis(m) nonbasis(n-m) */ for(k=0; k<=max_steps;k++){ /* ** Step 0) load new basis matrix and factor it */ for(i=1;i<=m;i++){ for(j=1;j<=m;j++){ DtypesR(i,j)=AB(i,j); } } Dmatrix_GQR(Q,DtypesR); /* ** Step 1) solving system B'*w=c(basis) ** a) forward solve DtypesR'*y=c(basis) */ for(i=1;i<=m;i++){ Y(i)=0.0; for(j=1;j<=i-1;j++){ Y(i)+=DtypesR(j,i)*Y(j); } Y(i)=(CB(i)-Y(i))/DtypesR(i,i); } /* ** b) find w=Q*y ** note: B'*w=(Q*DtypesR)'*Q*y= DtypesR'*(Q'*Q)*y=DtypesR'*y=c(basis) */ for(i=1;i<=m;i++){ W(i)=0.0; for(j=1;j<=m;j++){ W(i)+=Q(i,j)*Y(j); } } /* ** Step 2)find entering variable, ** (use lexicographically first variable with negative reduced cost) */ q=n+1; for(i=1;i<=n-m;i++){ /* calculate reduced cost */ r=CN(i); for(j=1;j<=m;j++){ r-=W(j)*AN(j,i); } if (r<-zero_tol){ if (q==n+1 || nonbasis(i)0) printf("optimal solution found in %d iterations\n",k); return OPT; } /* ** Step 3)Calculate translation direction for q entering ** by solving system B*d=-A(:,nonbasis(q)); ** a) let y=-Q'*A(:,nonbasis(q)); */ for(i=1;i<=m;i++){ Y(i)=0.0; for(j=1;j<=m;j++){ Y(i)-=Q(j,i)*AN(j,q); } } /* ** b) back solve Rd=y (d=R\y) ** note B*d= Q*DtypesR*d=Q*y=Q*-Q'*A(:nonbasis(q))=-A(:,nonbasis(q)) */ for(i=m;i>=1;i--){ DtypesD(i)=0.0; for(j=m;j>=i+1;j--){ DtypesD(i)+=DtypesR(i,j)*DtypesD(j); } DtypesD(i)=(Y(i)-DtypesD(i))/DtypesR(i,i); } /* ** Step 4 Choose leaving variable ** (first variable to become negative, by moving in direction DtypesD) ** (if none become negative, then objective function unbounded) */ a=0; l=0; for(i=1;i<=m;i++){ if (DtypesD(i)<-zero_tol){ at=-1*XB(i)/DtypesD(i); if (l==0 || at0){ printf("Objective function Unbounded (%d iterations)\n",k); } return UNBD; } /* ** Step 5) Update solution and basis data */ XN(q)=a; for(j=1;j<=m;j++){ XB(j)+=a*DtypesD(j); } XB(l)=0.0; /* enforce strict zeroness of nonbasis variables */ qv=nonbasis(q); nonbasis(q)=basis(l); basis(l)=qv; } if (verbose>=0){ printf("Simplex Algorithm did not Terminate in %d iterations\n",k); } return FAIL; } /***********************************************************************/ /******************* implementation code from MSD.c ********************/ /***********************************************************************/ /* ** copyright (c) 1995 Birk Huber */ /* ** MSD.c ** Prune and search based computation of cells of mixed subdivisions */ /* #include "pelutils.h" -Seems to be redundant */ /* node atom_new(); */ /* node set_up_FaceLists(); */ #define msd_out stdout /* was Pel_Out */ /* ********************************************************************* ** Aset_I: internal representation for Asets ** logical layout: ** (indices start at one for all vector typesin Aset_I) ** A_r(A) ---- number of point configs ** A_n(A) ---- dimension (without the lifting value). ** A_m(A) ---- total number of points in Aset ** A_npts(A,i) ---- number of points in ith polytope ** A_pt(A,i,j) ---- return jth point of ith polytope ** A_pt_coords(A,i,j) --- return coordinate vector of jth pnt of ith ptope ** A_pt_coord(A,i,j,k) --- return kth coord of jth pnt of ith ptope ** ** physical layout: ** r,n,m are stored seperatly as integers. ** all points are stored in one C-vector, with indexing information ** stored in one long integer vector brocken up logically as ** |m_1,....,m_r|s1,....,sr| */ #define A_r(A) (A->r) #define A_n(A) (A->n) #define A_m(A) (A->m) #define A_npts(A,r) (((A->store)[(r)-1])) #define A_ptst(A,r) (((A->store)[A_r(A)+(r)-1])) #define A_pt(A,r,i) (((A->pts)[A_ptst(A,r)+(i)-1])) #define A_pt_flat(A,i) (((A->pts)[(i)-1])) #define A_pt_coords(A,i,j) (pnt_coords(A_pt(A,i,j))) #define A_pt_coord(A,i,j,k) (*IVref(A_pt_coords(A,i,j),k)) /* NOW IN pelutils.h typedef struct Aset_Itag{ int r; int n; int m; node *pts; */ /*a vector of points */ /* int *store; }*Aset_I; */ /* ** Internalize_Aset ** Input: an Aset S. ** Output: an internal (Aset_I) representation of S. */ Aset_I internalize_aset(aset S){ Aset_I A; int r=0,pt=0; node ptr,ptc,ptp; if((A=(Aset_I)malloc(sizeof(struct Aset_Itag)))==0) bad_error("malloc failed in internalize_aset"); A_r(A)=aset_r(S); A_n(A)=aset_dim(S)-1; A_m(A)=aset_npts(S); if((A->store=(int *)malloc((2*A_r(A))*sizeof(int)))==0) bad_error("malloc failed in internalize_aset"); if((A->pts=(node *)malloc(A_m(A)*sizeof(node)))==0) bad_error("malloc failed in internalize_aset"); ptr = aset_start_cfg(S); while ((ptc = aset_next_cfg(&ptr)) != 0) { A_npts(A,++r)=0; A_ptst(A,r)=pt; while ((ptp = aset_next_pnt(&ptc)) != 0) { A_npts(A,r)++; A_pt_flat(A,++pt)=ptp; } } return A; } /* ** Aset_I_free ** free all storage allocated to an Aset_I. */ void Aset_I_free(Aset_I A){ if (A!=0){ free((char *)A->store); free((char *)A->pts); free((char *)A); } } /* ** Aset_I_print ** Display internal aset (for debugging purposes) */ void Aset_I_print(Aset_I A){ int i,r; #ifdef LOG_PRINT fprintf(msd_out," R=%d, N=%d, M=%d \n",A_r(A),A_n(A),A_m(A)); fprintf(msd_out," tops = <") #endif ; for(i=1;i<=A_r(A);i++){ #ifdef LOG_PRINT fprintf(msd_out,"%d ",A_npts(A,i)) #endif ; if (i\n"); fprintf(msd_out," sts = <") #endif ; for(i=1;i<=A_r(A);i++){ #ifdef LOG_PRINT fprintf(msd_out,"%d ",A_ptst(A,i)) #endif ; if (i\n") #endif ; for(r=1;r<=A_r(A);r++){ #ifdef LOG_PRINT fprintf(msd_out,"configuration %d :\n",r) #endif ; for(i=1;i<=A_npts(A,r);i++) { pnt_print(A_pt(A,r,i)); } } } /* ***************************************************************** ** Internal representation for mixed cells ** logical layout: ** C_r(C) number of point configs ** C_type(C,i) dimension of ith peice, ** i from 1 to r. ** C_idx(C,i,j) index of jth point of ith peice. ** j from 0 to T[i]. ** ** physical layout: ** store[0] ... store[r-1] hold T. ** store[r] ... store[2r-1] hold indices to first rows of Pt ** store[2r] ... store[3r+n-1] hold Pt ** */ /* NOW IN pelutils.h typedef struct Cell_Itag { int r; int *store; }*Cell_I; */ #define C_r(C) (((C)->r)) #define C_type(C,i) (((C)->store)[(i)-1]) #define C_st(C,i) (((C)->store)[C_r(C)+(i)-1]) #define C_idx(C,r,i) (((C)->store)[C_st(C,r)+(i)]) #define C_pt(A,C,r,i) (A_pt(A,r,C_idx(C,r,i))) #define C_pt_coords(A,C,r,i) (pnt_coords(C_pt(A,C,r,i))) #define C_pt_coord(A,C,r,i,j) (*IVref(C_pt_coords(A,C,r,i),j)) /* ** initialize_cell ** Input: an Aset A, and a Type vector T. ** Output: A blank cell to hold fine mixed type T cells of A */ Cell_I initialize_cell(Aset_I A, Ivector T){ Cell_I C; int i,j; if ((C=(Cell_I)malloc(sizeof(struct Cell_Itag)))==0) bad_error("malloc failed in initialize_cell"); C_r(C)=A_r(A); if((C->store = (int *)malloc((3*C_r(C)+A_n(A))*sizeof(int)))==0) bad_error("malloc failed in initialize_cell"); j=2*C_r(C); /* location of C_Pt(C,1,0) */ for(i=1;i<=C_r(C);i++){ C_type(C,i)=*IVref(T,i); /* copy T into C_type feild */ C_st(C,i)=j; /* set location of C_Pt(C,i,0)*/ j+=C_type(C,i)+1; } /* initialize C_Pt to all zeros (asthetic value only)*/ for(i=1;i<=C_r(C);i++) for(j=0;j<=C_type(C,i);j++) C_idx(C,i,j)=0; return C; } /* ** Cell_I_free ** free all storage allocated to a Cell_I. */ void Cell_I_free(Cell_I C){ if (C!=0){ free((char *)C->store); free((char *)C); } } /* ** Cell_I_print ** display a cells points */ void Cell_I_print(Cell_I C){ int i,j; #ifdef LOG_PRINT fprintf(msd_out,"[") #endif ; for(i=1;i<=C_r(C);i++){ for(j=0;j<=C_type(C,i);j++){ #ifdef LOG_PRINT fprintf(msd_out,"%d",C_idx(C,i,j)) #endif ; if (j| | | -+---> ,,,,,,, ** --+----- --+----- ** Face_1 Face_2 */ node List_Store=0; int List_R=0; node *List_Start; node *List_Ptrs; #define LStart(i) (List_Start[(i)-1]) #define LPtr(i) (List_Ptrs[(i)-1]) /* ** init_Face_List_storeage: ** Input: A number R of lists to create. ** Output: FALSE if error occurs, TRUE otherwise. ** Sets List_R to DtypesR. ** Creates a chain of DtypesR nodes starting at List_Store, (with nodes linked ** through their Left pointers, violating the usual convention for lists) ** The List_Start, and List_Ptr, arrays are created and initialized so that ** the ith entrees point to the ith nodes on the list List_Store. ** The Right Pointer of each of these nodes should be interpereted as a ** pointer to the start of the corresponding list, initialized to 0. */ int init_Face_List_storeage(int r){ node tmp; int i; LOCS(1); PUSH_LOC(List_Store); List_R=r; List_Start=(node *)mem_malloc(r*sizeof(node)); List_Ptrs=(node *)mem_malloc(r*sizeof(node)); for(i=1;i<=r;i++){ tmp=node_new(); node_set_ptr(tmp,(void *)List_Store,NODE,LEFT); node_set_ptr(tmp,(void *)0 ,NODE,RIGHT); List_Store=tmp; LStart(i)=tmp; LPtr(i)=tmp; } POP_LOCS(); return TRUE; } /* ** free_Face_list -- free data storage for the List_Start and List_Ptrs arrays ** reset List_Store and List_R to 0 */ void free_Face_list(){ mem_free((char *)List_Start); mem_free((char *)List_Ptrs); List_Store=0; List_R=0; } /* ** display all faces on face list */ void print_Face_list(){ int i; node ptr; for(i=1;i<=List_R;i++){ ptr=LStart(i); while((ptr=(node)node_get_ptr(ptr,RIGHT))!=0){ Imatrix_print((Imatrix)node_get_ptr(ptr,LEFT)); #ifdef LOG_PRINT fprintf(msd_out,"\n") #endif ; } } } /* ** Push_Face: */ void Push_Face(Imatrix F,int r){ node tmp,ptr; tmp=node_new(); ptr=(node)node_get_ptr(LPtr(r),RIGHT); node_set_ptr(tmp,(void *)F,IMTX,LEFT); node_set_ptr(tmp,(void *)ptr,NODE,RIGHT); node_set_ptr(LPtr(r),(void *)tmp,NODE,RIGHT); } void zeroth_face(int j){ LPtr(j)=LStart(j); } int next_face(Cell_I *C,Aset_I A, int r){ int i; Imatrix F; /* advance pointer */ if (LPtr(r)==0) return 0; LPtr(r)=(node)node_get_ptr(LPtr(r),RIGHT); if (LPtr(r)==0) return 0; /* copy face */ F=(Imatrix)node_get_ptr(LPtr(r),LEFT); for(i=0;i<=C_type(*C,r);i++) C_idx(*C,r,i)=*IVref0(F,i); return 1; } /* ** Intermediate testing -- handles testing for all incomplete cells */ static int MSD_LP_M=0, MSD_LP_N=0; static Dmatrix MSD_LP_A=0, MSD_LP_B=0, MSD_LP_C=0, MSD_LP_X=0; static Dmatrix MSD_LP_Q=0, MSD_LP_R=0, MSD_LP_T1=0, MSD_LP_T2=0; static Ivector MSD_LP_basis=0, MSD_LP_nonbasis=0; /* ** set_up_LP ** Input: An Aset_I A and a Cell_I C ** Output: LP,Ratio, and Basis have enough space reserved for them ** to allow them to hold any of the linear programs ** required by MSD for A and C with only reseting bounds. */ void set_up_LP(Aset_I A, Cell_I C){ MSD_LP_M=A_n(A)+A_r(A); MSD_LP_N=A_m(A); MSD_LP_A = Dmatrix_resize(MSD_LP_A, MSD_LP_M, MSD_LP_N); MSD_LP_B = Dmatrix_resize(MSD_LP_B, 1, MSD_LP_M); MSD_LP_C = Dmatrix_resize(MSD_LP_C, 1, MSD_LP_N); MSD_LP_X = Dmatrix_resize(MSD_LP_X, 1, MSD_LP_N); MSD_LP_Q = Dmatrix_resize(MSD_LP_Q, MSD_LP_M, MSD_LP_M); MSD_LP_R = Dmatrix_resize(MSD_LP_R, MSD_LP_M, MSD_LP_M); MSD_LP_T1 = Dmatrix_resize(MSD_LP_T1,1, MSD_LP_M); MSD_LP_T2 = Dmatrix_resize(MSD_LP_T2,1, MSD_LP_M); MSD_LP_basis = Imatrix_resize(MSD_LP_basis,1, MSD_LP_M); MSD_LP_nonbasis = Imatrix_resize(MSD_LP_nonbasis,1, MSD_LP_N-MSD_LP_M); } void free_LP(){ MSD_LP_M=0; MSD_LP_N=0; Dmatrix_free(MSD_LP_A); MSD_LP_A=0; Dmatrix_free(MSD_LP_B); MSD_LP_B=0; Dmatrix_free(MSD_LP_C); MSD_LP_C=0; Dmatrix_free(MSD_LP_X); MSD_LP_X=0; Dmatrix_free(MSD_LP_Q); MSD_LP_Q=0; Dmatrix_free(MSD_LP_R); MSD_LP_R=0; Dmatrix_free(MSD_LP_T1); MSD_LP_T1=0; Dmatrix_free(MSD_LP_T2); MSD_LP_T2=0; Imatrix_free(MSD_LP_basis); MSD_LP_basis=0; Imatrix_free(MSD_LP_nonbasis); MSD_LP_nonbasis=0; } /* ** Load_LP ** */ #define MSD_A(i,j) (DMref(MSD_LP_A,i,j)) #define MSD_B(i) (DVref(MSD_LP_B,i)) #define MSD_C(i) (DVref(MSD_LP_C,i)) #define MSD_X(i) (DVref(MSD_LP_X,i)) #define MSDbasis(i) (*IVref(MSD_LP_basis,i)) #define MSDnonbasis(i) (*IVref(MSD_LP_nonbasis,i)) void Load_LP(int st,int tp,Cell_I C, Aset_I A){ int cidx,bidx; int i,j,k; int nrows,ncols; int n; /* dimenstion of points (without lifting) */ int tm=0; /* total number of points in configs ts..tp */ int tr=1+tp-st; /* number of distinct configs to consider*/ int tc=0; double tmp; Imatrix coords; /* calculate new matrix dims */ n=A_n(A); for(i=st;i<=tp;i++){ tm+=A_npts(A,i); } nrows=n+tr; ncols=tm+n; MSD_LP_A=Dmatrix_resize(MSD_LP_A,nrows,ncols); MSD_LP_B=Dmatrix_resize(MSD_LP_B,1,nrows); MSD_LP_C=Dmatrix_resize(MSD_LP_C,1,ncols); MSD_LP_X=Dmatrix_resize(MSD_LP_X,1,ncols); MSD_LP_Q=Dmatrix_resize(MSD_LP_Q,nrows,nrows); MSD_LP_R=Dmatrix_resize(MSD_LP_R,nrows,ncols); MSD_LP_T1=Dmatrix_resize(MSD_LP_T1,1,nrows); MSD_LP_T2=Dmatrix_resize(MSD_LP_T2,1,nrows); MSD_LP_basis=Imatrix_resize(MSD_LP_basis,1,nrows); MSD_LP_nonbasis=Imatrix_resize(MSD_LP_nonbasis,1,ncols-nrows); for(j=1;j<=ncols;j++){ MSD_X(j)=0.0; for(i=1;i<=nrows;i++) MSD_A(i,j)=0; } for(i=1;i<=nrows;i++) MSD_B(i)=0; /* ** put n independent collumns at start of lp */ for(j=1;j<=n;j++){ for(i=1;i<=nrows;i++) MSD_A(i,j)=rand_double(0,10); MSD_C(j)=1500.0; } /* ** */ cidx=n; bidx=0; for(i=st;i<=tp;i++){ for(j=1;j<=A_npts(A,i);j++){ MSD_A(1+i-st,cidx+j)=1.0; coords=pnt_coords(A_pt(A,i,j)); for(k=1;k<=n;k++){ MSD_A(tr+k,cidx+j)=*IVref(coords,k); } MSD_C(cidx+j)=*IVref(coords,n+1); } MSD_B(1+i-st)=1.0; tmp=1.0/(C_type(C,i)+1); for(j=0;j<=C_type(C,i);j++){ MSDbasis(++bidx)=cidx+C_idx(C,i,j); MSD_X(cidx+C_idx(C,i,j))=tmp; for(k=1;k<=n;k++){ MSD_B(tr+k)+=tmp*MSD_A(tr+k,cidx+C_idx(C,i,j)); } } cidx+=A_npts(A,i); } for(j=1;j<=n;j++){ if (j<=nrows-bidx) MSDbasis(bidx+j)=j; else MSDnonbasis(j-nrows+bidx)=j; } bidx=bidx-nrows+n; for (i=n-tc+1;i<=ncols;i++) if(MSD_X(i)==0.0)MSDnonbasis(++bidx)=i; } #undef MSD_A #undef MSD_B #undef MSD_C #undef MSD_X #undef MSDbasis #undef MSDnonbasis /* ** Final testing -- Verification of complete cells */ Imatrix M; Imatrix U; Imatrix Norm; int vol; void set_up_Final(int n){ M=Imatrix_new(n,n+1); U=Imatrix_new(n,n); Norm=Imatrix_new(1,n+1); vol=0; } void free_Final(){ Imatrix_free(M); Imatrix_free(U); Imatrix_free(Norm); M=0;Norm=0;U=0;vol=0; } int Final_Check(Aset_I A, Cell_I C){ int i,j,k; int row=0,s0,s1; /* load matrix */ for(i=1;i<=A_r(A);i++){ for(j=1;j<=C_type(C,i);j++){ row++; for(k=1;k<=A_n(A)+1;k++){ *IMref(M,row,k)=C_pt_coord(A,C,i,j,k)-C_pt_coord(A,C,i,0,k); } } } /* factor matrix */ Imatrix_hermite(M,U); /* calculate volume */ vol=1; for(i=1;i<=A_n(A);i++) (vol)*=*IMref(M,i,i); if (vol==0) return FALSE; /* calculate normal and fix direction */ Imatrix_backsolve(M,Norm); if (*IVref(Norm,A_n(A)+1)<0){ for(i=1;i<=A_n(A)+1;i++) *IVref(Norm,i)*=-1; } for(i=1;i<=A_r(A);i++){ /* find offset of first point of cell */ s0=0; for(k=1;k<=A_n(A)+1;k++){ s0+=*IVref(Norm,k)*C_pt_coord(A,C,i,0,k); } /*check that remaining points have same norm */ for(j=1;j<=C_type(C,i);j++){ s1=0; for(k=1;k<=A_n(A)+1;k++){ s1+=*IVref(Norm,k)*C_pt_coord(A,C,i,j,k); } if (s1!=s0){warning("bad normall"); return FALSE;} } /* check that no points have lower offset */ for(j=1;j<=A_npts(A,i);j++){ s1=0; for(k=1;k<=A_n(A)+1;k++){ s1+=(*IVref(Norm,k))*A_pt_coord(A,i,j,k); } if (s10){ ** if ((C_i = next_face(C_i,A_i)!=0) { ** if (i < r){ ** Add rows to simplex tableau to look for C_i ** if (new system is feasible) { ** i++; ** C_i = 0; ** } ** } ** else { ** if (C is full dim and C lies on lower hull ){ ** S=S union {C_1,...C_n} ** } ** } ** } ** else i-- ** } */ node MSD(aset Ast, Ivector T){ Aset_I A; /* internal representation of Ast*/ Cell_I C; /* internal rep of target cell */ int i=1; /* how many fields of C speceifed*/ node Normals=0; /* output normals list */ int mv=0; /* total mixed volume */ LOCS(2); PUSH_LOC(Normals); PUSH_LOC(List_Store); /* input verification should check A and T for consistancy*/ if (T==0) bad_error("type vector must be specified in MSD"); /* ** Initialization */ A=internalize_aset(Ast); C=initialize_cell(A,T); set_up_LP(A,C); set_up_Final(A_n(A)); set_up_FaceLists(A,C); /* ** Iteration */ zeroth_face(1); while(i>0){ if (next_face(&C,A,i)>0){ if (i=0 && cid<=top){ if (C_idx(*C,j,cid)<(A_npts(A,j)-top+cid)){ C_idx(*C,j,cid)++; if (cid0){ Load_LP(i,i,C,A); if ( TRUE==IsLower()){ for(j=1;j<=C_type(C,i);j++){ for(k=1;k<=A_n(A);k++){ *IMref(ML,k,j)=C_pt_coord(A,C,i,j,k)- C_pt_coord(A,C,i,0,k); } } Imatrix_hermite(ML,UL); k=1; for(j=1;j<=C_type(C,i);j++) k*=*IMref(ML,j,j); if (k!=0) { Itmp=Imatrix_new(1,C_type(C,i)+1); for(j=0;j0){ printf("optimal solution found in %d iterations\n",k); } return TRUE; } /* ** Step 3)Calculate translation direction for q entering ** by solving system B*d=-A(:,MSDnonbasis(q)); ** a) let y=-Q'*A(:,MSDnonbasis(q)); */ for(i=1;i<=m;i++){ MSD_Y(i)=0.0; for(j=1;j<=m;j++){ MSD_Y(i)-=MSD_Q(j,i)*MSD_AN(j,q); } } /* ** b) back solve Rd=y (d=R\y) ** note B*d= Q*R*d=Q*y=Q*-Q'*A(:MSDnonbasis(q))=-A(:,MSDnonbasis(q)) */ for(i=m;i>=1;i--){ MSD_D(i)=0.0; for(j=m;j>=i+1;j--){ MSD_D(i)+=MSD_R(i,j)*MSD_D(j); } MSD_D(i)=(MSD_Y(i)-MSD_D(i))/MSD_R(i,i); } /* ** Step 4 Choose leaving variable ** (first variable to become negative, by moving in direction D) */ a=0; l=0; for(i=1;i<=m;i++){ if (MSD_D(i)<-MSDzero_tol){ at=-1*MSD_XB(i)/MSD_D(i); if (l==0 || at0){ printf("Objective function Unbounded (%d iterations)\n",k); } return FAIL; } /* ** Step 5) If step is non-degenerate stop. otherwise update basis */ if (a>=MSDzero_tol){ if (verbose>0){ printf("non-degenerate step after %d iterations\n",k); } return FALSE; } qv=MSDnonbasis(q); MSDnonbasis(q)=MSDbasis(l); MSDbasis(l)=qv; } if (verbose>=0){ printf("Simplex Algorithm did not Terminate in %d iterations\n",k); } return FAIL; } /* end Dtypes.c */ gambit-0.2010.09.01/src/tools/enumpoly/pelutils.h0000644000076500007650000006300011351773322016254 00000000000000/* ***************************************************************** This file, and all other pel*.h and pel*.cc files in the Gambit source code, are derived from the source code for Pelican, an implementation of the Huber-Sturmfels algorithm for solving sparse systems of polynomials written by Birk Huber. That code in turn incorporated the source code for HOMPACK and Qhull, which are included here after being modified in the construction of both Pelican and Gambit. We are grateful to the authors of Pelican, Qhull, and HOMPACK, for code that has been enormously useful in Gambit. More information about Qhull can be obtained from: http://www.geom.edu/software/qhull/ For more information concerning HOMPACK see: http://netlib2.cs.utk.edu/hompack/ ***************************************************************** */ /* This file contains the header information that had been in globals.h, and also the various header files that formerly resided in the Utils subdirectory of the Pelican distribution. We ae gathering it all together with the intent of putting it into a black box, making sure that it has no dependencies on the rest of the code. */ #define LOG_PRINT #ifndef PELUTILS #define PELUTILS #include #include #include #include #include #ifdef __GNUG__ #include #endif // __GNUG__ /* #define Pel_Out stdout #define Pel_Err stderr #define Pel_In stdin #define Pel_Log stdout */ /**************************************************************************/ /********************* definitions from Atom_Types.h **********************/ /**************************************************************************/ /* ** copyright (c) 1995 Birk Huber */ /* ** The types wich can be stored in the left and right fields ** of a node and the integers that represent them: ** ** Note type names should all consist of 3 or 4 CAPITOL letters ** These are not nescessarily constants the interpreter should ** know about but constants wich the diferent modules may need ** to interpret the data sent to them. */ #ifndef ATOM_INC #define ATOM_INC 1 #define NPTR 100 /* A pointer to a node pointer*/ #define NODE 110 /* A node pointer */ #define STR 120 /* a string (currently a pntr to a C-string)*/ #define IDF 121 /* a string (currently a pntr to a C-string)*/ #define ERR 123 /* a string (currently a pntr to a C-string)*/ #define PROC 130 /* Scalor Types */ #define INT 210 /* an int (will one always fit in a (char *)*/ #define DBL 220 /* a double (will it fit ) */ #define CMPX 230 /* NOT SET UP YET a complex */ #define POLY 240 /* NOT SET UP YET a pointer to a polynomial */ /* Vector Types */ #define NMTX 300 /* a pntr to a mtrx of nodeptrs */ #define IMTX 310 /* a pointer to an integer matrix (Imatrix)*/ #define DMTX 320 /* a pntr to a mtrx of doubles */ #define CMTX 330 /* a pntr to a mtrx of complexes */ #define PMTX 340 /* a pntr to a mtrx of Polynomials */ /* Convex Geometry */ #define PNT 510 /* point in affine space */ #define PCFG 520 /* point configuration */ #define ASET 530 /* An Aset */ #define CELL 540 /* An Icell (from cly_package)*/ /* End Type Definitions */ /* some other usefull constants */ #define LEFT 20 #define RIGHT 10 #define TRUE 1 #define FALSE 0 #endif /**************************************************************************/ /************************ definitions from Mem.h **************************/ /**************************************************************************/ /* ** copyright (c) 1995 Birk Huber */ /* ** elements of type node are pointers to an s-expression structure ** whose elements are a left (right)value and a left (right) type. ** The type is an integer, refering to the constants in XXX.h, ** and the left will be a value of the associated type,(stored as ** a char pointer). ** */ #define RIGHT 10 #define LEFT 20 typedef struct node_t *node; typedef struct local_t { struct local_t *next; node *val; } *local_v; #ifdef Mem_Internal struct node_t { int LT, RT, Mark; union { void *ptr; int ival; double dval; } L, R; }; #define Node_LT(n) ((n->LT)) #define Node_L(n) ((n->L)) #define Node_RT(n) ((n->RT)) #define Node_R(n) ((n->R)) #endif #define LOCS(n) struct local_t Loc[(n)]; int loc_ct=0; void node_push_local(local_v loc, node * val); #define PUSH_LOC(V) node_push_local(Loc+(loc_ct++),(&(V))); #define POP_LOCS() while(--loc_ct>=0) node_pop_local(); /* Allocation Functions */ int node_init_store(void); /*reserves space for the node stack */ void node_free_store(void); /*frees node stack*/ node node_new(void); /*allocates a node from stack*/ char *mem_strdup(char *); /*call strdup, with bookkeeping*/ void *mem_malloc(int); /* call malloc,keep running total of calls*/ void mem_free(void *); /* call free, keep running total */ /* ** node_push_local and node_pop_local maintain the ** the garbage collector's list of starting points. ** any function which (indirectly) calls new_node must ** protect any local variables it uses, by putting their ** addresses on the list with node_push_local(&ptr) and ** must have a cooresponding call to node_pop_local before ** returning */ void node_push_local(local_v, node *); void node_pop_local(void); /* ** access functions */ node node_set_ptr(node N,void *v, int tp, int side); node node_set_int(node N,int v, int tp, int side); node node_set_double(node N,double v, int tp, int side); int node_get_int(node N, int side); double node_get_double(node N, int side); void *node_get_ptr(node N, int side); int node_get_type(node g,int side); node Cons(node,node); node Car(node); node Cdr(node); int node_atomp(node); int node_nullp(node); node node_print(node); /**************************************************************************/ /************************ definitions from error.h ************************/ /**************************************************************************/ void bad_error(char *); void warning(char *); /**************************************************************************/ /******************* header information from globals.h ********************/ /**************************************************************************/ #ifndef PI #define PI (double)3.14159265358979323846264338328 #endif #ifndef size_t #define size_t int #endif #define TRUE 1 #define FALSE 0 #define min(i,j) ((i) < (j) ? (i): (j)) #define USE_HOMPACK 1 #define USE_PNEWTON 2 #ifndef IN_GLOBALS_C extern FILE *Pel_Err; extern FILE *Pel_Out; extern FILE *Pel_Log; extern FILE *Pel_In; extern char *Pel_LogName; extern char *FilePrefix; extern int Cont_Alg; extern int Show_Sys; extern int Show_Xpl; #endif /**************************************************************************/ /************************ declarations from Rand.h ************************/ /**************************************************************************/ void rand_seed(long int seedval); int rand_int(int low, int high); double rand_double(int low, int high); double drand48(); void srand48(long int seedval); /**************************************************************************/ /************************ definitions from Dlist.h ************************/ /**************************************************************************/ /* ** Define a list type for safe protection from garbage collection. ** ** L is assumed to be a safe local node variable for the procedure ** main(); After initialization (with Dlist_new()) ** a doubly linked list of nodes is maintained with two operations: ** ** Dlist_add(L,data) --- crates an entree to hold the node data in ** L, inserted at the front of the list, and ** returns the pointer to the list entry. ** Dlist_rem(L,node) --- takes a pointer to a list entry unlinks ** it from the list L and returns the ** original data node. ** Dlist_data(node) -- takes a list entry and returns the ** original data node. ** ** ** DList Header | Dlist Node | ** | | ** ____________ | ------------- | ** |Node | Node | | | Node | Node | next | ** | 0 | ----+----->| | | | -----+--------> | ** ------------ first | ---+--------- | ** | | ! ** | |link | ** | _____________ | ** | | Node | Node | | ** | +--- | | | | ** | ----------+-- | ** | |data | ** | | | */ #define Dnode_link(D) (((node)(D))->L.ptr) #define Dnode_next(D) (((node)D)->R.ptr) #define Dnode_prev(D) (((node)Dnode_link((node)(D)))->L.ptr) #define Dnode_data(D) (((node)Dnode_link((node)(D)))->R.ptr) #define Dlist_new() new_node() #define Dlist_first(L) Dnode_next(L) void Dlist_empty(node L); /* ** invariants: Dnode_next(Dnode_prev(pos)) ==pos ** for all pointers to Dlist node entrees. ** (NOTE: Dnode_next(L) := Dlist_first(L), ** where L is list header) ** ** Dnode_prev(Dnode_next(pos))=pos ** for all non-zero pointers to Dlist node entrees ** and also for list header ** */ node Dlist_add(node L, node data); node Dlist_del(node L, node pos); node Dlist_data(node pos); /**************************************************************************/ /********************** declarations from Dmatrix.h ***********************/ /**************************************************************************/ typedef struct Dmatrix_t *Dmatrix; typedef struct Dmatrix_t *Dvector; #ifdef DMATRIX_FAST struct Dmatrix_t { int store; int nrows; int ncols; double *coords; }; #define DVstore(V) (((V)->store)) #define DVlength(V) (((V)->ncols)) #define DVref1(V,j) (((V)->coords)[(j)-1]) #define DVref0(V,j) (((V)->coords)[j]) #define DVref(V,i) DVref1(V,i) #define DMstore(V) (((V)->store)) #define DMMrows(V) (((V)->store/(V)->ncols)) #define DMrows(V) ((V)->nrows) #define DMcols(V) ((V)->ncols) #define DMelts(V) ((V)->coords) #define DMref1(V,i,j) (((V)->coords)[((i)-1)*DMcols(V)+(j)-1]) #define DMref0(V,i,j) (((V)->coords)[(i)*DMcols(V)+(j)]) #define DMref(V,i,j) DMref1((V),i,j) #else /* ** matrix access macroes */ double DMstore(Dmatrix M); /* maximum #elts available*/ double DMMrows(Dmatrix M); /* maximum #rows */ double DMrows(Dmatrix M); /* number rows stored */ double DMcols(Dmatrix M); /* number cols stored */ double *DMref_P(Dmatrix M,int i,int j); /* acces starting at 1*/ double *DMelts(Dmatrix M); /* acces starting at 1*/ #define DMref0(M,i,j) (*DMref_P(M,i,j)) #define DMref1(M,i,j) (*DMref_P(M,(i)-1,(j)-1)) #define DMref(M,i,j) DMref1(M,i,j) /* ** Vectors are implemented as 1xM matrices, and acces is through ** usual matrix functions via macroes */ #define DVstore(V) (DMstore(V)) /* maximum #elts available */ #define DVlength(V) (DMcols(V)) /* actual #elts stored */ #define DVref1(V,i) (DMref1(V,1,i)) /* acces ith elt (starting at 1)*/ #define DVref0(V,i) (DMref0(V,0,i)) /* acces ith elt (starting at 0)*/ #define DVref(V,i) (DVref1(V,i)) #endif /* ** Constructor/Destructors/Display */ Dmatrix Dmatrix_new(int r, int c); Dmatrix Dmatrix_resize(Dmatrix M, int r, int d); void Dmatrix_free(Dmatrix V); Dmatrix Dmatrix_fprint(FILE *fout,Dmatrix M); #define Dmatrix_print(M) (Dmatrix_fprint(stdout,M)) #define Dvector_print(V) (Dmatrix_fprint(stdout,V)) #define Dvector_fprint(F,V) (Dmatrix_fprint(F,V)) #define Dvector_new(n) (Dmatrix_new(1,n)) #define Dvector_free(V) (Dmatrix_free(V)) /* ** Arithmatic and other operations on Dmatrices */ Dmatrix Dmatrix_add(Dmatrix M1, Dmatrix M2, Dmatrix *M3); #define add_Dvector(V1,V2,V3) add_Dmatrix(V1,V2,V3) Dmatrix Dmatrix_mull(Dmatrix M1, Dmatrix M2, Dmatrix *M3); Dmatrix Dmatrix_dot(Dmatrix M1, Dmatrix M2, Dmatrix M3); int Dvector_dot(Dmatrix M1, Dmatrix M2); int equal_Dmatrix(Dmatrix M1,Dmatrix M2); void Dmatrix_GQR(Dmatrix,Dmatrix); void Dmatrix_Solve(Dmatrix,Dmatrix,int); /* end Dmatrix.h */ /**************************************************************************/ /********************** declarations from Imatrix.h ***********************/ /**************************************************************************/ typedef struct Imatrix_t *Imatrix; typedef struct Imatrix_t *Ivector; #define IMATRIX_FAST 1 #ifdef IMATRIX_FAST struct Imatrix_t { int store; int topc; int topr; int ncols; int *elts; }; #define IVstore(V) (((V)->store)) #define IVlength(V) (((V)->topc)) #define IVref1(V,i) (&((V)->elts[i-1])) #define IVref0(V,i) (&((V)->elts[i])) #define IVref(V,i) IVref1(V,i) #define IMstore(V) (((V)->store)) #define IMMrows(V) (((V)->store/(V)->ncols)) #define IMrows(V) (((V)->topr)) #define IMcols(V) (((V)->topc)) #define IMNcols(V) (((V)->ncols)) #define IMref1(V,i,j) (&(((V))->elts[(i-1)*((V)->ncols)+j-1])) #define IMref0(V,i,j) (&((V)->elts[(i*(V)->ncols)+j])) #define IMref(V,i,j) IMref1(V,i,j) #else /* ** matrix access macroes */ int IMstore(Imatrix M); /* maximum #elts available*/ int IMMrows(Imatrix M); /* maximum #rows */ int IMrows(Imatrix M); /* number rows stored */ int IMcols(Imatrix M); /* number cols stored */ int* IMref1(Imatrix M,int i,int j); /* acces starting at 1 */ #define IMref0(M,i,j) (IMref(M,(i+1),(j+1))) /* acces starting at 0 */ #define IMref(M,i,j) (IMref1((M),i,j)) /* use Mref1 by default */ /* ** Vectors are implemented as 1xM matrices, and acces is through ** usual matrix functions via macroes */ #define IVstore(V) (IMstore(V)) /* maximum #elts available */ #define IVlength(V) (IMcols(V)) /* actual #elts stored */ #define IVref1(V,i) (IMref1(V,1,i)) /* acces ith elt (starting at 1)*/ #define IVref0(V,i) (IMref0(V,0,i)) /* acces ith elt (starting at 0)*/ #define IVref(V,i) (IVref1(V,i)) #endif /* ** Constructor/Destructors/Display */ Imatrix Imatrix_new(int r, int c); Imatrix Imatrix_resize(Imatrix M, int r, int d); Imatrix Imatrix_submat(Imatrix R, int r, int c); void Imatrix_free(Imatrix V); Imatrix Imatrix_fprint(FILE *fout, Imatrix M); #define Imatrix_print(M) (Imatrix_fprint(stdout,M)) #define Ivector_fprint(F,V) (Imatrix_fprint(F,V)) #define Ivector_print(V) (Imatrix_print(V)) #define Ivector_new(n) (Imatrix_new(1,n)) #define Ivector_free(V) (Imatrix_free(V)) /* ** Arithmatic and other operations on Imatrices */ Imatrix Imatrix_add(int i1, Imatrix M1,int i2, Imatrix M2, Imatrix M3); #define add_Ivector(V1,V2,V3) add_Imatrix(V1,V2,V3) Imatrix Imatrix_mul(Imatrix M1, Imatrix M2, Imatrix M3); Imatrix Imatrix_dot(Imatrix M1, Imatrix M2, Imatrix M3); int Ivector_dot(Imatrix M1, Imatrix M2); int Imatrix_equal(Imatrix M1,Imatrix M2); int Imatrix_rref(Imatrix M,int *); int Imatrix_backsolve(Imatrix M,Imatrix Sol); int Imatrix_order(Imatrix M1,Imatrix M2); int Imatrix_gcd_reduce(Imatrix M); int Imatrix_hermite(Imatrix S, Imatrix U); Imatrix Imatrix_dup(Imatrix S,Imatrix storeage); int Imatrix_is_zero(Imatrix S); /* end Imatrix.h */ /**************************************************************************/ /*********************** declarations from Lists.h ************************/ /**************************************************************************/ node list_cat(node,node); node list_push(node,node *); node list_pop(node *); node list_first(node); node list_rest(node); int list_insert(node, node *, int (*comp) (node, node),int uniq); node list_append(node,node *); int list_empty(node); int list_Imatrix_comp(node g1, node g2); node list_cat(node l1,node l2); void xpl_fprint(FILE *fout,node L); /* end Lists.h */ /**************************************************************************/ /********************** declarations from Pconfig.h ***********************/ /**************************************************************************/ /* General purpose implementation of points*/ void *node_get_ptr(node N, int side); #define pnt_coords(g) (((Imatrix)(node_get_ptr(g,RIGHT)))) #define pnt_label(g) ((char *)node_get_ptr(g,LEFT)) #define pnt_dim(g) ((IVlength((Imatrix)node_get_ptr(g,RIGHT)))) /* I don't remember where these are used? */ #define LABLES_ONLY 1 #define COORDS_ONLY 2 #define ALL 3 node pnt_new(char *s,Imatrix m); void pnt_free(node n); int pnt_print(node n); /* Display point */ int pnt_is_point(node n); /* return TRUE if node contains a point */ char * pnt_lable(node n); /* return lable for point */ /* General purpose storage of point configurations */ int node_get_int(node N, int side); #define pcfg_npts(g) ((int)node_get_int(g,LEFT)) #define pcfg_dim(g) ((pnt_dim(Car((node)node_get_ptr(g,RIGHT))))) node pcfg_new(); int pcfg_in(node,node); node pcfg_print(node n); node pcfg_print_short(node n); int pcfg_add(node point, node config); Imatrix point_cfg_coords(node n, Imatrix R); Imatrix pcfg_M(node n, Imatrix R); node pcfg_face(node pc, Imatrix normal); int is_normal_good(Imatrix normal, Imatrix N); int pcfg_remove(node, node,node); /* end Pconfig.h */ /**************************************************************************/ /********************** declarations from Pcomplex.h **********************/ /**************************************************************************/ typedef struct FCOMPLEX {double r,i;} fcomplex; #define Real(c) ((c).r) #define Imag(c) ((c).i) fcomplex ItoC(int i); fcomplex DtoC(double ); fcomplex Cadd(fcomplex, fcomplex); fcomplex Csub(fcomplex, fcomplex); fcomplex Cmul(fcomplex, fcomplex); fcomplex Cpow(fcomplex, int); fcomplex Complex(double, double); fcomplex Conjg(fcomplex); fcomplex Cdiv(fcomplex, fcomplex); double Cabs(fcomplex); fcomplex Csqrt(fcomplex); fcomplex RCmul(double,fcomplex); fcomplex RootOfOne(int,int); fcomplex Croot(fcomplex,int); void printC(fcomplex); /* end Pcomplex.h */ /**************************************************************************/ /*********************** declarations from Poly.h *************************/ /**************************************************************************/ #define RING_VAR_L 10 struct Pring_tag { int n; char **vars; char *def;}; typedef struct Pring_tag *Pring; struct mono_tag { Pring R; int *exps; int def; int homog; fcomplex coef; struct mono_tag *next; int remaining;}; typedef struct mono_tag *monomial; typedef struct mono_tag *polynomial1; void ring_set_var(Pring R, int n, char *lable); void ring_set_def(Pring R, char *lable); char *ring_var(Pring R, int n); char *ring_def(Pring R); int *poly_exp(monomial, int); int *poly_def(monomial); int *poly_homog(monomial); int poly_deg(polynomial1); int poly_dim(monomial); int ring_dim(Pring); Pring poly_ring(monomial); fcomplex *poly_coef(monomial); monomial poly_next(monomial); Pring poly_ring(monomial); Pring makePR(int); Pring free_Pring(Pring); polynomial1 makeP(Pring); polynomial1 freeP(polynomial1 p); /* frees space allocated to a polynomial1*/ polynomial1 copyP(polynomial1 p); polynomial1 copyM(); void printP(polynomial1 P); int orderP(); polynomial1 ItoP(int c,Pring R); polynomial1 DtoP(double c, Pring R); polynomial1 CtoP(fcomplex c, Pring R); polynomial1 addPPP(polynomial1 P1, polynomial1 P2, polynomial1 P3); polynomial1 subPPP(polynomial1 P1, polynomial1 P2, polynomial1 P3); polynomial1 mulPPP(polynomial1 P1, polynomial1 P2, polynomial1 P3); polynomial1 mulCPP(fcomplex c, polynomial1 P1, polynomial1 P2); polynomial1 divCPP(fcomplex c, polynomial1 P1, polynomial1 P2); polynomial1 mulMPP(polynomial1 mi, polynomial1 P1, polynomial1 P2); polynomial1 divMPP(polynomial1 mi, polynomial1 P1, polynomial1 P2); polynomial1 expIPP(int x, polynomial1 P, polynomial1 P3); polynomial1 unliftP(polynomial1 p); polynomial1 Homogenize(); polynomial1 Prog_Eq(); monomial poly_set_next(monomial m,monomial m2); int orderPP(polynomial1 P1,polynomial1 P2); /* end Poly.h */ /**************************************************************************/ /*********************** declarations from utime.h ************************/ /**************************************************************************/ int set_mark(void); int read_mark(int); /* end utime.h */ /**************************************************************************/ /************************ declarations from Aset.h ************************/ /**************************************************************************/ /* end Aset.h */ typedef struct node_t *point; typedef struct node_t *aset; typedef struct node_t *list; typedef struct Imatrix_t *norm_for_Aset; /* creation/display/access */ aset aset_new(int R,int D); aset aset_print(aset); aset aset_print_short(aset); point aset_new_pt(int N,char *lable); int aset_add(aset, int, point ); int aset_r(aset); int aset_dim(aset); int aset_npts(aset); int aset_pnt_set(point, int, int ); int aset_pnt_get(point, int); /* controll for iteration */ node aset_start_pnt(node ptr); point aset_next_pnt(aset *); aset aset_start_cfg(aset); aset aset_next_cfg(aset *); /* Manipulators */ aset aset_face(aset,norm_for_Aset); int aset_randlift(node A, int seed, int L, int U); int aset_unlift(node A); Imatrix aset_type(node A, Imatrix T); Imatrix aset_M(node A, Imatrix M); /**************************************************************************/ /*********************** declarations from Types.h ************************/ /**************************************************************************/ /* node node_print(node N); APPARENTLY REDUNDANT */ node ERRND(char *); void atom_free(node N); node atom_new(char *val, int tp); /* end Types.h */ /**************************************************************************/ /*********************** definitions from Dtypes.h ************************/ /**************************************************************************/ /* ** Dtypes.h--- Definition of access to several types represented ** by Dvectors: (bundeled to make location of fields ** within vector transparent) ** ** xpnt (=) ** represents a point of CP^nxC, ** where ** xj=(xjr+I*xji) is the coordinate associated ** to the jth variable ** h=(hr+I*hi) is the coordinate associated to the ** homog param ** t is the deformation variable. ** ** ptrans (=) ** represents a relation h=c+c1x1+...+cnxn ** usually used to define a random affine chart ** */ typedef Dmatrix xpnt; typedef Dmatrix sclvect; /* ** access macroes treating an xpntM as a complex matrix: ** and an xpnt as a complex vector: */ #define xpnt_new(n) Dvector_new(2*(n)+3) #define xpnt_n(X) ((DVlength(X)-3)/2) #define xpnt_free(X) Dvector_free(X); #define xpnt_h_set(X,C) {DVref(X,1)=(C).r;\ DVref(X,2)=(C).i;} #define xpnt_h(X) (Complex(DVref((X),1),\ DVref((X),2))) #define xpnt_xi(X,i) (Complex(DVref((X),2*(i)+1),\ DVref((X),2*(i)+2))) #define xpnt_xi_set(X,j,C) {DVref((X),2*(j)+1)=(C).r;\ DVref((X),2*(j)+2)=(C).i;} #define xpnt_t(X) (DVref((X),DVlength(X))) #define xpnt_t_set(X,i) (DVref((X),DVlength(X))=i) /* ** initializers, and manipulators, misc */ void xpnt_unscale(xpnt,Dvector); void xpnt_affine(xpnt); /*verified*/ void xpnt_normalize(xpnt X); /***********************************************************************/ /****************** header information from Extremal.h *****************/ /***********************************************************************/ node pcfg_extremal(node PC); /*verified*/ node aset_extremal(node A); /*verified*/ /* end Dtypes.h */ /* header information related to what was MSD.c */ node MSD(aset Ast, Ivector T); typedef struct Aset_Itag{ int r; int n; int m; node *pts; /*a vector of points */ int *store; }*Aset_I; typedef struct Cell_Itag { int r; int *store; }*Cell_I; node set_up_FaceLists(Aset_I A, Cell_I C); int IsLower(); /***********************************************************************/ /******************* header information for RSimp.c ********************/ /***********************************************************************/ int Rsimp(Dmatrix A, Dvector b, Dvector c, Dvector x,Ivector basis,Ivector nonbasis, Dmatrix DtypesR, Dmatrix Q, Dvector t1, Dvector t2); #endif // PELUTILS gambit-0.2010.09.01/src/tools/enumpoly/poly.cc0000644000076500007650000000207111435216102015524 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/poly.cc // Instantiation of polynomial classes // // 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 "libgambit/libgambit.h" #include "poly.imp" //template class polynomial; template class polynomial; template class polynomial; gambit-0.2010.09.01/src/tools/enumpoly/poly.h0000644000076500007650000001405111435216102015367 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/poly.h // Declaration of polynomial classes // // 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 #include "libgambit/rational.h" #include "libgambit/vector.h" #include "interval.h" #include "complex.h" /* This file supplies the template class polynomial These are univariate polynomials with coefficients of class T. Polynomials are implemented as Gambit::List's of coefficients. There is no attempt to maintain sparseness. */ template class polynomial { private: Gambit::List coeflist; public: // constructors and destructor polynomial(const int=-1); polynomial(const polynomial &); polynomial(const Gambit::List &); polynomial(const Gambit::Vector &); polynomial(const T&, const int&); ~polynomial(); // unary operators polynomial operator - () const; polynomial Derivative () const; // binary operators polynomial& operator = (const polynomial& y); bool operator == (const polynomial& y) const; bool operator != (const polynomial& y) const; const T& operator [] (const int index) const; polynomial operator + (const polynomial& y) const; polynomial operator - (const polynomial& y) const; polynomial operator * (const polynomial& y) const; polynomial operator / (const polynomial& y) const; polynomial& operator += (const polynomial& y); polynomial& operator -= (const polynomial& y); polynomial& operator *= (const polynomial& y); polynomial& operator /= (const polynomial& y); polynomial operator % (const polynomial& y) const; // manipulation void ToMonic() ; // polynomial Togdouble() const; polynomial TogDouble() const; // information bool IsZero() const; T EvaluationAt(const T& arg) const; int Degree() const; T LeadingCoefficient() const; Gambit::List CoefficientList() const; polynomial GcdWith(const polynomial&) const; bool IsQuadratfrei() const; bool CannotHaveRootsIn(const gInterval&) const; Gambit::List< gInterval > RootSubintervals(const gInterval&) const; gInterval NeighborhoodOfRoot(const gInterval&, T&) const; Gambit::List< gInterval > PreciseRootIntervals(const gInterval&,T&) const; Gambit::List PreciseRoots(const gInterval&, T&) const; }; /* REMARKS The function cannot_have_roots_in is based on the principle that if f = a_0 + a_1x + ... + a_dx^d with a_0 > 0, then abs(f(t)) >= a_0 - max{abs(a_1),...,abs(a_d)}*(abs(t) + ... + abs(t)^d) and the RHS will be positive whenever //WRONG! abs(t) < a_0/(a_0 + max{abs(a_1),...,abs(a_d)}). */ class complexpoly { private: Gambit::List coeflist; public: // constructors and destructor complexpoly(const int=-1); complexpoly(const complexpoly &); complexpoly(const Gambit::List &); complexpoly(const gComplex&, const int&); ~complexpoly(); // unary operators complexpoly operator - () const; complexpoly Derivative () const; // binary operators complexpoly& operator = (const complexpoly& y); bool operator == (const complexpoly& y) const; bool operator != (const complexpoly& y) const; const gComplex& operator [] (const int index) const; complexpoly operator + (const complexpoly& y) const; complexpoly operator - (const complexpoly& y) const; complexpoly operator * (const complexpoly& y) const; complexpoly operator / (const complexpoly& y) const; complexpoly& operator += (const complexpoly& y); complexpoly& operator -= (const complexpoly& y); complexpoly& operator *= (const complexpoly& y); complexpoly& operator /= (const complexpoly& y); complexpoly operator % (const complexpoly& y) const; // manipulation void ToMonic() ; // information bool IsZero() const; gComplex EvaluationAt(const gComplex& arg) const; int Degree() const; gComplex LeadingCoefficient() const; complexpoly GcdWith(const complexpoly&) const; bool IsQuadratfrei() const; Gambit::List Roots() const; }; gambit-0.2010.09.01/src/tools/enumpoly/poly.imp0000644000076500007650000005201511435216102015727 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/poly.imp // Implementation of polynomial class // // 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 #include "poly.h" //-------------------------------------------------------------------------- // class: polynomial //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // constructors and a destructor //-------------------------------------------------------------------------- template polynomial::polynomial(const polynomial& x) : coeflist(x.coeflist) { } template polynomial::polynomial(const T& coeff, const int& deg) { if (coeff != (T)0) { for (int i = 0; i < deg; i++) coeflist.Append((T)0); coeflist.Append(coeff); } } template polynomial::polynomial(const Gambit::List& coefficientlist) : coeflist(coefficientlist) { } template polynomial::polynomial(const Gambit::Vector& coefficientvector) : coeflist() { for (int i = 1; i <= coefficientvector.Length(); i++) coeflist.Append(coefficientvector[i]); } template polynomial::polynomial(const int deg) : coeflist() { if (deg >= 0) { //gout << "Error is polynomial int constructor.\n"; exit(1); } } template polynomial::~polynomial() { } //-------------------------------------------------------------------------- // operators //-------------------------------------------------------------------------- template polynomial& polynomial::operator= (const polynomial& y) { if (this!=&y) coeflist = y.coeflist; return *this; } template bool polynomial::operator== (const polynomial& y) const { if (Degree() != y.Degree()) return false; else for (int i = 0; i <= Degree(); i++) if (coeflist[i+1] != y.coeflist[i+1]) return false; return true; } template bool polynomial::operator!= (const polynomial& y) const { return !(*this == y); } template const T& polynomial::operator[](const int index) const { return coeflist[index+1]; } template polynomial polynomial::operator+(const polynomial& y) const { if ( Degree() < 0) return polynomial(y); else if (y.Degree() < 0) return polynomial(*this); int max_degree; if (Degree() > y.Degree()) {max_degree = Degree();} else {max_degree = y.Degree();} polynomial sum; for (int i = 0; i <= max_degree; i++) { sum.coeflist.Append((T)0); if (i <= Degree()) sum.coeflist[i+1] += coeflist[i+1]; if (i <= y.Degree()) sum.coeflist[i+1] += y.coeflist[i+1]; } while ( (sum.coeflist.Length() >= 1) && (sum.coeflist[sum.coeflist.Length()] == (T)0) ) sum.coeflist.Remove(sum.coeflist.Length()); return sum; } template polynomial polynomial::operator-(const polynomial& y) const { return polynomial(*this+(-y)); } template polynomial polynomial::operator*(const polynomial &y) const { if (Degree() == -1) return polynomial(*this); else if (y.Degree() == -1) return polynomial(y); int tot_degree = Degree() + y.Degree(); polynomial product; for (int t = 0; t <= tot_degree; t++) product.coeflist.Append((T)0); for (int i = 0; i <= Degree(); i++) for (int j = 0; j <= y.Degree(); j++) product.coeflist[i+j+1] += (*this)[i] * y[j]; return product; } template polynomial polynomial::operator/(const polynomial &q) const { assert(q.Degree() >= 0); polynomial ans; polynomial r = *this; while (r.Degree() >= q.Degree()) { polynomial x(r.LeadingCoefficient()/q.LeadingCoefficient(), r.Degree() - q.Degree()); ans += x; r-=q*x; } return polynomial(ans); } template polynomial& polynomial::operator+=(const polynomial& y) { return ((*this)=(*this)+y); } template polynomial& polynomial::operator-=(const polynomial& y) { return ((*this)=(*this)-y); } template polynomial& polynomial::operator*=(const polynomial& y) { return ((*this)=(*this)*y); } template polynomial& polynomial::operator/=(const polynomial& y) { return ((*this)=(*this)/y); } template polynomial polynomial::operator%(const polynomial &q) const { assert (q.Degree() != -1); polynomial ans; polynomial r = *this; while (r.Degree() >= q.Degree()) { polynomial x(r.LeadingCoefficient()/q.LeadingCoefficient(), r.Degree() - q.Degree()); ans += x; r-=q*x; } return polynomial(r); } template polynomial polynomial::operator- () const { polynomial negation; for (int i = 0; i <= Degree(); i++) negation.coeflist.Append(-coeflist[i+1]); return negation; } template polynomial polynomial::Derivative() const { if (Degree() <= 0) return polynomial(-1); polynomial derivative; for (int i = 1; i <= Degree(); i++) derivative.coeflist.Append((T)i * coeflist[i+1]); return derivative; } //-------------------------------------------------------------------------- // manipulation //-------------------------------------------------------------------------- template void polynomial::ToMonic() { assert (!IsZero()); T lc = LeadingCoefficient(); for (int i = 1; i <= coeflist.Length(); i++) coeflist[i] /= lc; } template polynomial polynomial::TogDouble() const { Gambit::List newcoefs; for (int i = 1; i <= coeflist.Length(); i++) { newcoefs.Append((double)coeflist[i]); } return polynomial(newcoefs); } //-------------------------------------------------------------------------- // information //-------------------------------------------------------------------------- template bool polynomial::IsZero() const { if (coeflist.Length() == 0) return true; else return false; } template T polynomial::EvaluationAt(const T& arg) const { T answer; if (IsZero()) answer = (T)0; else { answer = coeflist[Degree() + 1]; for (int i = Degree(); i >= 1; i--) { answer *= arg; answer += coeflist[i]; } } return answer; } template int polynomial::Degree() const { return coeflist.Length() - 1; } template T polynomial::LeadingCoefficient() const { if (Degree() < 0) return (T)0; else return coeflist[Degree() + 1]; } template Gambit::List polynomial::CoefficientList() const { return coeflist; } template polynomial polynomial::GcdWith(const polynomial& that) const { assert( !this->IsZero() && !that.IsZero() ); polynomial numerator(*this); numerator.ToMonic(); polynomial denominator(that); denominator.ToMonic(); polynomial remainder(numerator % denominator); while (!remainder.IsZero()) { remainder.ToMonic(); numerator = denominator; denominator = remainder; remainder = numerator % denominator; } return denominator; } template bool polynomial::IsQuadratfrei() const { polynomial Df(Derivative()); if (Df.Degree() <= 0) return true; if ( GcdWith(Df).Degree() <= 1 ) return true; else return false; } template bool polynomial::CannotHaveRootsIn(const gInterval& I) const { // get rid of easy cases if (Degree() == -1) return false; else if (Degree() == 0) return true; else if (EvaluationAt(I.LowerBound()) == (T)0) return false; // generate list of derivatives Gambit::List< polynomial > derivs; derivs.Append(Derivative()); int i; for (i = 2; i <= Degree(); i++) derivs.Append(derivs[i-1].Derivative()); T val = EvaluationAt(I.LowerBound()); if (val < (T)0) val = -val; // find max |c_0/Degree()*c_i|^(1/i) int max_index = 0; T base_of_max_index = (T)0; T relevant_factorial = (T)1; for (i = 1; i <= Degree(); i++) { relevant_factorial *= (T)i; T ith_coeff = derivs[i].EvaluationAt(I.LowerBound()) / relevant_factorial; if (ith_coeff < (T)0) ith_coeff = -ith_coeff; if (ith_coeff != (T)0) { T base = val/((T)Degree()*ith_coeff); if (base_of_max_index == (T)0) { max_index = i; base_of_max_index = base; } else if ( pow((T)base,(long)max_index) < pow((T)base_of_max_index,(long)i)) { max_index = i; base_of_max_index = base; } } } assert(base_of_max_index != (T)0); if ( (T)pow((T)I.Length(),(long)max_index) < (T)base_of_max_index ) return true; else return false; } template Gambit::List< gInterval > polynomial::RootSubintervals(const gInterval& I) const { assert ( Degree() >= 0 && IsQuadratfrei() ); polynomial Df = Derivative(); Gambit::List< gInterval > answer; Gambit::List< gInterval > to_be_processed; to_be_processed.Append(I); while (to_be_processed.Length() > 0) { gInterval in_process = to_be_processed.Remove(to_be_processed.Length()); if ( EvaluationAt(in_process.LowerBound()) == (T)0 ) { if (Df.CannotHaveRootsIn(in_process)) { answer.Append(in_process); } else { to_be_processed.Append(in_process.RightHalf()); to_be_processed.Append(in_process.LeftHalf()); } } else if ( EvaluationAt(in_process.UpperBound()) == (T)0 ) { if (Df.CannotHaveRootsIn(in_process)) { if (in_process.UpperBound() == I.UpperBound()) { answer.Append(in_process); } } else { to_be_processed.Append(in_process.RightHalf()); to_be_processed.Append(in_process.LeftHalf()); } } else if (!CannotHaveRootsIn(in_process)) { if (Df.CannotHaveRootsIn(in_process)) { if ( (EvaluationAt(in_process.LowerBound()) < (T)0 && EvaluationAt(in_process.UpperBound()) > (T)0) || (EvaluationAt(in_process.LowerBound()) > (T)0 && EvaluationAt(in_process.UpperBound()) < (T)0) ) { answer.Append(in_process); } } else { to_be_processed.Append(in_process.RightHalf()); to_be_processed.Append(in_process.LeftHalf()); } } } return answer; } template gInterval polynomial::NeighborhoodOfRoot(const gInterval& I, T& error) const { Gambit::List< gInterval > intrvls; intrvls.Append(I); while (intrvls[intrvls.Length()].Length() >= error) { if (EvaluationAt(intrvls[intrvls.Length()].LowerBound()) == (T)0) intrvls.Append(gInterval(intrvls[intrvls.Length()].LowerBound(), intrvls[intrvls.Length()].LowerBound())); else if (EvaluationAt(intrvls[intrvls.Length()].UpperBound()) == (T)0) intrvls.Append(gInterval(intrvls[intrvls.Length()].UpperBound(), intrvls[intrvls.Length()].UpperBound())); else if ( (EvaluationAt(intrvls[intrvls.Length()].LowerBound()) >= (T)0 && EvaluationAt(intrvls[intrvls.Length()].Midpoint ()) <= (T)0) || (EvaluationAt(intrvls[intrvls.Length()].LowerBound()) <= (T)0 && EvaluationAt(intrvls[intrvls.Length()].Midpoint ()) >= (T)0) ) intrvls.Append(intrvls[intrvls.Length()].LeftHalf()); else intrvls.Append(intrvls[intrvls.Length()].RightHalf()); } return intrvls[intrvls.Length()]; // It is, perhaps, possible to speed this up, at least for double's // by introducing Newton's method. } template Gambit::List< gInterval > polynomial::PreciseRootIntervals(const gInterval& I, T& error) const { Gambit::List< gInterval > coarse = RootSubintervals(I); Gambit::List< gInterval > fine; for (int i = 1; i <= coarse.Length(); i++) fine.Append(NeighborhoodOfRoot(coarse[i],error)); return fine; } template Gambit::List polynomial::PreciseRoots(const gInterval& I, T& error) const { Gambit::List roots; polynomial p(*this), factor(*this); while ( p.Degree() > 0 ) { int depth = 1; polynomial probe(p.Derivative()); polynomial current_gcd( p.GcdWith(probe) ); while ( current_gcd.Degree() > 0 ) { depth++; factor = current_gcd; probe = probe.Derivative(); current_gcd = current_gcd.GcdWith(probe); } for (int i = 1; i <= depth; i++) p = p/factor; Gambit::List< gInterval > fine = factor.PreciseRootIntervals(I,error); for (int j = 1; j <= fine.Length(); j++) { T approx = fine[j].LowerBound(); for (int h = 1; h <= 2; h++) { approx -= factor.EvaluationAt(approx) / factor.Derivative().EvaluationAt(approx); // Newton's Method } roots.Append(approx); } factor = p; } return roots; } //-------------------------------------------------------------------------- // class: complexpoly //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // constructors and a destructor //-------------------------------------------------------------------------- complexpoly::complexpoly(const complexpoly& x) : coeflist(x.coeflist) { } complexpoly::complexpoly(const gComplex& coeff, const int& deg) { if (coeff != (gComplex)0) { for (int i = 0; i < deg; i++) coeflist.Append((gComplex)0); coeflist.Append(coeff); } } complexpoly::complexpoly(const Gambit::List& coefficientlist) : coeflist(coefficientlist) { } complexpoly::complexpoly(const int deg) : coeflist() { if (deg >= 0) { //gout << "Error is complexpoly int constructor.\n"; exit(1); } } complexpoly::~complexpoly() { } //-------------------------------------------------------------------------- // operators //-------------------------------------------------------------------------- complexpoly& complexpoly::operator= (const complexpoly& y) { if (this!=&y) coeflist = y.coeflist; return *this; } bool complexpoly::operator== (const complexpoly& y) const { if (Degree() != y.Degree()) return false; else for (int i = 0; i <= Degree(); i++) if (coeflist[i+1] != y.coeflist[i+1]) return false; return true; } bool complexpoly::operator!= (const complexpoly& y) const { return !(*this == y); } const gComplex& complexpoly::operator[](const int index) const { return coeflist[index+1]; } complexpoly complexpoly::operator+(const complexpoly& y) const { if ( Degree() < 0) return complexpoly(y); else if (y.Degree() < 0) return complexpoly(*this); int max_degree; if (Degree() > y.Degree()) {max_degree = Degree();} else {max_degree = y.Degree();} complexpoly sum; for (int i = 0; i <= max_degree; i++) { sum.coeflist.Append((gComplex)0); if (i <= Degree()) sum.coeflist[i+1] += coeflist[i+1]; if (i <= y.Degree()) sum.coeflist[i+1] += y.coeflist[i+1]; } while ( (sum.coeflist.Length() >= 1) && (sum.coeflist[sum.coeflist.Length()] == (gComplex)0) ) sum.coeflist.Remove(sum.coeflist.Length()); return sum; } complexpoly complexpoly::operator-(const complexpoly& y) const { return complexpoly(*this+(-y)); } complexpoly complexpoly::operator*(const complexpoly &y) const { if (Degree() == -1) return complexpoly(*this); else if (y.Degree() == -1) return complexpoly(y); int tot_degree = Degree() + y.Degree(); complexpoly product; for (int t = 0; t <= tot_degree; t++) product.coeflist.Append((gComplex)0); for (int i = 0; i <= Degree(); i++) for (int j = 0; j <= y.Degree(); j++) product.coeflist[i+j+1] += (*this)[i] * y[j]; return product; } complexpoly complexpoly::operator/(const complexpoly &q) const { assert(q.Degree() >= 0); complexpoly ans; complexpoly r = *this; while (r.Degree() >= q.Degree()) { complexpoly x(r.LeadingCoefficient()/q.LeadingCoefficient(), r.Degree() - q.Degree()); ans += x; r-=q*x; } return complexpoly(ans); } complexpoly& complexpoly::operator+=(const complexpoly& y) { return ((*this)=(*this)+y); } complexpoly& complexpoly::operator-=(const complexpoly& y) { return ((*this)=(*this)-y); } complexpoly& complexpoly::operator*=(const complexpoly& y) { return ((*this)=(*this)*y); } complexpoly& complexpoly::operator/=(const complexpoly& y) { return ((*this)=(*this)/y); } complexpoly complexpoly::operator%(const complexpoly &q) const { assert (q.Degree() != -1); complexpoly ans; complexpoly r = *this; while (r.Degree() >= q.Degree()) { complexpoly x(r.LeadingCoefficient()/q.LeadingCoefficient(), r.Degree() - q.Degree()); ans += x; r-=q*x; } return complexpoly(r); } complexpoly complexpoly::operator- () const { complexpoly negation; for (int i = 0; i <= Degree(); i++) negation.coeflist.Append(-coeflist[i+1]); return negation; } complexpoly complexpoly::Derivative() const { if (Degree() <= 0) return complexpoly(-1); complexpoly derivative; for (int i = 1; i <= Degree(); i++) derivative.coeflist.Append((gComplex)i * coeflist[i+1]); return derivative; } //-------------------------------------------------------------------------- // manipulation //-------------------------------------------------------------------------- void complexpoly::ToMonic() { assert (!IsZero()); gComplex lc = LeadingCoefficient(); for (int i = 1; i <= coeflist.Length(); i++) coeflist[i] /= lc; } //-------------------------------------------------------------------------- // information //-------------------------------------------------------------------------- bool complexpoly::IsZero() const { if (coeflist.Length() == 0) return true; else return false; } gComplex complexpoly::EvaluationAt(const gComplex& arg) const { gComplex answer; for (int i = 0; i <= Degree(); i++) { gComplex monom_val = (gComplex)1; for (int j = 1; j <= i; j++) monom_val *= arg; answer += coeflist[i+1] * monom_val; } return answer; } int complexpoly::Degree() const { return coeflist.Length() - 1; } gComplex complexpoly::LeadingCoefficient() const { if (Degree() < 0) return (gComplex)0; else return coeflist[Degree() + 1]; } complexpoly complexpoly::GcdWith(const complexpoly& that) const { assert( !this->IsZero() && !that.IsZero() ); complexpoly numerator(*this); numerator.ToMonic(); complexpoly denominator(that); denominator.ToMonic(); complexpoly remainder(numerator % denominator); while (!remainder.IsZero()) { remainder.ToMonic(); numerator = denominator; denominator = remainder; remainder = numerator % denominator; } return denominator; } bool complexpoly::IsQuadratfrei() const { complexpoly Df(Derivative()); if (Df.Degree() <= 0) return true; if ( GcdWith(Df).Degree() <= 1 ) return true; else return false; } Gambit::List complexpoly::Roots() const { assert (!IsZero()); Gambit::List answer; if (Degree() == 0) return answer; complexpoly deriv(Derivative()); gComplex guess(1.3,0.314159); while (fabs(EvaluationAt(guess)) > 0.00001) { gComplex diff = EvaluationAt(guess)/deriv.EvaluationAt(guess); int count = 0; bool done = false; while (!done) { if ( count < 10 && fabs(EvaluationAt(guess - diff)) >= fabs(EvaluationAt(guess)) ) { diff /= gComplex(4.0,0.0); count++; } else done = true; } if (count == 10) { // gout << "Failure in complexpoly::Roots().\n"; exit(1); } guess -= diff; } answer.Append(guess); Gambit::List lin_form_coeffs; lin_form_coeffs.Append(guess); lin_form_coeffs.Append(gComplex(-1.0,0.0)); complexpoly linear_form(lin_form_coeffs); complexpoly quotient = *this/linear_form; answer += quotient.Roots(); for (int i = 1; i <= answer.Length(); i++) { // "Polish" each root twice answer[i] -= EvaluationAt(answer[i])/deriv.EvaluationAt(answer[i]); answer[i] -= EvaluationAt(answer[i])/deriv.EvaluationAt(answer[i]); } return answer; } gambit-0.2010.09.01/src/tools/enumpoly/prepoly.cc0000644000076500007650000003344311435216102016242 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/prepoly.cc // Implementation of supporting classes for polynomials // // 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 "libgambit/libgambit.h" #include "prepoly.h" //----------------------------------------------------------- // gSpace //----------------------------------------------------------- //------------------------- // Constructors/Destructors //------------------------- gSpace::gSpace(int nvars) : Variables() { Variable *newvar; //assert (nvars >= 0); for (int i = 1; i <= nvars; i++){ newvar = new Variable; newvar->Name = 'n'; newvar->Name += Gambit::ToText(i); newvar->number = i; Variables.Append(newvar); } } gSpace::gSpace(const gSpace &p) : Variables() { Variable *newvar; for (int i = 1; i <= p.Variables.Length(); i++){ newvar = new Variable; newvar->Name = p.Variables[i]->Name; newvar->number = i; Variables.Append(newvar); } } gSpace::~gSpace() { for (int i = 1; i <= Variables.Length(); i++) delete Variables[i]; } //----------------- // Member Functions //----------------- gSpace& gSpace::operator=(const gSpace & rhs) { // gout<<"IF OK, ZAP ME:prepoly.cc7\n";//** if (*this == rhs) return *this; Variables = rhs.Variables; return *this; } int gSpace::Dmnsn(void) const { return Variables.Length(); } Variable * gSpace::VariableWithNumber(int i) const { return Variables[i]; } const std::string & gSpace::GetVariableName(int i) const { // gout<<"IF OK, ZAP ME:prepoly.cc10\n";//** return ((Variables[i])->Name); } void gSpace::SetVariableName(int i, const std::string &s) { (Variables[i])->Name = s; } void gSpace::CreateVariables (int nvars ) { // gout<<"IF OK, ZAP ME:prepoly.cc12\n";//** Variable *var; int n = Variables.Length(); for (int i = 1; i <= nvars; i++) { // gout<<"IF OK, ZAP ME:prepoly.cc13\n";//** var = new Variable; var->Name = 'n'; var->Name += Gambit::ToText(n + i); Variables.Append(var); } } gSpace gSpace::WithVariableAppended() const { // gout<<"IF OK, ZAP ME:prepoly.cc14\n";//** gSpace enlarged(*this); enlarged.CreateVariables(1); return enlarged; } Variable* gSpace::operator[](int i) const { return VariableWithNumber(i); } bool gSpace::operator==(const gSpace & rhs) const { // gout<<"IF OK, ZAP ME:prepoly.cc15\n";//** if (Variables.Length() == rhs.Variables.Length() && Variables == rhs.Variables) return true; else return false; } bool gSpace::operator!=(const gSpace & rhs) const { // gout<<"IF OK, ZAP ME:prepoly.cc16\n";//** return !(*this == rhs); } // - RESTORE WHEN NEEDED // gSpace gSpace::NewFamilyWithoutVariable(int var) // {gout<<"IF OK, ZAP ME:prepoly.cc17\n";//** // gSpace result(NoOfVars - 1); // for (int i = 1; i <= NoOfVars; i++) // {gout<<"IF OK, ZAP ME:prepoly.cc18\n";//** // if (i < var) // result.SetVariableName(i,GetVariableName(i)); // else if (i > var) // result.SetVariableName(i,GetVariableName(i+1)); // } // return result; // } //------------------------------------------------------ // exp_vect //------------------------------------------------------ //------------------------- // Constructors/Destructors //------------------------- exp_vect::exp_vect(const gSpace* p) : Space(p), components(p->Dmnsn()) { for (int i = 1; i <= p->Dmnsn(); i++) components[i] = 0; } exp_vect::exp_vect(const gSpace* p, const int& var, const int& exp) : Space(p), components(p->Dmnsn()) { for (int i = 1; i <= Dmnsn(); i++) components[i] = 0; components[var] = exp; } exp_vect::exp_vect(const gSpace* p, int* exponents) : Space(p), components(p->Dmnsn()) { for (int i = 1; i <= Dmnsn(); i++) components[i] = exponents[i-1]; } exp_vect::exp_vect(const gSpace* p, Gambit::Vector exponents) : Space(p), components(p->Dmnsn()) { for (int i = 1; i <= Dmnsn(); i++) components[i] = exponents[i]; } exp_vect::exp_vect(const gSpace* p, Gambit::Array exponents) : Space(p), components(p->Dmnsn()) { for (int i = 1; i <= Dmnsn(); i++) components[i] = exponents[i]; } exp_vect::exp_vect(const exp_vect* p) : Space(p->Space), components(p->components) { } exp_vect::exp_vect(const exp_vect & p) : Space(p.Space), components(p.components) { } exp_vect::~exp_vect() { // gout << "Gotcha!\n"; } //------------------------- // Operators //------------------------- exp_vect& exp_vect::operator=(const exp_vect & RHS) { if (*this == RHS) return *this; Space = RHS.Space; components = RHS.components; return *this; } int exp_vect::operator[](int index) const { return components[index]; } bool exp_vect::operator==(const exp_vect & RHS) const { //assert (Space == RHS.Space); if (components == RHS.components) return true; else return false; } bool exp_vect::operator!=(const exp_vect & RHS) const { return !(*this == RHS); } bool exp_vect::operator<=(const exp_vect & RHS) const { //assert (Space == RHS.Space); for (int i = 1; i <= Dmnsn(); i++) if (components[i] > RHS.components[i]) return false; return true; } bool exp_vect::operator>=(const exp_vect & RHS) const { //assert (Space == RHS.Space); for (int i = 1; i <= Dmnsn(); i++) if (components[i] < RHS.components[i]) return false; return true; } bool exp_vect::operator< (const exp_vect & RHS) const { return !(*this >= RHS); } bool exp_vect::operator> (const exp_vect & RHS) const { return !(*this <= RHS); } exp_vect exp_vect::operator- () const { exp_vect tmp(Space); for (int i = 1; i <= Dmnsn(); i++) tmp.components[i] = -components[i]; return tmp; } exp_vect exp_vect::operator+ (const exp_vect & credit) const { //assert (Space == credit.Space); exp_vect tmp(Space); for (int i = 1; i <= Dmnsn(); i++) tmp.components[i] = components[i] + credit.components[i]; return tmp; } exp_vect exp_vect::operator- (const exp_vect & debit) const { //assert (Space == debit.Space); exp_vect tmp(Space); for (int i = 1; i <= Dmnsn(); i++) tmp.components[i] = components[i] - debit.components[i]; return tmp; } void exp_vect::operator+=(const exp_vect & credit) { //assert (Space == credit.Space); for (int i = 1; i <= Dmnsn(); i++) components[i] += credit.components[i]; } void exp_vect::operator-=(const exp_vect & debit) { //assert (Space == debit.Space); for (int i = 1; i <= Dmnsn(); i++) components[i] -= debit.components[i]; } //---------------------------- // Other Operations //---------------------------- exp_vect exp_vect::LCM(const exp_vect & arg2) const { //assert (Space == arg2.Space); exp_vect tmp(Space); for (int i = 1; i <= Dmnsn(); i++) if (components[i] < arg2.components[i]) tmp.components[i] = arg2.components[i]; else tmp.components[i] = components[i]; return tmp; } exp_vect exp_vect::WithVariableAppended(const gSpace* EnlargedSpace) const { exp_vect tmp(EnlargedSpace); for (int i = 1; i <= Dmnsn(); i++) tmp.components[i] = components[i]; tmp.components[Dmnsn() + 1] = 0; return tmp; } exp_vect exp_vect::AfterZeroingOutExpOfVariable(int& varnumber) const { exp_vect tmp(*this); tmp.components[varnumber] = 0; return tmp; } exp_vect exp_vect::AfterDecrementingExpOfVariable(int& varnumber) const { exp_vect tmp(*this); tmp.components[varnumber]--; return tmp; } //-------------------------- // Information //-------------------------- int exp_vect::Dmnsn() const { return Space->Dmnsn(); } bool exp_vect::IsPositive() const { // gout<<"IF OK, ZAP ME:prepoly.cc40\n";//** for (int i = 1; i <= Dmnsn(); i++) if (components[i] <= 0) return false; return true; } bool exp_vect::IsNonnegative() const { // gout<<"IF OK, ZAP ME:prepoly.cc41\n";//** for (int i = 1; i <= Dmnsn(); i++) if (components[i] < 0) return false; return true; } bool exp_vect::IsConstant() const { for (int i = 1; i <= Dmnsn(); i++) if ((*this)[i] > 0) return false; return true; } bool exp_vect::IsMultiaffine() const { for (int i = 1; i <= Dmnsn(); i++) if ((*this)[i] > 1) return false; return true; } bool exp_vect::IsUnivariate() const { int no_active_variables = 0; for (int i = 1; i <= Dmnsn(); i++) if ((*this)[i] > 0) no_active_variables++; if (no_active_variables == 1) return true; else return false; } int exp_vect::SoleActiveVariable() const { int sole_active_variable = 0; for (int i = 1; i <= Dmnsn(); i++) if ((*this)[i] > 0) { //assert(sole_active_variable == 0); sole_active_variable = i; } //assert (sole_active_variable > 0); return sole_active_variable; } int exp_vect::TotalDegree() const { int exp_sum = 0; for (int i = 1; i <= Dmnsn(); i++) exp_sum += (*this)[i]; return exp_sum; } bool exp_vect::Divides(const exp_vect& n) const { for (int i = 1; i <= Dmnsn(); i++) if ((*this)[i] > n[i]) return false; return true; } bool exp_vect::UsesDifferentVariablesThan(const exp_vect& n) const { for (int i = 1; i <= Dmnsn(); i++) if ( ((*this)[i] > 0) && (n[i] > 0) ) return false; return true; } //-------------------------- // Manipulation //-------------------------- void exp_vect::SetExp(int varno, int pow) { //assert (1 <= varno && varno <= Dmnsn() && 0 <= pow); components[varno] = pow; } void exp_vect::ToZero() { for (int i = 1; i <= Dmnsn(); i++) components[i] = 0; } //------------------------------------------------------ // term_order //------------------------------------------------------ //------------------- // Possible Orderings //------------------- bool lex(const exp_vect & LHS, const exp_vect & RHS) { for (int i = 1; i <= LHS.Dmnsn(); i++) if (LHS[i] < RHS[i]) return true; else if (LHS[i] > RHS[i]) return false; return false; } bool reverselex(const exp_vect & LHS, const exp_vect & RHS) { for (int i = LHS.Dmnsn(); i >= 1; i--) if (LHS[i] < RHS[i]) return true; else if (LHS[i] > RHS[i]) return false; return false; } bool deglex(const exp_vect & LHS, const exp_vect & RHS) { if (LHS.TotalDegree() < RHS.TotalDegree()) return true; else if (LHS.TotalDegree() > RHS.TotalDegree()) return false; for (int i = 1; i <= LHS.Dmnsn(); i++) if (LHS[i] < RHS[i]) return true; else if (LHS[i] > RHS[i]) return false; return false; } bool reversedeglex(const exp_vect & LHS, const exp_vect & RHS) { if (LHS.TotalDegree() < RHS.TotalDegree()) return true; else if (LHS.TotalDegree() > RHS.TotalDegree()) return false; for (int i = LHS.Dmnsn(); i >= 1; i--) if (LHS[i] < RHS[i]) return true; else if (LHS[i] > RHS[i]) return false; return false; } bool degrevlex(const exp_vect & LHS, const exp_vect & RHS) { if (LHS.TotalDegree() < RHS.TotalDegree()) return true; else if (LHS.TotalDegree() > RHS.TotalDegree()) return false; for (int i = LHS.Dmnsn(); i >= 1; i--) if (LHS[i] < RHS[i]) return false; else if (LHS[i] > RHS[i]) return true; return false; } bool reversedegrevlex(const exp_vect & LHS, const exp_vect & RHS) { if (LHS.TotalDegree() < RHS.TotalDegree()) return true; else if (LHS.TotalDegree() > RHS.TotalDegree()) return false; for (int i = 1; i <= LHS.Dmnsn(); i++) if (LHS[i] < RHS[i]) return false; else if (LHS[i] > RHS[i]) return true; return false; } //------------------------- // Constructors/Destructors //------------------------- term_order::term_order(const gSpace* p, ORD_PTR act_ord) : Space(p), actual_order(act_ord) { } term_order::term_order(const term_order & p) : Space(p.Space), actual_order(p.actual_order) { } term_order::~term_order() { // gout << "Sihonara, sucker ... \n"; } //------------------------- // Operators //------------------------- term_order& term_order::operator=(term_order & RHS) { // gout<<"IF OK, ZAP ME:prepoly.cc50\n";//** if (*this == RHS) return *this; Space = RHS.Space; actual_order = RHS.actual_order; return *this; } bool term_order::operator==(const term_order & RHS) const { return (Space == RHS.Space && actual_order == RHS.actual_order); } bool term_order::operator!=(const term_order & RHS) const { // gout<<"IF OK, ZAP ME:prepoly.cc52\n";//** return !(*this == RHS); } //------------------------- // Comparisons //------------------------- bool term_order::Less(const exp_vect & LHS, const exp_vect & RHS) const { return (*actual_order)(LHS, RHS); } bool term_order::LessOrEqual(const exp_vect & LHS, const exp_vect & RHS) const { return ((*actual_order)(LHS, RHS) || LHS == RHS); } bool term_order::Greater(const exp_vect & LHS, const exp_vect & RHS) const { return !(LessOrEqual(LHS, RHS)); } bool term_order::GreaterOrEqual(const exp_vect & LHS, const exp_vect & RHS) const { // gout<<"IF OK, ZAP ME:prepoly.cc56\n";//** return !(Less(LHS, RHS)); } //------------------------------------------- // Manipulation and Information //------------------------------------------- term_order term_order::WithVariableAppended(const gSpace* ExtendedSpace) const { return term_order(ExtendedSpace,actual_order); } gambit-0.2010.09.01/src/tools/enumpoly/prepoly.h0000644000076500007650000001503011435216102016074 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/prepoly.h // Declaration of supporting classes for polynomials // // 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 PREPOLY_H #define PREPOLY_H #include #include "libgambit/libgambit.h" /* The classes in this file are prior to the notion of a multivariate polynomial. First of all, one needs a space which the polynomials refer to. This is given by the notion of a gSpace. A polynomial is a sum of monomials, where each monomial is a coefficient multiplied by a power product, and each power product is the vector of variables "raised" by an exponent vector. The exponent vectors play a special role in many algorithms, especially those associated with Groebner bases, and they have a class. Finally, the notion of a term order on the set of exponent vector, which encompasses potentially infinitely many distinct orders, seems best implemented through a class that delivers a full menu of services built on top of a pointer to a function for computing an order. */ // ************************* // gSpace declaration // ************************* struct Variable { std::string Name; int number; }; class gSpace { private: Gambit::Array < Variable * > Variables; public: gSpace(int nvars = 0); gSpace(const gSpace &); ~gSpace(); // operators gSpace& operator=(const gSpace & rhs); Variable* operator[](int) const; bool operator==(const gSpace & rhs) const; bool operator!=(const gSpace & rhs) const; // information int Dmnsn(void) const; Variable* VariableWithNumber(int) const; const std::string& GetVariableName(int) const; gSpace WithVariableAppended() const; // manipulation void SetVariableName(int, const std::string &); void CreateVariables (int nvars = 1); }; // *********************** // class exp_vect // *********************** /* Exponent vectors are vectors of integers. In specifying operators we take the view that addition, subtraction, and order are defined, but not inner or scalar products. */ class exp_vect { private: const gSpace* Space; Gambit::Vector components; public: exp_vect(const gSpace*); exp_vect(const gSpace*, const int&, const int&); // x_i^j exp_vect(const gSpace*, int*); exp_vect(const gSpace*, Gambit::Vector); exp_vect(const gSpace*, Gambit::Array); exp_vect(const exp_vect*); exp_vect(const exp_vect&); ~exp_vect(); // Operators exp_vect& operator=(const exp_vect & RHS); int operator[](int index) const; bool operator==(const exp_vect& RHS) const; bool operator!=(const exp_vect& RHS) const; bool operator<=(const exp_vect& RHS) const; bool operator>=(const exp_vect& RHS) const; bool operator< (const exp_vect& RHS) const; bool operator> (const exp_vect& RHS) const; exp_vect operator - () const; exp_vect operator + (const exp_vect &) const; exp_vect operator - (const exp_vect &) const; void operator += (const exp_vect &); void operator -= (const exp_vect &); // Other operations exp_vect LCM(const exp_vect &) const; exp_vect WithVariableAppended(const gSpace*) const; exp_vect AfterZeroingOutExpOfVariable(int&) const; exp_vect AfterDecrementingExpOfVariable(int&) const; // Information int Dmnsn() const; bool IsPositive() const; bool IsNonnegative() const; bool IsConstant() const; bool IsMultiaffine() const; bool IsUnivariate() const; int SoleActiveVariable() const; int TotalDegree() const; bool Divides(const exp_vect&) const; bool UsesDifferentVariablesThan(const exp_vect&) const; // Manipulation void SetExp(int varno, int pow); void ToZero(); }; // *********************** // class term_order // *********************** /* A term order is a total order of the set of exponent vectors associated with a particular variable list, that has the properties: a) 1 < alpha for all alpha \ne 1; b) if alpha < beta, then alpha + gamma < beta + gamma for all gamma >= 0. In our implementation we take the view that the order itself is a variable of an object of the class, and implement this in terms of pointers to functions. */ // THE FOLLOWING FUNCTIONS SHOULD BE VIEWED AS PRIVATE MEMBERS OF // class term_order I WAS BAFFLED AS TO HOW TO HAVE A MEMBER THAT // IS A POINTER-TO-OTHER-MEMBER-FUNCTION typedef bool (*ORD_PTR)(const exp_vect &, const exp_vect &); bool lex(const exp_vect &, const exp_vect &); bool reverselex(const exp_vect &, const exp_vect &); bool deglex(const exp_vect &, const exp_vect &); bool reversedeglex(const exp_vect &, const exp_vect &); bool degrevlex(const exp_vect &, const exp_vect &); bool reversedegrevlex(const exp_vect &, const exp_vect &); class term_order { private: const gSpace* Space; ORD_PTR actual_order; public: term_order(const gSpace*, ORD_PTR); term_order(const term_order &); ~term_order(); // Operators term_order& operator=(term_order & RHS); bool operator==(const term_order & RHS) const; bool operator!=(const term_order & RHS) const; // Comparisons invoking the underlying order bool Less (const exp_vect &, const exp_vect &) const; bool LessOrEqual (const exp_vect &, const exp_vect &) const; bool Greater (const exp_vect &, const exp_vect &) const; bool GreaterOrEqual(const exp_vect &, const exp_vect &) const; // Manipulation and Information term_order WithVariableAppended(const gSpace*) const; }; #endif // PREPOLY_H gambit-0.2010.09.01/src/tools/enumpoly/quiksolv.cc0000644000076500007650000000204311435216102016415 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/quiksolv.cc // Instantiations of quick-solver classes // // 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 "libgambit/libgambit.h" #include "quiksolv.imp" //template class QuikSolv; template class QuikSolv; gambit-0.2010.09.01/src/tools/enumpoly/quiksolv.h0000644000076500007650000001543011435216102016263 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/quiksolv.h // Interface to quick-solver classes // // 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 QUIKSOLV_H #define QUIKSOLV_H #include "libgambit/libgambit.h" #include "odometer.h" #include "gsolver.h" #include "rectangl.h" #include "gpoly.h" #include "gpolylst.h" #include "gpartltr.h" #include "pelqhull.h" #include "pelclass.h" /* The (optimistically named) class described in this file is a method of finding the roots of a system of polynomials and inequalities, with equal numbers of equations and unknowns, that lie inside a given rectangle. The general idea is to first ask whether the Taylor's series information at the center of the rectangle precludes the existence of roots, and if it does not, whether Newton's method leads to a root, and if it does, whether the Taylor's series information at the root precludes the existence of another root. If the roots in the rectangle are not resolved by these queries, the rectangle is subdivided into 2^d subrectangles, and the process is repeated on each. This continues until it has been shown that all roots have been found, or a predetermined search depth is reached. The bound on depth is necessary because the procedure will not terminate if there are singular roots. */ /* The main constructor for this takes a gPolyList. The list must be at least as long as the dimension Dmnsn() of the space of the system. The first Dmnsn() polynomials are interpreted as equations, while remaining polynomials are interpreted as inequalities in the sense that the polynomial is required to be nonnegative. */ // *********************** // class QuikSolv // *********************** template class QuikSolv { private: const gPolyList System; const gPolyList gDoubleSystem; const int NoEquations; const int NoInequalities; const ListOfPartialTrees TreesOfPartials; bool HasBeenSolved; Gambit::List > Roots; const bool isMultiaffine; const Gambit::RectArray Equation_i_uses_var_j; // Supporting routines for the constructors Gambit::RectArray Eq_i_Uses_j() const; // Get Roots Using Pelican bool AllRealRootsFromPelican(const gPolyList &, Gambit::List > &) const; bool PelicanRoots(const gRectangle &, Gambit::List > &) const; // Check whether roots are impossible bool SystemHasNoRootsIn(const gRectangle& r, Gambit::Array&) const; // Ask whether Newton's method leads to a root bool NewtonRootInRectangle( const gRectangle&, Gambit::Vector&) const; bool NewtonRootNearRectangle(const gRectangle&, Gambit::Vector&) const; // Ask whether we can prove that there is no root other than // the one produced by the last step double MaxDistanceFromPointToVertexAfterTransformation( const gRectangle&, const Gambit::Vector&, const Gambit::SquareMatrix&) const; bool HasNoOtherRootsIn(const gRectangle&, const Gambit::Vector&, const Gambit::SquareMatrix&) const; // Combine the last two steps into a single query bool NewtonRootIsOnlyInRct(const gRectangle&, Gambit::Vector&) const; // Recursive parts of recursive methods void FindRootsRecursion( Gambit::List >*, const gRectangle&, const int&, Gambit::Array&, int &iterations, int depth, const int&, int*) const; const bool ARootExistsRecursion(const gRectangle&, Gambit::Vector&, const gRectangle&, Gambit::Array&) const; public: class NewtonError : public Gambit::Exception { public: virtual ~NewtonError(); std::string GetDescription(void) const; }; QuikSolv(const gPolyList &); QuikSolv(const gPolyList &, const int &); QuikSolv(const QuikSolv &); ~QuikSolv(); // Operators QuikSolv& operator= (const QuikSolv &); bool operator==(const QuikSolv &) const; bool operator!=(const QuikSolv &) const; // Information inline const gSpace* AmbientSpace() const { return System.AmbientSpace(); } inline const term_order* TermOrder() const { return System.TermOrder(); } inline const int Dmnsn() const { return System.Dmnsn(); } inline const gPolyList UnderlyingEquations() const { return System; } inline const bool WasSolved() const { return HasBeenSolved; } inline const Gambit::List > RootList() const { return Roots; } inline const bool IsMultiaffine() const { return isMultiaffine; } // Refines the accuracy of roots obtained from other algorithms Gambit::Vector NewtonPolishOnce(const Gambit::Vector &) const; Gambit::Vector SlowNewtonPolishOnce(const Gambit::Vector &) const; Gambit::Vector NewtonPolishedRoot(const Gambit::Vector &) const; // Checks for complex singular roots bool MightHaveSingularRoots() const; // The grand calculation - returns true if successful bool FindCertainNumberOfRoots (const gRectangle&, const int&, const int&); bool FindRoots (const gRectangle&, const int&); bool ARootExists (const gRectangle&, Gambit::Vector&) const; }; #endif // QUIKSOLV_H gambit-0.2010.09.01/src/tools/enumpoly/quiksolv.imp0000644000076500007650000005115111435216102016621 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/quiksolv.imp // Implementation of quick-solver classes // // 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 "quiksolv.h" //--------------------------------------------------------------- // class: QuikSolv //--------------------------------------------------------------- //--------------------------- // Constructors / Destructors //--------------------------- using namespace Gambit; template QuikSolv::QuikSolv(const gPolyList& given) : System(given), gDoubleSystem(given.AmbientSpace(),given.TermOrder(), given.NormalizedList()), NoEquations( min(System.Dmnsn(),System.Length()) ), NoInequalities( max(System.Length() - System.Dmnsn(),0) ), TreesOfPartials(gDoubleSystem), HasBeenSolved(false), Roots(), isMultiaffine(System.IsMultiaffine()), Equation_i_uses_var_j(Eq_i_Uses_j()) { } template QuikSolv::QuikSolv(const gPolyList& given, const int& no_eqs) : System(given), gDoubleSystem(given.AmbientSpace(),given.TermOrder(), given.NormalizedList()), NoEquations(no_eqs), NoInequalities(System.Length() - no_eqs), TreesOfPartials(gDoubleSystem), HasBeenSolved(false), Roots(), isMultiaffine(System.IsMultiaffine()), Equation_i_uses_var_j(Eq_i_Uses_j()) { } template QuikSolv::QuikSolv(const QuikSolv& qs) : System(qs.System), gDoubleSystem(qs.gDoubleSystem), NoEquations(qs.NoEquations), NoInequalities(qs.NoEquations), TreesOfPartials(qs.TreesOfPartials), HasBeenSolved(qs.HasBeenSolved), Roots(qs.Roots), isMultiaffine(qs.isMultiaffine), Equation_i_uses_var_j(qs.Equation_i_uses_var_j) { } template QuikSolv::~QuikSolv() { } //------------------------------------------------------- // Supporting Calculations for the Constructors //------------------------------------------------------- template Gambit::RectArray QuikSolv::Eq_i_Uses_j(void) const { Gambit::RectArray answer(System.Length(),Dmnsn()); for (int i = 1; i <= System.Length(); i++) for (int j = 1; j <= Dmnsn(); j++) if (System[i].DegreeOfVar(j) > 0) answer(i,j) = true; else answer(i,j) = false; return answer; } //--------------------------- // Find Roots Using Pelican //--------------------------- template bool QuikSolv::AllRealRootsFromPelican(const gPolyList & sys, Gambit::List > &ans) const { try { PelView pel(sys); if (!pel.FoundAllRoots()) return false; ans = pel.RealRoots(); } catch (...) { return false; } /* catch (ErrorInPelican) { return false; } catch (ErrorInQhull) { return false; } */ return true; } template bool QuikSolv::PelicanRoots(const gRectangle& r, Gambit::List > &answer) const { Gambit::List > firstcut; bool pelworked = AllRealRootsFromPelican(gDoubleSystem.InteriorSegment(1,Dmnsn()), firstcut); if (!pelworked) return false; for (int i = 1; i <= firstcut.Length(); i++) { firstcut[i] = NewtonPolishOnce(firstcut[i]); firstcut[i] = NewtonPolishOnce(firstcut[i]); bool isokay(true); if (!TogDouble(r).Contains(firstcut[i])) isokay = false; for (int j = Dmnsn() + 1; isokay && j <= System.Length(); j++) if (gDoubleSystem[j].Evaluate(firstcut[i]) < (double)0) isokay = false; if (isokay) answer.Append(firstcut[i]); } return true; } //--------------------------- // Is a root impossible? //--------------------------- template bool QuikSolv::SystemHasNoRootsIn(const gRectangle& r, Gambit::Array& precedence) const { for (int i = 1; i <= System.Length(); i++) { if ( (precedence[i] <= NoEquations && TreesOfPartials[precedence[i]].PolyHasNoRootsIn(r)) || (precedence[i] > NoEquations && TreesOfPartials[precedence[i]].PolyEverywhereNegativeIn(r)) ) { if (i != 1) { // We have found a new "most likely to never vanish" int tmp = precedence[i]; for (int j = 1; j <= i-1; j++) precedence[i - j + 1] = precedence[i - j]; precedence[1] = tmp; } return true; } } return false; } //-------------------------------------- // Does Newton's method lead to a root? //-------------------------------------- // // In NewtonRootInRectangle(), problems with infinite looping will occur // due to roundoff in trying to compare to the zero vector. // The fuzzy_equals() functions below alleviate this by introducing // an epsilon fudge-factor. This fudge-factor, and indeed the entire // implementation, is largely ad-hoc, but appears to work for most // applications. // // The fuzzy_equals() function used to be implemented as operator== // for the type gDouble in previous versions; indeed, it was the // raison d'etre for that class' existence. As such, it is possible // that this technique may be useful elsewhere where gDouble used to // be used. // static bool fuzzy_equals(double x, double y) { const double epsilon = 0.000000001; if (x == 0) { return (fabs(y) < epsilon); } else if (y == 0) { return (fabs(x) < epsilon); } else { return ((fabs(x - y) / (fabs(x) + fabs(y)) < epsilon) || (fabs(x) < epsilon && fabs(y) < epsilon)); } } static bool fuzzy_equals(const Gambit::Vector &x, const Gambit::Vector &y) { for (int i = x.First(); i <= x.Last(); i++) { if (!fuzzy_equals(x[i], y[i])) return false; } return true; } template bool QuikSolv::NewtonRootInRectangle(const gRectangle& r, Gambit::Vector& point) const { assert (NoEquations == System.Dmnsn()); Gambit::Vector zero(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) zero[i] = (double)0; Gambit::Vector oldevals = TreesOfPartials.ValuesOfRootPolys(point, NoEquations); if (fuzzy_equals(oldevals, zero)) { return r.Contains(point); } gRectangle bigr = r.SameCenterDoubleSideLengths(); Gambit::Vector newpoint(Dmnsn()); while (true) { try { newpoint = NewtonPolishOnce(point); } catch (Gambit::SingularMatrixException) { bool nonsingular = false; int direction = 1; while (direction < Dmnsn() && !nonsingular) { Gambit::Vector perturbed_point(point); if (r.UpperBoundOfCoord(direction) > point[direction]) perturbed_point[direction] += (r.UpperBoundOfCoord(direction) - point[direction])/10; else perturbed_point[direction] += (r.LowerBoundOfCoord(direction) - point[direction])/10; nonsingular = true; try { newpoint = point + (NewtonPolishOnce(perturbed_point) - perturbed_point); } catch (Gambit::SingularMatrixException) { nonsingular = false; } direction++; } if (!nonsingular) { Gambit::Vector perturbed_point(point); if (r.UpperBoundOfCoord(direction) > point[direction]) perturbed_point[direction] += (r.UpperBoundOfCoord(direction) - point[direction])/10; else perturbed_point[direction] += (r.LowerBoundOfCoord(direction) - point[direction])/10; newpoint = point + (NewtonPolishOnce(perturbed_point) - perturbed_point); } } if ( !bigr.Contains(newpoint) ) return false; point = newpoint; Gambit::Vector newevals = TreesOfPartials.ValuesOfRootPolys(point, NoEquations); if (newevals * newevals > oldevals * oldevals) return false; if (fuzzy_equals(newevals, zero)) { if (r.Contains(point)) { point = SlowNewtonPolishOnce(point); point = SlowNewtonPolishOnce(point); return true; } else { return false; } } oldevals = newevals; } } template bool QuikSolv::NewtonRootNearRectangle(const gRectangle& r, Gambit::Vector& point) const { Gambit::Vector zero(NoEquations); for (int i = 1; i <= NoEquations; i++) zero[i] = (double)0; Gambit::Vector oldevals = TreesOfPartials.ValuesOfRootPolys(point, NoEquations); gRectangle bigr = r.CubeContainingCrcmscrbngSphere(); if (fuzzy_equals(oldevals, zero)) { return bigr.Contains(point); } while (true) { Gambit::Vector newpoint = SlowNewtonPolishOnce(point); if ( !bigr.Contains(newpoint) ) return false; point = newpoint; Gambit::Vector newevals = TreesOfPartials.ValuesOfRootPolys(point, NoEquations); if (fuzzy_equals(newevals, zero)) { return r.Contains(point); } oldevals = newevals; } } //------------------------------------ // Is the Newton root the only root? //------------------------------------ template double QuikSolv::MaxDistanceFromPointToVertexAfterTransformation( const gRectangle& r, const Gambit::Vector& p, const Gambit::SquareMatrix& M) const { assert( r.Contains(p) ); double max = (double)0; Gambit::Array ListOfTwos(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) ListOfTwos[i] = 2; gIndexOdometer ListOfTopBottoms(ListOfTwos); while (ListOfTopBottoms.Turn()) { Gambit::Vector diffs(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) if (ListOfTopBottoms[i] == 2) diffs[i] = r.CartesianFactor(i).UpperBound() - p[i]; else diffs[i] = p[i] - r.CartesianFactor(i).LowerBound(); Gambit::Vector new_diffs = M * diffs; double squared_length = new_diffs * new_diffs; if (max < squared_length) max = squared_length; } return sqrt((double)max); } template bool QuikSolv::HasNoOtherRootsIn(const gRectangle& r, const Gambit::Vector& p, const Gambit::SquareMatrix& M) const { assert (NoEquations == System.Dmnsn()); gPolyList system1 = gDoubleSystem.TranslateOfSystem(p); gPolyList system2 = system1.SystemInNewCoordinates(M); double radius = MaxDistanceFromPointToVertexAfterTransformation(r,p,M); double max = (double)0; for (int i = 1; i <= Dmnsn(); i++) max += system2[i].MaximalValueOfNonlinearPart(radius); if (max >= radius) return false; else return true; } //-------------------------------------------- // Does Newton's method yield a unique root? //-------------------------------------------- template bool QuikSolv::NewtonRootIsOnlyInRct(const gRectangle& r, Gambit::Vector& point) const { assert (NoEquations == System.Dmnsn()); if ( NewtonRootInRectangle(r,point) ) { Gambit::SquareMatrix Df = TreesOfPartials.SquareDerivativeMatrix(point); if ( HasNoOtherRootsIn(r,point,Df.Inverse()) ) return true; else return false; } else return false; } //---------------------------------- // Operators //---------------------------------- template QuikSolv& QuikSolv::operator=(const QuikSolv & rhs) { assert (System == rhs.System); if (*this != rhs) { HasBeenSolved = rhs.HasBeenSolved; Roots = rhs.Roots; } return *this; } template bool QuikSolv::operator==(const QuikSolv & rhs) const { if (System != rhs.System || HasBeenSolved != rhs.HasBeenSolved || Roots != rhs.Roots) return false; else return true; } template bool QuikSolv::operator!=(const QuikSolv & rhs) const { return !(*this == rhs); } //------------------------------------------- // Improve Accuracy of Root //------------------------------------------- template Gambit::Vector QuikSolv::NewtonPolishOnce(const Gambit::Vector& point) const { Gambit::Vector oldevals = TreesOfPartials.ValuesOfRootPolys(point, NoEquations); Gambit::Matrix Df = TreesOfPartials.DerivativeMatrix(point,NoEquations); Gambit::SquareMatrix M(Df * Df.Transpose()); Gambit::Vector Del = - (Df.Transpose() * M.Inverse()) * oldevals; return point + Del; } template Gambit::Vector QuikSolv::SlowNewtonPolishOnce(const Gambit::Vector& point) const { Gambit::Vector oldevals = TreesOfPartials.ValuesOfRootPolys(point, NoEquations); Gambit::Matrix Df = TreesOfPartials.DerivativeMatrix(point,NoEquations); Gambit::SquareMatrix M(Df * Df.Transpose()); Gambit::Vector Del = - (Df.Transpose() * M.Inverse()) * oldevals; bool done = false; while (!done) { Gambit::Vector newevals(TreesOfPartials.ValuesOfRootPolys(point + Del,NoEquations)); if (newevals * newevals <= oldevals * oldevals) done = true; else for (int i = 1; i <= Del.Length(); i++) Del[i] /= 2; } return point + Del; } template Gambit::Vector QuikSolv::NewtonPolishedRoot(const Gambit::Vector &initial) const { Gambit::List > interval_list; for (int i = 1; i <= Dmnsn(); i++) interval_list.Append(gInterval(initial[i] - (double)1, initial[i] + (double)1)); gRectangle box(interval_list); Gambit::Vector point(initial); if (!NewtonRootInRectangle(box,point)) throw NewtonError(); point = SlowNewtonPolishOnce(point); point = SlowNewtonPolishOnce(point); return point; } //------------------------------------------- // Check for Singularity //------------------------------------------- template bool QuikSolv::MightHaveSingularRoots() const { assert (NoEquations == System.Dmnsn()); gPoly newpoly = gDoubleSystem.ReductionOf( gDoubleSystem.DetOfDerivativeMatrix(), *(gDoubleSystem.TermOrder())); if (newpoly.IsZero()) return true; Gambit::List > newlist(gDoubleSystem.UnderlyingList()); newlist.Append(newpoly); gPolyList larger_system(gDoubleSystem.AmbientSpace(), gDoubleSystem.TermOrder(), newlist); gIdeal test_ideal(gDoubleSystem.TermOrder(),larger_system); return !(test_ideal.IsEntireRing()); } //------------------------------------------- // The Central Calculation //------------------------------------------- template bool QuikSolv::FindRoots(const gRectangle& r, const int& max_iterations) { assert (NoEquations == System.Dmnsn()); int zero = 0; return FindCertainNumberOfRoots(r,max_iterations,zero); } template bool QuikSolv::FindCertainNumberOfRoots(const gRectangle& r, const int& max_iterations, const int& max_no_roots) { assert (NoEquations == System.Dmnsn()); Gambit::List >* rootlistptr = new Gambit::List >(); if (NoEquations == 0) { Gambit::Vector answer(0); rootlistptr->Append(answer); Roots = *rootlistptr; HasBeenSolved = true; return true; } /* - Commmented out 7/11/00 because g3.nfg does not work Gambit::List > answer; bool done = PelicanRoots(r, answer); if (done) { Roots = answer; HasBeenSolved = true; return true; } */ Gambit::Array precedence(System.Length()); // Orders search for nonvanishing poly for (int i = 1; i <= System.Length(); i++) precedence[i] = i; int iterations = 0; int* no_found = new int(0); FindRootsRecursion(rootlistptr, TogDouble(r), max_iterations, precedence, iterations, 1, max_no_roots, no_found); if (iterations < max_iterations) { Roots = *rootlistptr; HasBeenSolved = true; return true; } return false; /* - This is code that was once used to call the Grobner basis solver It will not work with T = gDouble or double, due to numerical instability gSolver bigsolver(System.TermOrder(), System); if ( !bigsolver.IsZeroDimensional() ) return false; else { Gambit::List > rootlist; rootlist = bigsolver.Roots(); Gambit::List > roots; for (int j = 1; j <= rootlist.Length(); j++) if (TogDouble(r).Contains(rootlist[j])) roots += rootlist[j]; Roots = roots; } return true; */ } // // TLT: In some cases, this recursive process apparently goes into an // infinite regress. I'm not able to identify just why this occurs, // but as at least a temporary safeguard, we will limit the maximum depth // of this recursive search. // // This limit has been chosen only because it doesn't look like any // "serious" search (i.e., one that actually terminates with a result) // will take more than a depth of 32. // #define MAX_DEPTH 32 template void // Gambit::List > QuikSolv::FindRootsRecursion( Gambit::List >* rootlistptr, const gRectangle& r, const int& max_iterations, Gambit::Array& precedence, int& iterations, int depth, const int& max_no_roots, int* roots_found) const { assert (NoEquations == System.Dmnsn()); // Check for user interrupt // m_status.SetProgress(50.0); if ( SystemHasNoRootsIn(r, precedence) ) return; Gambit::Vector point = r.Center(); if ( NewtonRootIsOnlyInRct(r, point) ) { int i; for (i = NoEquations + 1; i <= System.Length(); i++) if (TreesOfPartials[i].ValueOfRootPoly(point) < (double)0) return; bool already_found = false; for (i = 1; i <= rootlistptr->Length(); i++) if (fuzzy_equals(point, (*rootlistptr)[i])) already_found = true; if (!already_found) { rootlistptr->Append(point); (*roots_found)++; } return; } int N = r.NumberOfCellsInSubdivision(); for (int i = 1; i <= N; i++) if (max_no_roots == 0 || *roots_found < max_no_roots) { if (iterations >= max_iterations || depth == MAX_DEPTH) return; else { iterations++; FindRootsRecursion(rootlistptr, r.SubdivisionCell(i), max_iterations, precedence, iterations, depth+1, max_no_roots, roots_found); } } return; } template const bool QuikSolv::ARootExistsRecursion(const gRectangle& r, Gambit::Vector& sample, const gRectangle& smallrect, Gambit::Array& precedence) const { if (fuzzy_equals(smallrect.MaximalSideLength(), (double) 0.0)) { sample = smallrect.Center(); return true; } if ( SystemHasNoRootsIn(smallrect, precedence) ) return false; Gambit::Vector point = smallrect.Center(); if (NewtonRootNearRectangle(smallrect,point)) if (r.Contains(point)) { bool satisfies_inequalities(true); for (int i = NoEquations + 1; i <= System.Length(); i++) if (satisfies_inequalities) if (TreesOfPartials[i].ValueOfRootPoly(point) < (double)0) satisfies_inequalities = false; if (satisfies_inequalities) { sample = point; return true; } } int N = smallrect.NumberOfCellsInSubdivision(); for (int i = 1; i <= N; i++) if (ARootExistsRecursion(r, sample, smallrect.SubdivisionCell(i), precedence)) return true; return false; } template bool QuikSolv::ARootExists (const gRectangle& r, Gambit::Vector& sample) const { if (NoEquations == 0) { Gambit::Vector answer(0); sample = answer; return true; } gRectangle r_double(TogDouble(r)); Gambit::Array precedence(System.Length()); // Orders search for nonvanishing poly for (int i = 1; i <= System.Length(); i++) precedence[i] = i; return ARootExistsRecursion(r_double, sample, r_double, precedence); } template QuikSolv::NewtonError::~NewtonError() { } template std::string QuikSolv::NewtonError::GetDescription(void) const { return "Newton method failed to polish approximate root"; } gambit-0.2010.09.01/src/tools/enumpoly/rectangl.cc0000644000076500007650000000231011435216102016334 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/rectangl.cc // Instantiation of rectangle classes // // 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 #include "libgambit/libgambit.h" #include "rectangl.imp" //template class gRectangle; //template gRectangle TogDouble(const gRectangle&); template class gRectangle; template gRectangle TogDouble(const gRectangle&); gambit-0.2010.09.01/src/tools/enumpoly/rectangl.h0000644000076500007650000000655111435216102016211 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/rectangl.h // Declaration of rectangle class // // 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 RECTANGL_H #define RECTANGL_H #include "interval.h" #include "libgambit/vector.h" /* This file provides the template class gRectangle which models the concept of a nonempty compact interval. Since boundary points can be identified, open and half open (bounded) intervals can be effected, but less directly. */ template class gRectangle { private: Gambit::List > sides; public: // constructors gRectangle(const gRectangle&); gRectangle(const Gambit::List >&); gRectangle(const Gambit::Vector, const Gambit::Vector); ~gRectangle(); // operators gRectangle& operator = (const gRectangle& y); bool operator == (const gRectangle& y) const; bool operator != (const gRectangle& y) const; // information const int Dmnsn() const; Gambit::Vector LowerBound() const; Gambit::Vector UpperBound() const; const T LowerBoundOfCoord(const int&) const; const T UpperBoundOfCoord(const int&) const; const T HeightInCoord(const int&) const; const gInterval CartesianFactor(const int&) const; const gRectangle SameCenterDoubleSideLengths() const; const gRectangle CubeContainingCrcmscrbngSphere() const; const gRectangle Orthant(const Gambit::Array&) const; const Gambit::Vector SideLengths() const; const T MaximalSideLength() const; bool Contains(const Gambit::Vector &) const; bool Contains(const gRectangle &) const; const T Volume() const; const Gambit::Vector Center() const; const gRectangle BoundingRectangle() const; const Gambit::List > VertexList() const; const int NumberOfCellsInSubdivision() const; const gRectangle SubdivisionCell(const int&) const; const T DiameterSquared() const; }; //------------- // Conversion: //------------- template gRectangle TogDouble(const gRectangle&); #endif // RECTANGL_H gambit-0.2010.09.01/src/tools/enumpoly/rectangl.imp0000644000076500007650000002013211435216102016536 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/rectangl.imp // Implementation of rectangle class // // 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 #include "rectangl.h" #include "odometer.h" //-------------------------------------------------------------------------- // rectangle -- constructors and destructor //-------------------------------------------------------------------------- template gRectangle::gRectangle(const gRectangle& given) : sides(given.sides) { } template gRectangle::gRectangle(const Gambit::List< gInterval >& given) : sides(given) { } template gRectangle::gRectangle(const Gambit::Vector lower_bd, const Gambit::Vector upper_bd) : sides() { assert (lower_bd.Check(upper_bd)); for (int i = 1; i <= upper_bd.Length(); i++) { gInterval side(lower_bd[i],upper_bd[i]); sides.Append(side); } } template gRectangle::~gRectangle() { } //-------------------------------------------------------------------------- // rectangle -- operators //-------------------------------------------------------------------------- template gRectangle& gRectangle::operator = (const gRectangle& /* rhs */) { // gout << "For const'ness, operator = not allowed for gRectangles\n"; exit (0); return *this; } template bool gRectangle::operator == (const gRectangle& rhs) const { for (int i = 1; i <= Dmnsn(); i++) if (sides[i] != rhs.sides[i]) return false; return true; } template bool gRectangle::operator != (const gRectangle& rhs) const { return !(*this == rhs); } //-------------------------------------------------------------------------- // interval -- information //-------------------------------------------------------------------------- template const int gRectangle::Dmnsn() const { return sides.Length(); } template Gambit::Vector gRectangle::LowerBound(void) const { Gambit::Vector answer(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) answer[i] = sides[i].LowerBound(); return answer; } template Gambit::Vector gRectangle::UpperBound(void) const { Gambit::Vector answer(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) answer[i] = sides[i].UpperBound(); return answer; } template const T gRectangle::LowerBoundOfCoord(const int& i) const { assert (1 <= i && i <= Dmnsn()); return sides[i].LowerBound(); } template const T gRectangle::UpperBoundOfCoord(const int& i) const { assert (1 <= i && i <= Dmnsn()); return sides[i].UpperBound(); } template const T gRectangle::HeightInCoord(const int& i) const { assert (1 <= i && i <= Dmnsn()); return sides[i].Length(); } template const gInterval gRectangle::CartesianFactor(const int& i) const { return sides[i]; } template const gRectangle gRectangle::SameCenterDoubleSideLengths() const { Gambit::List > new_sides; for (int i = 1; i <= Dmnsn(); i++) new_sides.Append(CartesianFactor(i).SameCenterTwiceLength()); return gRectangle(new_sides); } template const gRectangle gRectangle::CubeContainingCrcmscrbngSphere() const { T maxlength((T)0); T sumsquares((T)0); int i; for (i = 1; i <= Dmnsn(); i++) { sumsquares += sides[i].Length() * sides[i].Length(); if (sides[i].Length() > maxlength) maxlength = sides[i].Length(); } T diameter((T)0); while (diameter * diameter < sumsquares) diameter += maxlength; Gambit::List > new_sides; for (i = 1; i <= Dmnsn(); i++) new_sides.Append(CartesianFactor(i).SameCenterWithNewLength(diameter)); return gRectangle(new_sides); } template const gRectangle gRectangle::Orthant(const Gambit::Array& top_or_bot) const { Gambit::List > new_sides; for (int i = 1; i <= Dmnsn(); i++) if (top_or_bot[i] == 0) new_sides.Append(CartesianFactor(i).LeftHalf()); else new_sides.Append(CartesianFactor(i).RightHalf()); return gRectangle(new_sides); } template const Gambit::Vector gRectangle::SideLengths() const { Gambit::Vector answer(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) answer[i] = sides[i].UpperBound() - sides[i].LowerBound(); return answer; } template const T gRectangle::MaximalSideLength() const { T answer((T)0); for (int i = 1; i <= Dmnsn(); i++) if (HeightInCoord(i) > answer) answer = HeightInCoord(i); return answer; } template bool gRectangle::Contains(const Gambit::Vector& point) const { assert (point.Length() == Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) if (point[i] < sides[i].LowerBound() || sides[i].UpperBound() < point[i]) return false; return true; } template bool gRectangle::Contains(const gRectangle& R) const { assert (R.Dmnsn() == Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) if ( !sides[i].Contains(R.sides[i]) ) return false; return true; } template const T gRectangle::Volume() const { T answer = (T)1; for (int i = 1; i <= Dmnsn(); i++) answer *= ( sides[i].UpperBound() - sides[i].LowerBound() ); return answer; } template const Gambit::Vector gRectangle::Center() const { Gambit::Vector answer(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) answer[i] = (sides[i].UpperBound() + sides[i].LowerBound()) / ((T)2); return answer; } template const gRectangle gRectangle::BoundingRectangle() const { return *this; } template const Gambit::List > gRectangle::VertexList() const { Gambit::List > answer; Gambit::Array ListOfTwos(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) ListOfTwos[i] = 2; gIndexOdometer ListOfTopBottoms(ListOfTwos); while (ListOfTopBottoms.Turn()) { Gambit::Vector next(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) if (ListOfTopBottoms[i] == 1) next[i] = LowerBoundOfCoord(i); else next[i] = UpperBoundOfCoord(i); answer.Append(next); } return answer; } template const int gRectangle::NumberOfCellsInSubdivision() const { int answer = 1; for (int i = 1; i <= Dmnsn(); i++) answer *= 2; return answer; } template const gRectangle gRectangle::SubdivisionCell(const int& index) const { int tmp = index; Gambit::Array updowns(Dmnsn()); for (int i = 1; i <= Dmnsn(); i++) { if (tmp % 2 == 1) { updowns[i] = 1; tmp--; } else updowns[i] = 0; tmp /= 2; } return Orthant(updowns); } template const T gRectangle::DiameterSquared() const { T answer((T)0); for (int i = 1; i <= Dmnsn(); i++) answer += HeightInCoord(i) * HeightInCoord(i); return answer; } //---------------------------------- // Conversion //---------------------------------- template gRectangle TogDouble(const gRectangle& given) { Gambit::List > cartesian_factors; for (int i = 1; i <= given.Dmnsn(); i++) cartesian_factors.Append(gInterval((double)given.LowerBound()[i], (double)given.UpperBound()[i])); return gRectangle(cartesian_factors); } gambit-0.2010.09.01/src/tools/enumpoly/sfg.cc0000644000076500007650000001610511435216102015323 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/sfg.cc // Implementation of sequence form classes // // 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 "sfg.h" #include "sfstrat.h" #include "gnarray.imp" #include "libgambit/libgambit.h" //---------------------------------------------------- // Sfg: Constructors, Destructors, Operators //---------------------------------------------------- Sfg::Sfg(const Gambit::BehavSupport &S) : EF(S.GetGame()), efsupp(S), seq(EF->NumPlayers()), isetFlag(S.GetGame()->NumInfosets()), isetRow(S.GetGame()->NumInfosets()), infosets(EF->NumPlayers()) { int i; Gambit::Array zero(EF->NumPlayers()); Gambit::Array one(EF->NumPlayers()); Gambit::BehavSupport support(EF); for(i=1;i<=EF->NumPlayers();i++) { seq[i]=1; zero[i]=0; one[i]=1; } isetFlag = 0; isetRow = 0; GetSequenceDims(EF->GetRoot()); isetFlag = 0; gIndexOdometer index(seq); SF = new gNArray *>(seq); while (index.Turn()) { (*SF)[index.CurrentIndices()] = new Gambit::Array(EF->NumPlayers()); for(i=1;i<=EF->NumPlayers();i++) (*(*SF)[index.CurrentIndices()])[i]=(Gambit::Rational)0; } E = new Gambit::Array *> (EF->NumPlayers()); for(i=1;i<=EF->NumPlayers();i++) { (*E)[i] = new Gambit::RectArray(infosets[i].Length()+1,seq[i]); for(int j = (*(*E)[i]).MinRow();j<=(*(*E)[i]).MaxRow();j++) for(int k = (*(*E)[i]).MinCol();k<=(*(*E)[i]).MaxCol();k++) (*(*E)[i])(j,k)=(Gambit::Rational)0; (*(*E)[i])(1,1)=(Gambit::Rational)1; } sequences = new Gambit::Array(EF->NumPlayers()); for(i=1;i<=EF->NumPlayers();i++) (*sequences)[i] = new SFSequenceSet(EF->GetPlayer(i)); Gambit::Array parent(EF->NumPlayers()); for(i=1;i<=EF->NumPlayers();i++) parent[i] = (((*sequences)[i])->GetSFSequenceSet())[1]; MakeSequenceForm(EF->GetRoot(),(Gambit::Rational)1,one,zero,parent); } Sfg::~Sfg() { gIndexOdometer index(seq); while (index.Turn()) delete (*SF)[index.CurrentIndices()]; delete SF; int i; for(i=1;i<=EF->NumPlayers();i++) delete (*E)[i]; delete E; for(i=1;i<=EF->NumPlayers();i++) delete (*sequences)[i]; delete sequences; } void Sfg:: MakeSequenceForm(const Gambit::GameNode &n, Gambit::Rational prob,Gambit::Arrayseq, Gambit::Array iset, Gambit::Array parent) { int i,pl; if (n->GetOutcome()) { for(pl = 1;pl<=seq.Length();pl++) (*(*SF)[seq])[pl] += prob * n->GetOutcome()->GetPayoff(pl); } if(n->GetInfoset()) { if(n->GetPlayer()->IsChance()) { for(i=1;i<=n->NumChildren();i++) MakeSequenceForm(n->GetChild(i), prob * n->GetInfoset()->GetActionProb(i), seq,iset,parent); } else { int pl = n->GetPlayer()->GetNumber(); iset[pl]=n->GetInfoset(); int isetnum = iset[pl]->GetNumber(); Gambit::Array snew(seq); snew[pl]=1; for(i=1;iNumChildren();i++) { if(efsupp.Contains(n->GetInfoset()->GetAction(i))) { snew[pl]+=1; if(flag) { Sequence* child; child = new Sequence(n->GetPlayer(), n->GetInfoset()->GetAction(i), myparent,snew[pl]); parent[pl]=child; ((*sequences)[pl])->AddSequence(child); } (*(*E)[pl])(isetRow(pl,isetnum),snew[pl]) = -(Gambit::Rational)1; MakeSequenceForm(n->GetChild(i),prob,snew,iset,parent); } } } } } void Sfg:: GetSequenceDims(const Gambit::GameNode &n) { int i; if(n->GetInfoset()) { if(n->GetPlayer()->IsChance()) { for(i=1;i<=n->NumChildren();i++) GetSequenceDims(n->GetChild(i)); } else { int pl = n->GetPlayer()->GetNumber(); int isetnum = n->GetInfoset()->GetNumber(); bool flag = false; if(!isetFlag(pl,isetnum)) { // on first visit to iset, create new sequences infosets[pl].Append(n->GetInfoset()); isetFlag(pl,isetnum)=1; isetRow(pl,isetnum)=infosets[pl].Length()+1; flag =true; } for(i=1;i<=n->NumChildren();i++) { if(efsupp.Contains(n->GetInfoset()->GetAction(i))) { if(flag) { seq[pl]++; } GetSequenceDims(n->GetChild(i)); } } } } } int Sfg::TotalNumSequences() const { int tot=0; for(int i=1;i<=seq.Length();i++) tot+=seq[i]; return tot; } int Sfg::NumPlayerInfosets() const { int tot=0; for(int i=1;i<=infosets.Length();i++) tot+=infosets[i].Length(); return tot; } int Sfg::InfosetRowNumber(int pl, int j) const { if(j==1) return 0; int isetnum = (*sequences)[pl]->Find(j)->GetInfoset()->GetNumber(); return isetRow(pl,isetnum); } int Sfg::ActionNumber(int pl, int j) const { if(j==1) return 0; return efsupp.GetIndex(GetAction(pl,j)); } Gambit::GameInfoset Sfg::GetInfoset(int pl, int j) const { if(j==1) return 0; return (*sequences)[pl]->Find(j)->GetInfoset(); } Gambit::GameAction Sfg::GetAction(int pl, int j) const { if(j==1) return 0; return (*sequences)[pl]->Find(j)->GetAction(); } Gambit::MixedBehavProfile Sfg::ToBehav(const Gambit::PVector &x) const { Gambit::MixedBehavProfile b(efsupp); b = (Gambit::Rational) 0; Sequence *sij; const Sequence *parent; Gambit::Rational value; int i,j; for(i=1;i<=EF->NumPlayers();i++) for(j=2;j<=seq[i];j++) { sij = ((*sequences)[i]->GetSFSequenceSet())[j]; int sn = sij->GetNumber(); parent = sij->Parent(); // gout << "\ni,j,sn,iset,act: " << i << " " << j << " " << sn << " "; // gout << sij->GetInfoset()->GetNumber() << " " << sij->GetAction()->GetNumber(); if(x(i, parent->GetNumber())>(double)0) value = (x(i,sn)/x(i,parent->GetNumber())); else value = 0; b(i,sij->GetInfoset()->GetNumber(),efsupp.GetIndex(sij->GetAction()))= value; } return b; } Gambit::Rational Sfg::Payoff(const Gambit::Array & index,int pl) const { return Payoffs(index)[pl]; } template class gNArray *>; gambit-0.2010.09.01/src/tools/enumpoly/sfg.h0000644000076500007650000000540711435216102015170 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/sfg.h // Interface to sequence form classes // // 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 SFG_H #define SFG_H #include "libgambit/libgambit.h" #include "odometer.h" #include "gnarray.h" #include "sfstrat.h" class Sfg { private: Gambit::Game EF; const Gambit::BehavSupport &efsupp; Gambit::Array *sequences; gNArray *> *SF; // sequence form Gambit::Array *> *E; // constraint matrices for sequence form. Gambit::Array seq; Gambit::PVector isetFlag,isetRow; Gambit::Array > infosets; void MakeSequenceForm(const Gambit::GameNode &, Gambit::Rational,Gambit::Array, Gambit::Array, Gambit::Array); void GetSequenceDims(const Gambit::GameNode &); public: Sfg(const Gambit::BehavSupport &); virtual ~Sfg(); inline int NumSequences(int pl) const {return seq[pl];} inline int NumInfosets(int pl) const {return infosets[pl].Length();} inline Gambit::Array NumSequences() const {return seq;} int TotalNumSequences() const; int NumPlayerInfosets() const; inline int NumPlayers() const {return EF->NumPlayers();} inline Gambit::Array Payoffs(const Gambit::Array & index) const {return *((*SF)[index]);} Gambit::Rational Payoff(const Gambit::Array & index,int pl) const; Gambit::RectArray Constraints(int player) const {return *((*E)[player]);}; int InfosetRowNumber(int pl, int sequence) const; int ActionNumber(int pl, int sequence) const; Gambit::GameInfoset GetInfoset(int pl, int sequence) const; Gambit::GameAction GetAction(int pl, int sequence) const; const Gambit::Game &GetEfg(void) const {return EF;} Gambit::MixedBehavProfile ToBehav(const Gambit::PVector &x) const; const Sequence* GetSequence(int pl, int seq) const {return ((*sequences)[pl])->Find(seq);} }; #endif // SFG_H gambit-0.2010.09.01/src/tools/enumpoly/sfstrat.cc0000644000076500007650000001401711435216102016232 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/sfstrat.cc // Implementation of sequence form strategy classes // // 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 "sfstrat.h" #include "sfg.h" //-------------------------------------- // Sequence: Member functions //-------------------------------------- Gambit::List Sequence::History(void) const { Gambit::List h; Gambit::GameAction a = action; const Sequence * s = (this); while(a) { h.Append(a); s = s->parent; a = s->GetAction(); } return h; } //-------------------------------------- // SFSequenceSet: Member functions //-------------------------------------- SFSequenceSet::SFSequenceSet(const Gambit::GamePlayer &p) : efp(p), sequences() { Sequence *empty; empty = new Sequence(p,0,0,1); AddSequence(empty); } SFSequenceSet::SFSequenceSet(const SFSequenceSet &s) : efp(s.efp), sequences(s.sequences) { } SFSequenceSet::~SFSequenceSet() { // potential problem here? It is not clear this is where this belongs. // What if there are multiple SFSequenceSets pointing to // the same sequences? for(int i=1;i<=sequences.Length();i++) delete sequences[i]; } SFSequenceSet &SFSequenceSet::operator=(const SFSequenceSet &s) { if (this != &s) { efp = s.efp; sequences = s.sequences; } return *this; } bool SFSequenceSet::operator==(const SFSequenceSet &s) { if (sequences.Length() != s.sequences.Length()) return (false); int i; for (i = 1; i <= sequences. Length() && sequences[i] == s.sequences[i]; i++); if (i > sequences.Length()) return (true); else return (false); } //------------------------------------------ // SFSequenceSet: Member functions //------------------------------------------ // Append a sequences to the SFSequenceSet void SFSequenceSet::AddSequence(Sequence *s) { assert (efp == s->Player()); sequences.Append(s); } // Removes a sequence pointer. Returns true if the sequence was successfully // removed, false otherwise. bool SFSequenceSet::RemoveSequence( Sequence *s ) { assert (efp == s->Player()); int t; t = sequences.Find(s); if (t>0) sequences.Remove(t); return (t>0); } // Finds the sequence pointer of sequence number j. Returns 0 if there // is no sequence with that number. Sequence *SFSequenceSet::Find( int j ) { int t=1; while(t <= sequences.Length()) { if(sequences[t]->GetNumber() == j) return sequences[t]; t++; } return 0; } // Number of Sequences in a SFSequenceSet int SFSequenceSet::NumSequences(void) const { return (sequences.Length()); } // Return the entire sequence set const Gambit::Array &SFSequenceSet::GetSFSequenceSet(void) const { return sequences; } //----------------------------------------------- // SFSupport: Ctors, Dtor, Operators //----------------------------------------------- SFSupport::SFSupport(const Sfg &SF) : bsfg(&SF), sups(SF.GetEfg()->NumPlayers()) { for (int i = 1; i <= sups.Length(); i++) sups[i] = new SFSequenceSet(SF.GetEfg()->GetPlayer(i)); } SFSupport::SFSupport(const SFSupport &s) : bsfg(s.bsfg), sups(s.sups.Length()) { for (int i = 1; i <= sups.Length(); i++) sups[i] = new SFSequenceSet(*s.sups[i]); } SFSupport::~SFSupport() { for (int i = 1; i <= sups.Length(); i++) delete sups[i]; } SFSupport &SFSupport::operator=(const SFSupport &s) { if (this != &s && bsfg == s.bsfg) { for (int i = 1; i <= sups.Length(); i++) { delete sups[i]; sups[i] = new SFSequenceSet(*s.sups[i]); } } return *this; } bool SFSupport::operator==(const SFSupport &s) const { assert(sups.Length() == s.sups.Length()); int i; for (i = 1; i <= sups.Length() && *sups[i] == *s.sups[i]; i++); if (i > sups.Length()) return (true); else return (false); } bool SFSupport::operator!=(const SFSupport &s) const { return !(*this == s); } //------------------------ // SFSupport: Members //------------------------ const Gambit::Array &SFSupport::Sequences(int pl) const { return (sups[pl]->GetSFSequenceSet()); } int SFSupport::NumSequences(int pl) const { return sups[pl]->NumSequences(); } const Gambit::Array SFSupport::NumSequences(void) const { Gambit::Array a(sups.Length()); for (int i = 1 ; i <= a.Length(); i++) a[i] = sups[i]->NumSequences(); return a; } int SFSupport::TotalNumSequences(void) const { int total = 0; for (int i = 1 ; i <= sups.Length(); i++) total += sups[i]->NumSequences(); return total; } int SFSupport::Find(Sequence *s) const { return sups[s->Player()->GetNumber()]->GetSFSequenceSet().Find(s); } void SFSupport::AddSequence(Sequence *s) { sups[s->Player()->GetNumber()]->AddSequence(s); } bool SFSupport::RemoveSequence(Sequence *s) { return sups[s->Player()->GetNumber()]->RemoveSequence(s); } // Returns true if all sequences in _THIS_ belong to _S_ bool SFSupport::IsSubset(const SFSupport &s) const { assert(sups.Length() == s.sups.Length()); for (int i = 1; i <= sups.Length(); i++) if (NumSequences(i) > s.NumSequences(i)) return false; else { const Gambit::Array &strats = sups[i]->GetSFSequenceSet(); for (int j = 1; j <= NumSequences(i); j++) if (!s.sups[i]->GetSFSequenceSet().Find(strats[j])) return false; } return true; } gambit-0.2010.09.01/src/tools/enumpoly/sfstrat.h0000644000076500007650000000757011435216102016102 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpoly/sfstrat.h // Interface to sequence form strategy classes // // 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 SFSTRAT_H #define SFSTRAT_H #include "libgambit/libgambit.h" struct Sequence { friend class Sfg; friend class SFSequenceSet; private: int number; std::string name; Gambit::GamePlayer player; Gambit::GameAction action; const Sequence *parent; Sequence(Gambit::GamePlayer pl, Gambit::GameAction a, const Sequence *p, int n) : number(n), player(pl), action(a), parent(p) { } ~Sequence() { } public: const std::string &GetName(void) const { return name; } void SetName(const std::string &s) { name = s; } Gambit::List History(void) const; int GetNumber(void) const { return number; } Gambit::GameAction GetAction(void) const {return action; } Gambit::GameInfoset GetInfoset(void) const { if(action) return action->GetInfoset();return 0; } Gambit::GamePlayer Player(void) const { return player; } const Sequence *Parent(void) const { return parent; } }; class SFSequenceSet { protected: Gambit::GamePlayer efp; Gambit::Array sequences; public: SFSequenceSet(const SFSequenceSet &s); SFSequenceSet(const Gambit::GamePlayer &p); SFSequenceSet &operator=(const SFSequenceSet &s); bool operator==(const SFSequenceSet &s); virtual ~SFSequenceSet(); // Append a sequence to the SFSequenceSet void AddSequence(Sequence *s); // Removes a sequence pointer. Returns true if the sequence was successfully // removed, false otherwise. bool RemoveSequence( Sequence *s ); Sequence * Find(int j); // Number of sequences in the SFSequenceSet int NumSequences(void) const; // return the entire sequence set in a const Gambit::Array const Gambit::Array &GetSFSequenceSet(void) const; }; class Sfg; class SFSupport { protected: const Sfg *bsfg; Gambit::Array sups; public: SFSupport(const Sfg &); SFSupport(const SFSupport &s); virtual ~SFSupport(); SFSupport &operator=(const SFSupport &s); bool operator==(const SFSupport &s) const; bool operator!=(const SFSupport &s) const; const Sfg &Game(void) const { return *bsfg; } const Gambit::Array &Sequences(int pl) const; int NumSequences(int pl) const; const Gambit::Array NumSequences(void) const; int TotalNumSequences(void) const; void AddSequence(Sequence *); bool RemoveSequence(Sequence *); bool IsSubset(const SFSupport &s) const; // returns the index of the sequence in the support if it exists, // otherwise returns zero int Find(Sequence *) const; }; class SequenceProfile { friend class Sfg; private: long index; Gambit::Array profile; public: SequenceProfile(const Sfg &); SequenceProfile(const SequenceProfile &p); ~SequenceProfile(); SequenceProfile &operator=(const SequenceProfile &); bool IsValid(void) const; long GetIndex(void) const; Sequence *const operator[](int p) const; Sequence *const Get(int p) const; void Set(int p, Sequence *const s); }; #endif // SFSTRAT_H gambit-0.2010.09.01/src/tools/enumpure/0000777000076500007650000000000011441457120014312 500000000000000gambit-0.2010.09.01/src/tools/enumpure/enumpure.cc0000644000076500007650000001423011435216102016371 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/enumpure/enumpure.cc // Compute pure-strategy equilibria in extensive form games // // 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 #include #include #include "libgambit/libgambit.h" #include "libgambit/subgame.h" using namespace Gambit; template void PrintProfile(std::ostream &p_stream, const MixedBehavProfile &p_profile) { p_stream << "NE,"; for (int i = 1; i <= p_profile.Length(); i++) { p_stream << p_profile[i]; if (i < p_profile.Length()) { p_stream << ','; } } p_stream << std::endl; } List > SolveBehav(const BehavSupport &p_support, bool p_print = false) { List > solutions; Game efg = p_support.GetGame(); for (BehavIterator citer(p_support); !citer.AtEnd(); citer++) { bool isNash = true; for (GamePlayerIterator player = efg->Players(); isNash && !player.AtEnd(); player++) { Rational current = citer->GetPayoff(player); for (GameInfosetIterator infoset = player->Infosets(); isNash && !infoset.AtEnd(); infoset++) { for (GameActionIterator action = infoset->Actions(); !action.AtEnd(); action++) { if (citer->GetActionValue(action) > current) { isNash = false; break; } } } } if (isNash) { MixedBehavProfile temp(efg); // zero out all the entries, since any equilibria are pure ((Vector &) temp).operator=(Rational(0)); for (GamePlayerIterator player = efg->Players(); !player.AtEnd(); player++) { for (GameInfosetIterator infoset = player->Infosets(); !infoset.AtEnd(); infoset++) { temp(citer->GetAction(infoset)) = 1; } } if (p_print) { PrintProfile(std::cout, temp); } solutions.Append(temp); } } return solutions; } List > SubsolveBehav(const BehavSupport &p_support) { return SolveBehav(p_support, false); } template void PrintProfile(std::ostream &p_stream, const MixedStrategyProfile &p_profile) { p_stream << "NE,"; for (int i = 1; i <= p_profile.Length(); i++) { p_stream << p_profile[i]; if (i < p_profile.Length()) { p_stream << ','; } } p_stream << std::endl; } void SolveMixed(Game p_nfg) { for (StrategyIterator citer(p_nfg); !citer.AtEnd(); citer++) { bool flag = true; for (GamePlayerIterator player = p_nfg->Players(); flag && !player.AtEnd(); player++) { Rational current = citer->GetPayoff(player); PureStrategyProfile p(*citer); for (GameStrategyIterator strategy = player->Strategies(); !strategy.AtEnd(); strategy++) { if (p.GetStrategyValue(strategy) > current) { flag = false; break; } } } if (flag) { MixedStrategyProfile temp(p_nfg); ((Vector &) temp).operator=(Rational(0)); PureStrategyProfile profile(*citer); for (GamePlayerIterator player = p_nfg->Players(); !player.AtEnd(); player++) { temp[profile.GetStrategy(player)] = 1; } PrintProfile(std::cout, temp); } } } void PrintBanner(std::ostream &p_stream) { p_stream << "Search for Nash equilibria in pure strategies\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "With no options, locates all Nash equilibria in pure strategies.\n\n"; std::cerr << "Options:\n"; std::cerr << " -S use strategic game\n"; std::cerr << " -P find only subgame-perfect equilibria\n"; std::cerr << " -h print this help message\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; exit(1); } int main(int argc, char *argv[]) { opterr = 0; bool quiet = false, useStrategic = false, bySubgames = false; int c; while ((c = getopt(argc, argv, "hqSP")) != -1) { switch (c) { case 'S': useStrategic = true; break; case 'P': bySubgames = true; break; case 'h': PrintHelp(argv[0]); break; case 'q': quiet = true; break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Game game = ReadGame(std::cin); if (!game->IsTree() || useStrategic) { game->BuildComputedValues(); SolveMixed(game); } else { if (bySubgames) { List > solutions; solutions = SolveBySubgames(BehavSupport(game), &SubsolveBehav); for (int i = 1; i <= solutions.Length(); i++) { PrintProfile(std::cout, solutions[i]); } } else { SolveBehav(game, true); } } return 0; } catch (InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } } gambit-0.2010.09.01/src/tools/gt/0000777000076500007650000000000011441457122013066 500000000000000gambit-0.2010.09.01/src/tools/gt/cmatrix.cc0000644000076500007650000002376411434220577015000 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "cmatrix.h" #include "math.h" #include "float.h" cvector::~cvector() { delete []x; } // adopted from NRiC, pg 45 cmatrix::~cmatrix() { delete []x; } int cvector::num_vec_cons = 0; cmatrix cmatrix::inv(bool &worked) const { if (m!=n) { cerr << "invalid cmatrix inverse" << endl; exit(1); } cmatrix temp(n,n); int *ix = new int[n]; if (!LUdecomp(temp,ix)) { worked = false; delete []ix; return cmatrix(n,n,0,false); } worked = true; cmatrix ret(n,n); int i,j; double *col = new double[n]; for(j=0;j=big) { big = dum; imax = i; } } if (j!=imax) { for(k=0;k=0;i--) { sum = b[i]; for(int j=i+1;j<=n-1;j++) sum -= x[i*n+j]*b[j]; b[i] = sum/x[i*n+i]; } } bool cmatrix::solve(cvector &b, cvector &ret) { if (m!=n) { cerr << "invalid cmatrix in solve" << endl; exit(1); } for(int i=0;iabsb) { double sqr = absb/absa; return absa*sqrt(1.0+sqr*sqr); } else { if (absb==0.0) return 0; double sqr = absa/absb; return absb*sqrt(1.0+sqr*sqr); } } #define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a)) // adopted from pg 67 of NRiC void cmatrix::svd(cmatrix &u, cmatrix &v, double *w) { u = *this; if (v.n!=n || v.m!=n) { delete []v.x; v.n = n; v.m = n; v.s = n*n; v.x = new double[v.s]; } int flag,i,its,j,jj,k,l,nm; double anorm,c,f,g,h,s,scale,x,y,z,*rv1; rv1 = new double[n]; g=scale=anorm=(double)0; for(i=0;itemp ? anorm : temp; } for(i=n-1;i>=0;i--) { if (in?n-1:m-1;i>=0;i--) { l=i+1; g=w[i]; for(j=l;j=0;k--) { for(its=1;its<=30;its++) { flag = 1; for(l=k;l>=0;l--) { nm = l-1; if ((double)(fabs(rv1[l])+anorm)==anorm) { flag = 0; break; } if ((double)(fabs(w[nm])+anorm)==anorm) break; } if (flag) { c = (double)0; s = (double)1; for(i=l;i<=k;i++) { f = s*rv1[i]; rv1[i] = c*rv1[i]; if ((double)(fabs(f)+anorm)==anorm) break; g = w[i]; h = pythag(f,g); w[i] = h; h = 1/h; c = g*h; s = -f*h; for(j=0;j max) { max = fabs(retval[i][j]); maxi = i; } } if(j != lastj && max == 0.0) { if(lastj >= 0) return DBL_MAX; lastj = j; if(j != m-1) continue; } if(maxi == -1) { cout << "oops"; return DBL_MAX; } i = maxi; pivot = retval[i][j]; for(i0 = 0; i0 < m; i0++) { if(i0 != i) { for(j0 = 0; j0 < m; j0++) { if(j0 != j) { retval[i0][j0] *= pivot; retval[i0][j0] -= retval[i0][j] * retval[i][j0]; retval[i0][j0] /= D; } } } } for(i0 = 0; i0 < m; i0++) { retval[i0][j] = -retval[i0][j]; } retval[i][j] = D; D = pivot; r[i] = j; c[j] = i; if(j == lastj) break; if(j == m-1 && lastj >= 0) j = lastj - 1; } // cout << retval << endl << endl; int s=0; i = 0; memcpy(r2, r, m * sizeof(int)); while(i < m-1) { j = r2[i]; if(i != j) { s++; r2[i] = r2[j]; r2[j] = j; } else i++; } for(i = 0; i < m; i++) for(j = 0; j < m; j++) x[i*n+j] = retval[c[i]][r[j]]; if(s%2 == 1) { negate(); D = -D; } // cout << *this << endl << endl; return D; } double cmatrix::testAdjoint() //returns the characteristic polynomial and adjoint cmatrix { cmatrix c(n,n,1.0,1), p(n,n); int i = 0, j; double det,b; for (;;) { i++; if (i == n) break; p = *this * c; c = p; b = - c.trace() / i; for (j = 0; j < n; j++) c[j][j] += b; } p = m * c; det = - p.trace() / n; b = 1 - 2*((n - 1) % 2); *this = c * b; return det; } double cmatrix::trace() { assert(n == m); double sum = 0.0; for(int i = 0; i < n; i++) { sum += x[i*n+i]; } return sum; } gambit-0.2010.09.01/src/tools/gt/cmatrix.h0000644000076500007650000005053111351773315014633 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CMATRIX_H_ #define _CMATRIX_H_ #include #ifdef SOLARIS #include #endif #include #include #include #include #include #include #include #include using namespace std; class cmatrix; class cmatrixrow { public: double operator[](int) const { return 0.0; } }; class cvector { friend class cmatrix; public: static int num_vec_cons; inline cvector() { cvector::num_vec_cons++; m = 1; x = new double[1]; } inline cvector(int m) { cvector::num_vec_cons++; this->m = m; x = new double[m]; } ~cvector(); inline cvector(const cvector &v) { cvector::num_vec_cons++; m = v.m; x = new double[m]; //for(int i=0;im = m; x = new double[m]; for(int i=0;im = m; if (keep) x = v; else { x = new double[m]; //for(int i=0;ima) ma = t; return ma; } inline double min() const { double t,mi = x[0]; for(int i=1;i0?x[0]:-x[0]; for(int i=1;i0?x[i]:-x[i]))>ma) ma = t; return ma; } inline double absmin() const { double t,mi = x[0]>0?x[0]:-x[0]; for(int i=1;i0?x[i]:-x[i]))m) return false; #if !defined(HAVE_BCMP) for(int i=0;ix[i]!=x[i]) return false; return true; #else return bcmp(x,v->x,m*sizeof(double))==0; #endif // HAVE_BCMP } inline bool operator==(const double &a) const { for(int i=0;i>(istream &s, cvector &v); inline double *values() { return x; } inline int getm() const { return m; } inline ostream &niceprint(ostream &s) { for(int i=0;i f2) ? f1 : f2); } inline cvector operator+(const cvector &a, const cvector &b) { return cvector(a)+=b; } inline cvector operator-(const cvector &a, const cvector &b) { return cvector(a)-=b; } inline cvector operator+(const cvector &a, const double &b) { return cvector(a)+=b; } inline cvector operator-(const cvector &a, const double &b) { return cvector(a)-=b; } inline cvector operator+(const double &a, const cvector &b) { return cvector(b)+=a; } inline cvector operator-(const double &a, const cvector &b) { return cvector(b.getm(),a)-=b; } inline cvector operator*(const cvector &a, const double &b) { return cvector(a)*=b; } inline cvector operator*(const double &a, const cvector &b) { return cvector(b)*=a; } inline cvector operator/(const cvector &a, const double &b) { return cvector(a)/=b; } inline ostream &operator<<(ostream &s, const cvector& v) { // s << v.m << ' '; for(int i=0;i>(istream &s, cvector& v) { int tm; s >> tm; if (tm!=v.m) { delete []v.x; v.m = tm; v.x = new double[tm]; } for(int i=0;i> v.x[i]; return s; } class cmatrix { public: inline cmatrix(int m=1, int n=1) { this->m = m; this->n = n; s = m*n; x = new double[s]; } ~cmatrix(); inline cmatrix(const cmatrix &ma, bool transpose=false) { s = ma.m*ma.n; x = new double[s]; if (transpose) { int i,j,c; n = ma.m; m = ma.n; c = 0; for(i=0;im = m; this->n = n; s = m*n; x = new double[s]; if (diaonly) { int i; //for(i=0;i=m) for(i=0;im = m; this->n = n; s = m*n; x = new double[s]; //for(int i=0;im = m; this->n = n; s = m*n; //int i; x = new double[s]; //for(i=0;ima) ma=t; return ma; } inline double min() const { double t,mi = x[0]; for(int i=1;i0?x[0]:-x[0]; for(int i=1;i0?x[i]:-x[i]))0?x[0]:-x[0]; for(int i=1;i0?x[i]:-x[i]))>ma) ma=t; return ma; } inline bool operator==(const cmatrix &ma) const { if (ma.n!=n||ma.m!=m) return false; #if !defined(HAVE_BCMP) for(int i=0;i>(istream& s, cmatrix& ma); // LU decomposition -- ix is the row permutations int LUdecomp(cmatrix &LU, int *ix) const; // LU back substitution -- // ix from above fn call (this should be an LU combination) void LUbacksub(int *ix, double *col) const; // solves equation Ax=b (A is this, x is the returned value) bool solve(cvector &b, cvector &dest); double *solve(const double *b, bool &worked) const; inline double *solve(const double *b) const { bool w; return solve(b,w); } inline void negate() { for(int i = 0; i < s; i++) x[i] = -x[i]; } cmatrix inv(bool &worked) const; inline cmatrix inv() const { bool w; return inv(w); } double adjoint(); inline double trace(); double testAdjoint(); inline void multiply(const cvector &source, cvector &dest) { assert(n == source.m && m == dest.m); int i,j,c=0; for(i = 0; i < m; i++) { dest[i] = 0; for(j = 0; j < n; j++,c++) dest[i] += x[c] * source[j]; } } inline double *values() { return x; } // w needs to points to an array of n fp numbers void svd(cmatrix &u, cmatrix &v, double *w); // makes the matrix tri-diagonal (if symmetric) // The matrix is replaced by Q, and the vectors d and e hold // the diagonal and off-diagonal elements respectively void tridiag(cvector &d, cvector &e); // converts the Q matrix from tridiag into the eigenvectors // d and e are the diagonal and off-diagonal elements from // tridiag and the eigenvalues are left in d void tridiagev(cvector &d, cvector &e); // returns the inverse of a real, symmetric matrix // via eigenvalue decomposition. If any of the e.v. are // very close to zero, it uses the psuedo inverse // (ie 1/ev = 0) cmatrix syminv(double tol=1e-10) const; // uses the above two to compute eigen decomp of symmetric // matrix (destroys matrix and replaces with eigenvectors) cvector eigensym() { cvector d,e; tridiag(d,e); tridiagev(d,e); return d; } inline ostream &niceprint(ostream& s) { s << m << ' ' << n << endl; for(int i=0;i>(istream& s, cmatrix& ma) { int tn,tm; s >> tm >> tn; if (tm!=ma.m || tn!=ma.n) { delete []ma.x; ma.s = tm*tn; ma.x = new double[ma.s]; ma.m = tm; ma.n = tn; } for(int i=0;i> ma.x[i]; } return s; } #endif gambit-0.2010.09.01/src/tools/gt/gnm.cc0000644000076500007650000003110511441446351014074 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "cmatrix.h" #include "gnm.h" #include "gnmgame.h" extern bool g_verbose; extern int g_numDecimals; void PrintProfile(std::ostream &p_stream, const std::string &p_label, const cvector &p_profile) { p_stream << p_label; for (int i = 0; i < p_profile.getm(); i++) { p_stream.setf(std::ios::fixed); p_stream << ',' << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } // gnm(A,g,Eq,steps,fuzz,LNMFreq,LNMMax,LambdaMin,wobble,threshold) // ---------------------------------------------------------------- // This executes the GNM algorithm on game A. // Interpretation of parameters: // g: perturbation ray. // Eq: an array of equilibria will be stored here // steps: number of steps to take within a support cell; higher // values of this parameter slow GNM down, but may help it // avoid getting off the path. // fuzz: a small floating point cutoff for a variety of things. // can probably be left at 1e-12. // LNMFreq: a Local Newton Method subroutine will be run every // LNMFreq steps to decrease accumulated errors. This // executes fairly quickly, so LNMFreq can be around 3. // LNMMax: the maximum allowed iterations within the LNM algorithm. // LambdaMin: should always be negative. Once the trajectory // gets this far out, the algorithm terminates, assuming // that there are no more equilibria on the path. // wobble: this is a boolean value indicating whether or not to use // "wobbles" of the perturbation vector to remove // accumulated errors. This removes the theoretical guarantee // of convergence, but in practice may help keep GNM on the path. // threshold: the equilibrium error threshold for doing a wobble. If // wobbles are disabled, GNM will terminate if the error // reaches this threshold. int GNM(gnmgame &A, cvector &g, cvector **&Eq, int steps, double fuzz, int LNMFreq, int LNMMax, double LambdaMin, bool wobble, double threshold) { int i, // utility variables bestAction, k, j, n, n_hat, // player whose pure strategy next enters or leaves the support s_hat_old=-1, // the last pure strategy to enter or leave the support s_hat, // the next pure strategy to enter or leave the support Index = 1, // index of the equilibrium we're moving towards numEq = 0, // number of equilibria found so far stepsLeft; // number of linear steps remaining until we hit the boundary int N = A.getNumPlayers(), M = A.getNumActions(); // the two most important cvector sizes, stored locally for brevity double bestPayoff, det, // determinant of the jacobian newV, // utility variable lambda, // current position along the ray dlambda, // derivative of lambda w.r.t time minBound, // distance to closest change of support bound, // utility variable del, // amount of time required to reach the next support boundary, // assuming linear cvector field delta, // the actual amount of time we will step forward (smaller than del) ee, V = 0.0; // scale factor for perturbation int s[M]; // current best responses int B[M]; // current support memset(B, 0, M * sizeof(int)); cmatrix DG(M,M), // jacobian of the payoff function R(M,M), // jacobian of the retraction operator I(M,M,1,1), // identity Dpsi, // jacobian of the cvector field J(M,M); // adjoint of Dpsi cvector sigma(M), // current strategy profile g0(M), // original perturbation ray z(M), // current position in space of games v(M), // current cvector of payoffs for each pure strategy dz(M), // derivative of z w.r.t. time dv(M), // derivative of v w.r.t. time nothing(M,0),// cvector of all zeros err(M), backup(M); // utility variables for use as intermediate values in computations cmatrix Y1(M,M), Y2(M,M), Y3(M,M); cvector G(N), yn1(N), ym1(M), ym2(M), ym3(M); // INITIALIZATION Eq = (cvector **)malloc(sizeof(cvector *)); // Find the lone equilibrium of the perturbed game for(n = 0; n < N; n++) { bestPayoff = g[A.firstAction(n)]; bestAction = A.firstAction(n); for(j = bestAction+1; j < A.lastAction(n); j++) { if(g[j] > bestPayoff) { bestPayoff = g[j]; bestAction = j; } } s[n] = bestAction; B[bestAction] = 1; G[n] = bestPayoff; } // initialize sigma to be the pure strategy profile // that is the lone equilibrium of the perturbed game for(i = 0; i < M; i++) { sigma[i] = (double)B[i]; } if (g_verbose) { PrintProfile(std::cout, "start", sigma); } A.payoffMatrix(DG, sigma, fuzz); DG.multiply(sigma, v); v /= (double)(N-1); // Scale g until the equilibrium sigma calculated above // is in fact the one unique equilibrium, and set lambda // equal to 1 V = 0; for(n = 0; n < N; n++) { yn1[n] = v[s[n]]; for(i = A.firstAction(n); i < A.lastAction(n); i++) { if(!B[i]) { newV = (v[i]-yn1[n]) / (G[n]-g[i]); if(newV > V) V = newV; } } } lambda = 1.0; // we scale g instead V = V+1; // a little extra padding g *= V; /* for(n = 0; n < N; n++) { yn1[n] = v[s[n]]; // yn1[n] is the payoff n receives for the action we wish to make dominant for(i = A.firstAction(n); i < A.lastAction(n); i++) { if(B[i]) // if i is the action we wish to make dominant newV = yn1[n]-G[n]; else newV = yn1[n]-G[n]*(v[i]-yn1[n])/(g[i]-G[n]); if(newV>V) V = newV; } } lambda = 1.0; // we scale g instead V = V+1; // a little extra padding for(n = 0; n < N; n++) for(i = A.firstAction(n); i < A.lastAction(n); i++) { g[i] *= (V-yn1[n])/G[n]; } */ if(N <= 2) { // ensure we don't do small steps and LNM LNMFreq = 0; steps = 1; } z = g; z += v; z += sigma; // z=sigma+v+g*lambda; A.retractJac(R,B); // this outer while loop executes once for each support boundary // that the path crosses. while(1) { k = 0; // iteration counter; when k reaches LNMFreq, run LNM // within a single boundary, support unchanged // take the specified number of steps within these support boundaries. for(stepsLeft = steps; stepsLeft > 0; stepsLeft--) { //find J = Adj psi J = I; J += DG; J *= R; J -= I; J.negate(); // J = I-((I+DG)*R); det = J.adjoint(); // sets J = adjoint(J) // find derivatives of z and lambda J.multiply(g,dz); dz.negate(); //dz = -(J*g); dlambda = -det; R.multiply(dz, ym1); DG.multiply(ym1,dv); //dv = (DG*(R*dz)); ym1 = g; ym1 *= dlambda; dv += ym1; //dv += g*dlambda; //Calculate payoff cvector DG.multiply(sigma, v); v /= (double)(N-1); ym1 = g; ym1 *= lambda; v += ym1; // v = DG*sigma / (double)(N-1) + g * lambda; //Find next action that will enter or leave the support //This bit pretends that z and v change linearly and calculates //at what point z will equal v at a certain action; this //indicates that the action's probability is either //becoming 0 or becoming positive. minBound = BIGFLOAT; for(n = 0; n < N; n++) { for(i = A.firstAction(n); i < A.lastAction(n); i++) { // do not cross the same boundary we just crossed if(dz[i] != dv[s[n]] && s_hat_old != i) { bound= (z[i]-v[s[n]])/(dv[s[n]]-dz[i]); if(bound > 0.0) { // forward in time if(bound< minBound) { minBound = bound; s_hat = i; n_hat = n; } } } } } delta = del = minBound; // if the path doesn't seem to cross any more support boundaries, // and there is no equilibrium in sight, then quit; we don't know // how big a step size to take, and anyway there's a good chance // there are no more equilibria on the path. This could be // handled differently. if(minBound == BIGFLOAT && Index*(lambda+dlambda*delta) > 0) { return numEq; } // each step covers 1.0/steps of the distance to the boundary delta = del / stepsLeft; // test whether lambda will become 0 in the course of this // step, which means there's an equilibrium there if(Index*(lambda+dlambda*delta) <= 0.0) { // if there's no next support boundary, treat the equilibrium // as the next support boundary and step up to it incrementally if(minBound == BIGFLOAT && N > 2 && stepsLeft > 1) { del = -lambda / dlambda; delta = del / stepsLeft; } else { delta -= -lambda / dlambda; // delta is now just big enough ym1 = dz; // to get us to the equilibrium ym1 *= (-lambda / dlambda); z += ym1; // z += dz*delta; lambda = 0; A.retract(sigma, z); A.payoffMatrix(DG, sigma, fuzz); ee = 0.0; if(N > 2) { // if N=2, the graph is linear, so we are at a //precise equilibrium. otherwise, refine it. J = DG; J += I; J *= R; J -= I; J.negate(); //J=I-((I+DG)*R); det = J.adjoint(); ee = A.LNM(z, nothing, det, J, DG, sigma, LNMMax, fuzz,ym1,ym2,ym3); } if(ee < fuzz) { // only save high quality equilibria; // this restriction could be removed. Eq = (cvector **)realloc(Eq, (numEq+2)*sizeof(cvector *)); Eq[numEq] = new cvector(M); *(Eq[numEq++]) = sigma; PrintProfile(std::cout, "NE", sigma); } Index = -Index; s_hat_old = -1; stepsLeft++; continue; } } if(del == BIGFLOAT) { return numEq; } backup = z; // do the step ym1 = dz; ym1 *= delta; z += ym1; // z = z+dz*delta; lambda += dlambda*delta; // if we're sufficiently far out on the ray in the reverse // direction, we're probably not going back if(lambda < LambdaMin && Index == -1) { return numEq; } A.retract(sigma,z); A.payoffMatrix(DG, sigma,fuzz); if(N <= 2) break; // already at the support boundary DG.multiply(sigma,err); err /= (double)(N-1); g0 = g; g0 *= lambda; err += g0; err += sigma; err -= z; err.negate(); ee = max(err.max(),-err.min()); if(ee < fuzz && stepsLeft > 2) { // path is probably near-linear; stepsLeft = 2; // step all the way to boundary k = LNMFreq - 1; // then run LNM } if(ee > threshold) { // if we've accumulated too much error, either if(wobble) { // wobble or quit. DG.multiply(sigma, ym1); ym1 /= (double)(N-1); g = z; g -= sigma; g -= ym1; g /= lambda; // g = ((z-sigma)-((DG*sigma) / (double)(N-1)))/lambda; } else return numEq; } // if we've done LNMMax repetitions, time to get back on the path if(stepsLeft > 1 && (++k == LNMFreq)) { A.LNM(z, g0, det, J, DG, sigma, LNMMax, fuzz,ym1,ym2,ym3); k = 0; } } // end of for loop // now we've reached a support boundary // if a player's current best response is leaving the // support, we must find a new one for that player if(s[n_hat] == s_hat) for(i = A.firstAction(n_hat); i < A.lastAction(n_hat); i++) if(B[i] && i != s_hat) { s[n_hat] = i; break; } B[s_hat] = !B[s_hat]; A.retractJac(R,B); s_hat_old = s_hat; A.retract(ym1, z); sigma = ym1; sigma.support(B); sigma.unfuzz(fuzz); A.normalizeStrategy(sigma); if (g_verbose) { PrintProfile(std::cout, Gambit::ToText(lambda), sigma); } z -= ym1; z += sigma; // z = (z-x)+sigma; // wobble the perturbation cvector to put us back on an equilibrium if(N > 2 && wobble) { A.payoffMatrix(DG, sigma, fuzz); DG.multiply(sigma, ym1); ym1 /= (double)(N-1); g = z; g -= sigma; g -= ym1; g /= lambda; // g = ((z-sigma)-((DG*sigma) / (double)(N-1)))/lambda; } } } gambit-0.2010.09.01/src/tools/gt/gnm.h0000644000076500007650000000200711350032206013722 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __GNM_H #define __GNM_H #include "cmatrix.h" #include "gnmgame.h" int GNM(gnmgame &A, cvector &g, cvector **&Eq, int steps, double fuzz, int LNMFreq, int LNMMax, double LambdaMin, bool wobble, double threshold); #endif gambit-0.2010.09.01/src/tools/gt/gnmgame.cc0000644000076500007650000001510211351773315014730 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "gnmgame.h" #include "cmatrix.h" #include "math.h" gnmgame::gnmgame(int numPlayers, int *actions): numPlayers(numPlayers) { int i; numStrategies = 1; for(i = 0; i < numPlayers; i++) { numStrategies *= actions[i]; } this->actions = new int[numPlayers]; strategyOffset = new int[numPlayers+1]; numActions = 0; maxActions = 0; for(i = 0; i < numPlayers; i++) { strategyOffset[i] = numActions; this->actions[i] = actions[i]; numActions+=actions[i]; if(actions[i] > maxActions) maxActions = actions[i]; } strategyOffset[i] = numActions; } gnmgame::~gnmgame() { delete[] strategyOffset; delete[] actions; } void gnmgame::retractJac(cmatrix &dest, int *support) { int n, i, j; double totalk; for(n = 0; n < numPlayers; n++) { totalk = 0.0; for(i = firstAction(n); i < lastAction(n); i++) { totalk += support[i]; } for(i = 0; i < numActions; i++) { for(j = firstAction(n); j < lastAction(n); j++) { if(i >= firstAction(n) && i < lastAction(n) && support[i] && support[j]) { if(i==j) dest[i][j] = 1.0-1.0/totalk; else dest[i][j] = -1.0/totalk; } else dest[i][j] = 0.0; } } } } int compareDouble(const void *d1, const void *d2) { if(*(double *)d1 > *(double *)d2) return -1; else if(*(double *)d1 < *(double *)d2) return 1; else return 0; } void gnmgame::retract(cvector &dest, cvector &z) { int n, i; double v, sumz; double y[numActions]; memcpy(y,z.values(),numActions*sizeof(double)); for(n = 0; n < numPlayers; n++) { qsort(y+firstAction(n),actions[n],sizeof(double),compareDouble); sumz = y[firstAction(n)]; for(i=firstAction(n)+1; i < lastAction(n); i++) { if(sumz - (i-firstAction(n)) * y[i] > 1) break; sumz += y[i]; } v = (sumz - 1) / (double)(i-firstAction(n)); for(i = firstAction(n); i < lastAction(n); i++) { dest[i] = z[i] - v; if(dest[i] < 0.0) dest[i] = 0.0; } } } double gnmgame::LNM(cvector &z, const cvector &g, double det, cmatrix &J, cmatrix &DG, cvector &s, int MaxLNM, double fuzz, cvector &del, cvector &scratch, cvector &backup) { double b, e = BIGFLOAT, ee; int k, faulted = 0; if(MaxLNM >= 1 && det != 0.0) { b = 1.0/det; for(k = 0; k < MaxLNM; k++) { // del = z - s - DG*s / (double)(numPlayers - 1) - g; DG.multiply(s,del); del /= (double)(numPlayers - 1); del += g; del += s; del -= z; del.negate(); ee = max(del.max(),-del.min()); if(ee < fuzz) { e = ee; break; } else if(e < ee) { // we got worse z = backup; retract(s, z); payoffMatrix(DG, s, fuzz); if(faulted) // if we've already failed once, quit. return e; b /= MaxLNM; // if the full LNM step fails to improve things, e = BIGFLOAT; // take smaller steps. faulted++; continue; } e = ee; J.multiply(del, scratch); scratch *= b; backup = z; z -= scratch; // z = z - (J * del) * b; retract(s, z); payoffMatrix(DG, s, fuzz); } return ee; } else return fuzz; } void gnmgame::normalizeStrategy(cvector &s) { double sum; for(int n = 0; n < numPlayers; n++) { sum = 0.0; for(int i = firstAction(n); i < lastAction(n); i++) { sum += s[i]; } for(int i = firstAction(n); i < lastAction(n); i++) { s[i] /= sum; } } } int indexOf(int *list, int target, int length) { for(int i = 0; i < length; i++) { if(list[i] == target) return i; } return -1; } void gnmgame::LemkeHowson(cvector &dest, cmatrix &T, int *Im) { double D = 1; int cg = numActions + numPlayers ; int K = cg+1; int n, pc, pr, p; double m; int col[numActions+numPlayers+2], row[numActions+numPlayers]; for(n = 0; n < numActions+numPlayers+2; n++) col[n] = n+1; for(n = 0; n < numActions+numPlayers; n++) row[n] = -n-1; for(n = 0; n < numPlayers; n++) { pc = indexOf(col, Im[n]+1, numActions+numPlayers+2); pr = indexOf(row,-numActions-n-1, numActions+numPlayers); p = Pivot(T, pr, pc, row, col, D); pc = indexOf(col, numActions+n+1, numActions+numPlayers+2); pr = indexOf(row, -Im[n]-1, numActions+numPlayers); p = Pivot(T, pr, pc, row, col, D); } pc = indexOf(col, cg+1, numActions+numPlayers+2); m = -BIGFLOAT; pr = -1; for(n = 0; n < numPlayers + numActions; n++) { if(T[n][pc] < 0) { if(T[n][K] / T[n][pc] > m) { m = T[n][K] / T[n][pc]; pr = n; } } } if(m > 0) { p = Pivot(T, pr, pc, row, col, D); do { pc = indexOf(col, -p, numActions+numPlayers+2); m = BIGFLOAT; pr = -1; for(n = 0; n < numPlayers + numActions; n++) { if(T[n][pc] > 0 && (row[n] <= numActions || row[n] > numActions+numPlayers)) { if(T[n][K] / T[n][pc] < m) { m = T[n][K] / T[n][pc]; pr = n; } } } p = Pivot(T, pr, pc, row, col, D); } while(p != cg+1); } for(n = 0; n < numActions; n++) { pr = indexOf(row,n+1,numActions+numPlayers); if(pr == -1) dest[n] = 0.0; else dest[n] = T[pr][K] / D; } } int gnmgame::Pivot(cmatrix &T, int pr, int pc, int *row, int *col, double &D) { double pivot = T[pr][pc]; int i0,j0,p,sgn = pivot < 0 ? -1 : 1; for(i0 = 0; i0 < numActions+numPlayers; i0++) { if(i0 != pr) { for(j0 = 0; j0 < numActions+numPlayers+2; j0++) { if(j0 != pc) { T[i0][j0] *= pivot; T[i0][j0] -= T[i0][pc] * T[pr][j0]; T[i0][j0] /= D * sgn; } } } } if(sgn == 1) { for(i0 = 0; i0 < numActions+numPlayers; i0++) { T[i0][pc] = -T[i0][pc]; } } else { for(j0 = 0; j0 < numActions+numPlayers+2; j0++) { T[pr][j0] = -T[pr][j0]; } } T[pr][pc] = sgn * D; D = pivot < 0 ? -pivot : pivot; p = row[pr]; row[pr] = col[pc]; col[pc] = p; if(D > 1e6) { T /= D; D = 1; } return p; } gambit-0.2010.09.01/src/tools/gt/gnmgame.h0000644000076500007650000000643711351773315014605 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __GNMGAME_H #define __GNMGAME_H #include "cmatrix.h" #define BIGFLOAT 3.0e+28F class gnmgame { public: //actions[i] = number of actions player i has gnmgame(int numplayers, int *actions); virtual ~gnmgame(); // Input: s[i] has integer index of player i's pure strategy // s is of length numPlayers virtual double getPurePayoff(int player, int *s) = 0; virtual void setPurePayoff(int player, int *s, double value) = 0; // The actions of all players are combined in one linear array of length // numActions; this gives the index of a player's first action in the array. inline int firstAction(int player) { return strategyOffset[player]; } inline int lastAction(int player) { return strategyOffset[player+1]; } // s is the mixed strategy profile. It is of length numActions, and // s[i] is the probability that the appropriate player takes action i. virtual double getMixedPayoff(int player, cvector &s) = 0; // s is the mixed strategy profile, as above. This function stores // the Jacobian of the payoff function G, where G(i) is the payoff to // the owner of action i if he deviates from s by choosing i instead. virtual void payoffMatrix(cmatrix &dest, cvector &s, double fuzz) = 0; // this stores the Jacobian of the retraction function in dest. void retractJac(cmatrix &dest, int *support); // This retracts z onto the nearest normalized strategy profile, according // to the Euclidean metric void retract(cvector &dest, cvector &z); // LNM runs the local Newton method on z to attempt to bring it closer to // the image of the graph of the equilibrium correspondence above the ray, // under the homeomorphism. In order to prevent costly memory allocation, // a number of scratch vectors are passed in. double LNM(cvector &z, const cvector &g, double det, cmatrix &J, cmatrix &DG, cvector &s, int MaxLNM, double fuzz, cvector &del, cvector &scratch, cvector &backup); // This normalizes a strategy profile by scaling appropriately. void normalizeStrategy(cvector &s); void LemkeHowson(cvector &dest, cmatrix &T, int *Im); inline int getNumPlayers() { return numPlayers; } inline int getNumActions() { return numActions; } inline int getNumActions(int p) { return actions[p]; } inline int getMaxActions() { return maxActions; } protected: int Pivot(cmatrix &T, int pr, int pc, int *row, int *col, double &D); int *strategyOffset; int numPlayers, numStrategies, numActions; int *actions; int maxActions; }; #endif gambit-0.2010.09.01/src/tools/gt/ipa.cc0000644000076500007650000001313011350032206014047 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "cmatrix.h" #include "ipa.h" #include "gnmgame.h" // IPA(A,g,zh,alpha,fuzz,ans) // -------------------------- // This runs the IPA algorithm on game A. // Interpretation of parameters: // g: perturbation ray. // zh: initial approximation for z. Can be set to vector of all 1's. // alpha: stepsize. Must be a number between 0 and 1, to be interpreted // as the fraction of a complete step to take. // fuzz: the cutoff accuracy for an equilibrium after which the algorithm // stops refining it // ans: a pre-allocated vector in which the equilibrium will be stored int IPA(gnmgame &A, cvector &g, cvector &zh, double alpha, double fuzz, cvector &ans) { int N = A.getNumPlayers(), M = A.getNumActions(), // For easy reference i,j,n,bestAction,B, // utility vars Im[N], // best actions in perturbed game firstIteration = 1; double bestPayoff,l; // utility vars cmatrix DG(M,M), O(N,N,0), // matrix of zeroes S(N,M,0), // I(M+N,M+N,1,1), // identity T(M+N,M+N+2,0), // tableau for Lemke-Howson T2(M+N,M+N,0); // submatrix of tableau used if Lemke-Howson is unnecessary cvector d(M), // diff u(M), y(M), // old z yh(M), // old zh s(M), // current strategy so(M), // old strategy sh(M), // approximate strategy sho(M,0), // old approximate strategy z(M), // current point in game-space zt(M), // next approximating point ym1(M), // utility vars ym2(M), ymn1(M+N), ymn2(M+N); // Find the best action for each player when the game is highly perturbed for(n = 0; n < N; n++) { bestPayoff = g[A.firstAction(n)]; bestAction = A.firstAction(n); for(j = bestAction+1; j < A.lastAction(n); j++) { if(g[j] > bestPayoff) { bestPayoff = g[j]; bestAction = j; } } Im[n] = bestAction; } A.retract(sh, zh); so = sh; while(1) { A.payoffMatrix(DG,sh,0.0); DG /= (double)(N-1); // find the Jacobian of the approximating bimatrix game // Initialize the Lemke-Howson tableau for(n = 0; n < N; n++) { for(i = 0; i < M+N; i++) { if(i >= A.firstAction(n) && i < A.lastAction(n)) { T[M+n][i] = 1; T[i][M+n] = -1; } else { T[M+n][i] = T[i][M+n] = 0; } } } for(n = 0; n < M; n++) { T[n][M+N] = g[n]; T[n][M+N+1] = 0.0; } for(n = 0; n < N; n++) { T[M+n][M+N+1] = 1.0; T[M+n][M+N] = 0.0; } for(i = 0; i < M; i++) for(j = 0; j < M; j++) T[i][j] = DG[i][j]; // copy the tableau to T2 for(i = 0; i < M+N; i++) for(j = 0; j < M+N; j++) T2[i][j] = T[i][j]; // zero out columns not in the support for(i = 0; i < M; i++) { if(so[i] <= 0.0) { for(j = 0; j < M+N; j++) { if(i == j) T2[j][i] = 1.0; else T2[j][i] = 0.0; } } } for(i = 0; i < M; i++) { ymn1[i] = 0; } for(i = M; i < M+N; i++) { ymn1[i] = 1; } // find equilibrium assuming current support T2.solve(ymn1, ymn2); for(i = 0; i < M; i++) s[i] = ymn2[i]; int flag = 0; for(i = 0; i < M; i++) { if(s[i] < 0.0) { flag = 1; // need to update the support break; } } if(flag) { // update support and solve A.LemkeHowson(s,T,Im); } else { // limit to current support for(i = 0; i < M; i++) { if(so[i] <= 0.0) s[i] = 0.0; } } DG.multiply(s,z); z += s; // see if the support has changed B = 1; for(i = 0; i < M; i++) { if((s[i] > 0.0) != (so[i] > 0.0)) { B = 0; break; } } // see if angle between z-sh and zh-sh is acute; if so, scale zh. u = zh; u -= sh; ym1 = z; ym1 -= sh; l = (ym1 * u) / u.norm2(); // dot product if(l <= 0.0 || B) { zh = u; zh *= l; zh += sh; yh -= sho; yh *= l; yh += sho; } ym1 = z; ym1 -= zh; ym2 = s; ym2 -= sh; // if z and zh or s and sh are close enough, // we've got an approximate equilibrium, so we can quit if(N <= 2 || (ym1.norm() < fuzz || ym2.norm() < fuzz)) { ans = s; A.payoffMatrix(DG,s,0.0); return 1; } ym1 = z; // do a first-order approximation on the first iteration, // and subsequently do a second-order approximation if(!firstIteration) { d = z; d -= zh; d -= y; d += yh; // Rule of false position if(B && d.absmax() > fuzz) { for(i = 0; i < M; i++) { ym1[i] = (yh[i] * z[i] - zh[i] * y[i])/d[i]; } } else { // Only do a first-order approximation ym1 = z; } } else { firstIteration = 0; ym1 = z; } zt = ym1; zt *= alpha / (1-alpha); zt += zh; zt *= (1-alpha); // zt = ym1*alpha + zh * (1-alpha) // Update values so = s; y = z; sho = sh; yh = zh; zh = zt; A.retract(sh,zh); } } gambit-0.2010.09.01/src/tools/gt/ipa.h0000644000076500007650000000171511350032206013717 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __IPA_H #define __IPA_H #include "cmatrix.h" #include "gnmgame.h" int IPA(gnmgame &A, cvector &g, cvector &zh, double alpha, double fuzz, cvector &ans); #endif gambit-0.2010.09.01/src/tools/gt/nfgame.cc0000644000076500007650000001057011350032206014540 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "cmatrix.h" #include "nfgame.h" nfgame::nfgame(int numPlayers, int *actions, const cvector &payoffs) : gnmgame(numPlayers, actions), payoffs(payoffs) { blockSize = new int[numPlayers + 1]; blockSize[0] = 1; for(int i = 1; i <= numPlayers; i++) { blockSize[i] = blockSize[i-1]*actions[i-1]; } } nfgame::~nfgame() { delete[] blockSize; } int nfgame::findIndex(int player, int *s) { int i, retIndex=player * blockSize[numPlayers]; for(i = 0; i < numPlayers; i++) retIndex += blockSize[i] * s[i]; return retIndex; } double nfgame::getMixedPayoff(int player, cvector &s) { double m[blockSize[numPlayers]]; memcpy(m, payoffs.values() + player * blockSize[numPlayers], blockSize[numPlayers]*sizeof(double)); return localPayoff(s, m, numPlayers); } void nfgame::payoffMatrix(cmatrix &dest, cvector &s, double fuzz) { int rown, coln, rowi, coli; double fuzzcount; double m[blockSize[numPlayers]]; double local[maxActions*maxActions]; for(rown = 0; rown < numPlayers; rown++) { for(coln = 0; coln < numPlayers; coln++) { if(rown == coln) { fuzzcount = fuzz; for(rowi=firstAction(rown); rowi < lastAction(rown); rowi++) { for(coli=firstAction(coln); coli < lastAction(coln); coli++) { dest[rowi][coli]=fuzzcount; fuzzcount += fuzz; } } } else { // set m to be the payoffs for player rown memcpy(m, payoffs.values() + rown * blockSize[numPlayers], blockSize[numPlayers] * sizeof(double)); localPayoffMatrix(local, rown, coln, s, m, numPlayers-1); for(rowi = firstAction(rown); rowi < lastAction(rown); rowi++) { for(coli = firstAction(coln); coli < lastAction(coln); coli++) { if(rown > coln) { dest[rowi][coli] = *(local + (rowi - firstAction(rown))*actions[coln] + (coli - firstAction(coln))); } else { dest[rowi][coli] = *(local + (coli - firstAction(coln))*actions[rown] + (rowi - firstAction(rown))); } } } } } } } //assumes m = memcpy(m, payoffs + blockSize[numPlayers] * player1, blockSize[numPlayers]*sizeof(double)), player1 != player2 //i.e. m points to payoff cmatrix for the desired player void nfgame::localPayoffMatrix(double *dest, int player1, int player2, cvector &s, double *m, int n) { int i; if(player1 == n) { for(i = 0; i < actions[player1]; i++) { localPayoffVector(dest+i*actions[player2], player2, s, m+i*blockSize[player1], n-1); } } else if(player2 == n) { for(i = 0; i < actions[player2]; i++) { localPayoffVector(dest+i*actions[player1], player1, s, m+i*blockSize[player2], n-1); } } else { m = scaleMatrix(s, m, n); localPayoffMatrix(dest, player1, player2, s, m, n-1); } } double *nfgame::scaleMatrix(cvector &s, double *m, int n) { int i,j, curbase, newbase = -1; double scale; for(i = 0; i < actions[n]; i++) { if(s[i+firstAction(n)] > 0.0) { scale = s[i+firstAction(n)]; curbase = i*blockSize[n]; if(newbase < 0) { newbase = curbase; for(j = curbase; j < curbase+blockSize[n]; j++) { m[j] *= scale; } } else { for(j = 0; j < blockSize[n]; j++) { m[newbase + j] += scale * m[curbase+j]; } } } } return m+newbase; } void nfgame::localPayoffVector(double *dest, int player, cvector &s, double *m, int n) { if(player == n) { for(int i = 0; i < actions[player]; i++) { dest[i] = localPayoff(s, m+i*blockSize[player], n-1); } } else { m = scaleMatrix(s, m, n); localPayoffVector(dest, player, s, m, n-1); } } double nfgame::localPayoff(cvector &s, double *m, int n) { if(n < 0) return *m; else { m = scaleMatrix(s, m, n); return localPayoff(s, m, n-1); } } gambit-0.2010.09.01/src/tools/gt/nfgame.h0000644000076500007650000000340411350032206014400 00000000000000/* Copyright 2002 Ben Blum, Christian Shelton * * This file is part of GameTracer. * * GameTracer 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. * * GameTracer 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 GameTracer; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __NFGAME_H #define __NFGAME_H #include "gnmgame.h" #include "cmatrix.h" class nfgame : public gnmgame { public: nfgame(int numPlayers, int *actions, const cvector &payoffs); ~nfgame(); // Input: s[i] has integer index of player i's pure strategy // s is of length numPlayers inline double getPurePayoff(int player, int *s) { return payoffs[findIndex(player, s)]; } inline void setPurePayoff(int player, int *s, double value) { payoffs[findIndex(player, s)]= value; } double getMixedPayoff(int player, cvector &s); void payoffMatrix(cmatrix &dest, cvector &s, double fuzz); private: int findIndex(int player, int *s); void localPayoffMatrix(double *dest, int player1, int player2, cvector &s, double *m, int n); void localPayoffVector(double *dest, int player, cvector &s, double *m, int n); double localPayoff(cvector &s, double *m, int n); double *scaleMatrix(cvector &s, double *m, int n); cvector payoffs; int *blockSize; }; #endif gambit-0.2010.09.01/src/tools/gt/nfggnm.cc0000644000076500007650000001425411435216102014565 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/gt/nfggnm.cc // Gambit frontend to Gametracer global Newton method // // 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 #include #include #include #include "libgambit/libgambit.h" #include "nfgame.h" #include "gnmgame.h" #include "gnm.h" // GNM CONSTANTS const int STEPS = 100; const double FUZZ = 1e-12; const int LNMFREQ = 3; const int LNMMAX = 10; const double LAMBDAMIN = -10.0; const bool WOBBLE = false; const double THRESHOLD = 1e-2; int g_numDecimals = 6; bool g_verbose = false; int g_numVectors = 1; std::string g_startFile; bool ReadProfile(std::istream &p_stream, cvector &p_profile) { for (int i = 0; i < p_profile.getm(); i++) { if (p_stream.eof() || p_stream.bad()) { return false; } p_stream >> p_profile[i]; if (i < p_profile.getm() - 1) { char comma; p_stream >> comma; } } // Read in the rest of the line and discard std::string foo; std::getline(p_stream, foo); return true; } extern void PrintProfile(std::ostream &, const std::string &, const cvector &); void PrintBanner(std::ostream &p_stream) { p_stream << "Compute Nash equilibria using a global Newton method\n"; p_stream << "Gametracer version 0.2, Copyright (C) 2002, Ben Blum and Christian Shelton\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "Options:\n"; std::cerr << " -d DECIMALS show equilibria as floating point with DECIMALS digits\n"; std::cerr << " -h print this help message\n"; std::cerr << " -n COUNT number of perturbation vectors to generate\n"; std::cerr << " -s FILE file containing perturbation vectors\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; std::cerr << " -v verbose mode (shows intermediate output)\n"; std::cerr << " (default is to only show equilibria)\n"; exit(1); } void Solve(const Gambit::Game &p_game) { int i; Gambit::Rational maxPay = p_game->GetMaxPayoff(); Gambit::Rational minPay = p_game->GetMinPayoff(); double scale = 1.0 / (maxPay - minPay); int *actions = new int[p_game->NumPlayers()]; int veclength = p_game->NumPlayers(); for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { actions[pl-1] = p_game->GetPlayer(pl)->NumStrategies(); veclength *= p_game->GetPlayer(pl)->NumStrategies(); } cvector payoffs(veclength); gnmgame *A = new nfgame(p_game->NumPlayers(), actions, payoffs); int *profile = new int[p_game->NumPlayers()]; for (Gambit::StrategyIterator iter(p_game); !iter.AtEnd(); iter++) { for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { profile[pl-1] = iter->GetStrategy(pl)->GetNumber() - 1; } for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { A->setPurePayoff(pl-1, profile, (double) (iter->GetPayoff(pl) - minPay) * scale); } } cvector g(A->getNumActions()); // choose a random perturbation ray int numEq; if (g_startFile != "") { std::ifstream startVectors(g_startFile.c_str()); while (!startVectors.eof() && !startVectors.bad()) { cvector **answers; if (ReadProfile(startVectors, g)) { g /= g.norm(); // normalized if (g_verbose) { PrintProfile(std::cout, "pert", g); } numEq = GNM(*A, g, answers, STEPS, FUZZ, LNMFREQ, LNMMAX, LAMBDAMIN, WOBBLE, THRESHOLD); for (i = 0; i < numEq; i++) { free(answers[i]); } free(answers); } } } else { for (int iter = 0; iter < g_numVectors; iter++) { cvector **answers; for(i = 0; i < A->getNumActions(); i++) { #if !defined(HAVE_DRAND48) g[i] = rand(); #else g[i] = drand48(); #endif // HAVE_DRAND48 } g /= g.norm(); // normalized if (g_verbose) { PrintProfile(std::cout, "pert", g); } numEq = GNM(*A, g, answers, STEPS, FUZZ, LNMFREQ, LNMMAX, LAMBDAMIN, WOBBLE, THRESHOLD); for (i = 0; i < numEq; i++) { free(answers[i]); } free(answers); } } delete A; } int main(int argc, char *argv[]) { opterr = 0; bool quiet = false; int c; while ((c = getopt(argc, argv, "d:n:s:qvhS")) != -1) { switch (c) { case 'q': quiet = true; break; case 'v': g_verbose = true; break; case 'd': g_numDecimals = atoi(optarg); break; case 'n': g_numVectors = atoi(optarg); break; case 's': g_startFile = optarg; break; case 'S': break; case 'h': PrintHelp(argv[0]); break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Gambit::Game game = Gambit::ReadGame(std::cin); game->BuildComputedValues(); Solve(game); return 0; } catch (Gambit::InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } } gambit-0.2010.09.01/src/tools/gt/nfgipa.cc0000644000076500007650000001104711435216102014552 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/gt/nfgipa.cc // Gambit frontend to Gametracer IPA // // 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 #include #include #include #include "libgambit/libgambit.h" #include "nfgame.h" #include "ipa.h" #define ALPHA 0.02 #define EQERR 1e-6 int g_numDecimals = 6; void PrintProfile(std::ostream &p_stream, const Gambit::Game &p_game, cvector *p_profile) { p_stream.setf(std::ios::fixed); p_stream << "NE"; for (int i = 0; i < p_game->MixedProfileLength(); i++) { p_stream << "," << std::setprecision(g_numDecimals) << (*p_profile)[i]; } p_stream << std::endl; } void PrintBanner(std::ostream &p_stream) { p_stream << "Compute Nash equilibria using iterated polymatrix approximation\n"; p_stream << "Gametracer version 0.2, Copyright (C) 2002, Ben Blum and Christian Shelton\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "Options:\n"; std::cerr << " -d DECIMALS show equilibria as floating point with DECIMALS digits\n"; std::cerr << " -h print this help message\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; exit(1); } void Solve(const Gambit::Game &p_game, const Gambit::Array &p_pert) { int i; int *actions = new int[p_game->NumPlayers()]; int veclength = p_game->NumPlayers(); for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { actions[pl-1] = p_game->GetPlayer(pl)->NumStrategies(); veclength *= p_game->GetPlayer(pl)->NumStrategies(); } cvector payoffs(veclength); gnmgame *A = new nfgame(p_game->NumPlayers(), actions, payoffs); int *profile = new int[p_game->NumPlayers()]; for (Gambit::StrategyIterator iter(p_game); !iter.AtEnd(); iter++) { for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { profile[pl-1] = iter->GetStrategy(pl)->GetNumber() - 1; } for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { A->setPurePayoff(pl-1, profile, iter->GetPayoff(pl)); } } cvector g(A->getNumActions()); // perturbation ray int numEq; cvector ans(A->getNumActions()); cvector zh(A->getNumActions(),1.0); do { for(i = 0; i < A->getNumActions(); i++) { g[i] = p_pert[i+1]; } g /= g.norm(); // normalized numEq = IPA(*A, g, zh, ALPHA, EQERR, ans); } while(numEq == 0); PrintProfile(std::cout, p_game, &ans); delete A; } int main(int argc, char *argv[]) { opterr = 0; bool quiet = false; int c; while ((c = getopt(argc, argv, "d:qhS")) != -1) { switch (c) { case 'q': quiet = true; break; case 'd': g_numDecimals = atoi(optarg); break; case 'S': break; case 'h': PrintHelp(argv[0]); break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Gambit::Game game = Gambit::ReadGame(std::cin); game->BuildComputedValues(); Gambit::Array pert(game->MixedProfileLength()); for (int i = 1; i <= pert.Length(); i++) { pert[i] = 1.0; } Solve(game, pert); return 0; } catch (Gambit::InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } } gambit-0.2010.09.01/src/tools/lcp/0000777000076500007650000000000011441457122013232 500000000000000gambit-0.2010.09.01/src/tools/lcp/basis.cc0000644000076500007650000001027211435216102014552 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/basis.cc // Implementation of Basis class // // 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 "basis.h" // --------------------------------------------------------------------------- // Class Basis // --------------------------------------------------------------------------- // ----------------------- // C-tor, D-tor, Operators // ----------------------- Basis::Basis(int first, int last, int firstlabel, int lastlabel) : basis(first, last), cols(firstlabel, lastlabel), slacks(first, last), colBlocked(firstlabel,lastlabel), rowBlocked(first,last) { int i; for(i = cols.First(); i <= cols.Last(); i++) { cols[i] = 0; colBlocked[i] = false; } for(i = basis.First(); i <= basis.Last(); i++) { basis[i]= - i; slacks[i] = i; rowBlocked[i] = false; } IsBasisIdent = true; } Basis::Basis(const Basis &bas) : basis(bas.basis), cols( bas.cols ), slacks( bas.slacks ), colBlocked(bas.colBlocked), rowBlocked(bas.rowBlocked), IsBasisIdent(bas.IsBasisIdent) { } Basis::~Basis() { } Basis& Basis::operator=(const Basis &orig) { if(this != &orig) { basis = orig.basis; cols = orig.cols; slacks = orig.slacks; rowBlocked = orig.rowBlocked; colBlocked = orig.colBlocked; IsBasisIdent = orig.IsBasisIdent; } return *this; } // ------------------------- // Public Members // ------------------------- int Basis::First() const { return basis.First();} int Basis::Last() const { return basis.Last();} int Basis::MinCol() const { return cols.First();} int Basis::MaxCol() const { return cols.Last();} bool Basis::IsRegColumn( int col ) const {return col >= cols.First() && col <= cols.Last();} bool Basis::IsSlackColumn( int col ) const {return -col >= basis.First() && -col <= basis.Last();} int Basis::Pivot(int outindex, int col) { int outlabel = basis[outindex]; if (IsSlackColumn(col)) slacks[-col] = outindex; else if (IsRegColumn(col)) cols[col] = outindex; else throw Gambit::IndexException(); // not a valid column to pivot in. if (IsSlackColumn(outlabel)) slacks[-outlabel] = 0; else if (IsRegColumn(outlabel)) cols[outlabel] = 0; else { // Note: here, should back out outindex. throw Gambit::IndexException(); // not a valid column to pivot out. } basis[outindex] = col; CheckBasis(); return outlabel; } bool Basis::Member( int col ) const { int ret; if (IsSlackColumn(col)) ret = slacks[-col]; else if (IsRegColumn(col)) ret = cols[col]; else ret = 0; return (ret != 0); } int Basis::Find( int col ) const { int ret; if ( IsSlackColumn(col)) ret = slacks[-col]; else if (IsRegColumn(col)) ret = cols[col]; else throw Gambit::IndexException(); return ret; } int Basis::Label(int index) const { return basis[index]; } void Basis::Mark(int col ) { if (IsSlackColumn(col)) rowBlocked[-col] = true; else if (IsRegColumn(col)) colBlocked[col] = true; } void Basis::UnMark(int col ) { if (IsSlackColumn(col)) rowBlocked[-col] = false; else if (IsRegColumn(col)) colBlocked[col] = false; } bool Basis::IsBlocked(int col) const { if (IsSlackColumn(col)) return rowBlocked[-col]; else if (IsRegColumn(col)) return colBlocked[col]; return false; } void Basis::CheckBasis() { bool check = true; for (int i =basis.First(); i <= basis.Last() && check; i++) if(basis[i] != -i) check = false; IsBasisIdent = check; } bool Basis::IsIdent() { return IsBasisIdent; } gambit-0.2010.09.01/src/tools/lcp/basis.h0000644000076500007650000000543711435216102014423 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/basis.h // Declaration of basis class for tableaus // // 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 BASIS_H #define BASIS_H #include "libgambit/libgambit.h" //--------------------------------------------------------------------------- // Class Basis //--------------------------------------------------------------------------- class Basis { private: Gambit::Array basis; // current members of basis (neg for slacks) Gambit::Array cols; // location of col in basis (0 if not in basis) Gambit::Array slacks; // location of slacks in basis Gambit::Array colBlocked; Gambit::Array rowBlocked; bool IsBasisIdent; public: //------------------------------------------- // Constructors, Destructor, Operators //------------------------------------------- Basis(int first, int last, int firstlabel, int lastlabel); Basis(const Basis &); virtual ~Basis(); Basis& operator=(const Basis&); //------------------------------ // Public Members //------------------------------ int First() const; // First basis index int Last() const; // Last basis index int MinCol() const; // First Column label int MaxCol() const; // Last Column label bool IsRegColumn( int col ) const; bool IsSlackColumn( int col ) const; //remove outindex, insert label, return outlabel int Pivot(int outindex, int col); // return true iff label is a Basis member bool Member(int label) const; // finds Basis index corresponding to label number, int Find(int label) const; // finds label of variable corresponding to Basis index int Label(int index) const; // marks/unmarks label to block it from entering basis void Mark(int label); void UnMark(int label); // returns true if label is blocked from entering basis bool IsBlocked(int label) const; // Check if Basis is Ident virtual void CheckBasis(); // returns whether the basis is the identity matrix bool IsIdent(); }; #endif // BASIS_H gambit-0.2010.09.01/src/tools/lcp/bfs.cc0000644000076500007650000000343111435216102014222 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/bfs.cc // Implementation of basic feasible solution class // // 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 "libgambit/libgambit.h" #include "libgambit/rational.h" #include "bfs.h" //-------------------------------------------------------------------------- // class BFS: member functions //-------------------------------------------------------------------------- template BFS::BFS(void) : Gambit::Map((T) 0) { } template BFS::BFS(const T &d) : Gambit::Map((T) d) { } template BFS::BFS(const BFS &m) : Gambit::Map(m) { } template int BFS::operator==(const BFS &M) const { if (this->length != M.length) return 0; for (int i = 0; i < this->length; i++) if (this->keys[i] != M.keys[i]) return 0; return 1; } template int BFS::operator!=(const BFS &M) const { return !(*this == M); } template class BFS; template class BFS; gambit-0.2010.09.01/src/tools/lcp/bfs.h0000644000076500007650000000237311435216102014070 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/bfs.h // Interface to basic feasible solution class // // 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 BFS_H #define BFS_H #include "libgambit/map.h" template class BFS : public Gambit::Map { public: BFS(void); BFS(const T &d); BFS(const BFS &m); // define two BFS's to be equal if their bases are equal int operator==(const BFS &M) const; int operator!=(const BFS &M) const; }; #endif // BFS_H gambit-0.2010.09.01/src/tools/lcp/btableau.cc0000644000076500007650000000217411435216102015232 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/btableau.cc // Instantiation of base tableau classes // // 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 "libgambit/libgambit.h" #include "btableau.imp" template class BaseTableau; template class BaseTableau; template class TableauInterface; template class TableauInterface; gambit-0.2010.09.01/src/tools/lcp/btableau.h0000644000076500007650000001150311435216102015070 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/btableau.h // Interface to base tableau classes // // 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 BTABLEAU_H #define BTABLEAU_H #include "libgambit/rational.h" #include "bfs.h" #include "basis.h" // --------------------------------------------------------------------------- // BaseTableau Stuff // --------------------------------------------------------------------------- template class BaseTableau { public: class BadPivot : public Gambit::Exception { public: virtual ~BadPivot() { } std::string GetDescription(void) const { return "Bad Pivot in BaseTableau"; } }; virtual ~BaseTableau() { } bool ColIndex(int) const; bool RowIndex(int) const; bool ValidIndex(int) const; virtual int MinRow() const = 0; virtual int MaxRow() const = 0; virtual int MinCol() const = 0; virtual int MaxCol() const = 0; virtual bool Member(int i) const = 0; // is variable i is a member of basis virtual int Label(int i) const = 0; // return variable in i'th position of Tableau virtual int Find(int i) const = 0; // return position of variable i // pivoting virtual int CanPivot(int outgoing,int incoming) = 0; virtual void Pivot(int outrow,int col) = 0; // perform pivot operation -- outgoing is row, incoming is column void CompPivot(int outlabel,int col); virtual long NumPivots() const = 0; // raw Tableau functions virtual void Refactor() = 0; }; // --------------------------------------------------------------------------- // TableauInterface Stuff // --------------------------------------------------------------------------- template class TableauInterface : public BaseTableau{ protected: const Gambit::Matrix *A; // should this be private? const Gambit::Vector *b; // should this be private? Basis basis; Gambit::Vector solution; // current solution vector. should this be private? long npivots; T eps1,eps2; Gambit::Array artificial; // artificial variables public: TableauInterface(const Gambit::Matrix &A, const Gambit::Vector &b); TableauInterface(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); TableauInterface(const TableauInterface&); virtual ~TableauInterface(); TableauInterface& operator=(const TableauInterface&); // information int MinRow() const; int MaxRow() const; int MinCol() const; int MaxCol() const; Basis & GetBasis(void); const Gambit::Matrix & Get_A(void) const; const Gambit::Vector & Get_b(void) const; bool Member(int i) const; int Label(int i) const; // return variable in i'th position of Tableau int Find(int i) const; // return Tableau position of variable i long NumPivots() const; long &NumPivots(); void Mark(int label); // marks label to block it from entering basis void UnMark(int label); // unmarks label bool IsBlocked(int label) const; // returns true if label is blocked virtual void BasisVector(Gambit::Vector &x) const = 0; // solve M x = (*b) void GetColumn( int , Gambit::Vector &) const; // raw column void GetBasis( Basis & ) const; // return Basis for current Tableau BFS GetBFS1(void) const; BFS GetBFS(void); // used in lpsolve for some reason virtual int CanPivot(int outgoing,int incoming) = 0; virtual void Pivot(int outrow,int col) = 0; // pivot -- outgoing is row, incoming is column virtual void SolveColumn(int, Gambit::Vector &) = 0; // column in new basis virtual void Solve(const Gambit::Vector &b, Gambit::Vector &x) = 0; // solve M x = b virtual void SolveT(const Gambit::Vector &c, Gambit::Vector &y) = 0; // solve y M = c virtual void Refactor() = 0; virtual void SetRefactor(int) = 0; // miscellaneous functions bool EqZero(T x) const; bool LtZero(T x) const; bool GtZero(T x) const; bool LeZero(T x) const; bool GeZero(T x) const; T Epsilon(int i = 2) const; bool IsArtifColumn(int col) const; }; #endif // BTABLEAU_H gambit-0.2010.09.01/src/tools/lcp/btableau.imp0000644000076500007650000001534211435216102015433 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/btableau.imp // Implementation of base tableau classes // // 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. // // --------------------------------------------------------------------------- // BaseTableau method definitions // --------------------------------------------------------------------------- #include "btableau.h" template bool BaseTableau::ColIndex(int x) const { return MinCol()<=x && x<=MaxCol(); } template bool BaseTableau::RowIndex(int x) const { return MinRow()<=x && x<=MaxRow(); } template bool BaseTableau::ValidIndex(int x) const { return (ColIndex(x) || RowIndex(-x)); } template void BaseTableau::CompPivot(int outlabel, int col) { Pivot(Find(outlabel),col); Pivot(Find(-col),-outlabel); } // --------------------------------------------------------------------------- // TableauInterface method definitions // --------------------------------------------------------------------------- // Constructors and Destructor template TableauInterface::TableauInterface(const Gambit::Matrix &A, const Gambit::Vector &b) : A(&A), b(&b), basis(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()), solution(A.MinRow(),A.MaxRow()), npivots(0), artificial(A.MaxCol()+1,A.MaxCol()) { // These are the values recommended by Murtagh (1981) for 15 digit // accuracy in LP problems // Note: for gRational, eps1 and eps2 resolve to 0 Gambit::Epsilon(eps1,5); Gambit::Epsilon(eps2); } template TableauInterface::TableauInterface(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : A(&A), b(&b), basis(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()+art.Length()), solution(A.MinRow(),A.MaxRow()), npivots(0), artificial(A.MaxCol()+1,A.MaxCol()+art.Length()) { Gambit::Epsilon(eps1,5); Gambit::Epsilon(eps2); for(int i = 0;i TableauInterface::TableauInterface(const TableauInterface &orig) : A(orig.A), b(orig.b), basis(orig.basis), solution(orig.solution), npivots(orig.npivots), eps1(orig.eps1), eps2(orig.eps2), artificial(orig.artificial) { } template TableauInterface::~TableauInterface() { } template TableauInterface& TableauInterface::operator=(const TableauInterface &orig) { if(this!= &orig) { A = orig.A; b = orig.b; basis= orig.basis; solution= orig.solution; npivots = orig.npivots; artificial = orig.artificial; } return *this; } // getting information template int TableauInterface::MinRow() const { return A->MinRow(); } template int TableauInterface::MaxRow() const { return A->MaxRow(); } template int TableauInterface::MinCol() const { return basis.MinCol(); } template int TableauInterface::MaxCol() const { return basis.MaxCol(); } template Basis & TableauInterface::GetBasis(void) {return basis; } template const Gambit::Matrix & TableauInterface::Get_A(void) const {return *A; } template const Gambit::Vector & TableauInterface::Get_b(void) const {return *b;} template bool TableauInterface::Member(int i) const { return basis.Member(i);} template int TableauInterface::Label(int i) const { return basis.Label(i);} template int TableauInterface::Find(int i) const { return basis.Find(i);} template long TableauInterface::NumPivots() const { return npivots; } template long &TableauInterface::NumPivots() { return npivots; } template void TableauInterface::Mark(int label) {basis.Mark(label);} template void TableauInterface::UnMark(int label) {basis.UnMark(label);} template bool TableauInterface::IsBlocked(int label) const { return basis.IsBlocked(label); } template void TableauInterface::GetColumn(int col, Gambit::Vector &ret) const { if(IsArtifColumn(col)) { ret = (T) 0; ret[artificial[col]] = (T)1; } else if(basis.IsRegColumn(col)) A->GetColumn(col, ret); else if (basis.IsSlackColumn(col)) { ret = (T) 0; ret[-col] = (T) 1; } } template void TableauInterface::GetBasis(Basis &out) const { out= basis; } template BFS TableauInterface::GetBFS() { Gambit::Vector sol(basis.First(),basis.Last()); BasisVector(sol); BFS cbfs((T) 0); for(int i=MinCol();i<=MaxCol();i++) if(Member(i)) cbfs.Define(i,sol[basis.Find(i)]); return cbfs; } template BFS TableauInterface::GetBFS1() const { Gambit::Vector sol(basis.First(),basis.Last()); BasisVector(sol); BFS cbfs((T) 0); int i; for(i=-MaxRow();i<=-MinRow();i++) if(Member(i)) cbfs.Define(i,sol[basis.Find(i)]); for(i=MinCol();i<=MaxCol();i++) if(Member(i)) cbfs.Define(i,sol[basis.Find(i)]); return cbfs; } // miscellaneous functions template bool TableauInterface::EqZero(T x) const { return (LeZero(x) && GeZero(x)); } template bool TableauInterface::LtZero(T x) const { return !GeZero(x); } template bool TableauInterface::GtZero(T x) const { return !LeZero(x); } template bool TableauInterface::LeZero(T x) const { if(x <=eps2) return 1; return 0; } template bool TableauInterface::GeZero(T x) const { if(x >= -eps2) return 1; return 0; } template T TableauInterface::Epsilon(int i) const { if(i!=1 && i!=2) { throw Gambit::IndexException(); } if(i==1) return eps1; return eps2; } template bool TableauInterface::IsArtifColumn(int col) const { return col>=artificial.First() && col<=artificial.Last(); } /* template BaseTableau::BadPivot::~BadPivot() { } template gText BaseTableau::BadPivot::Description(void) const { return "Bad Pivot in BaseTableau"; } */ gambit-0.2010.09.01/src/tools/lcp/efglcp.cc0000644000076500007650000003620311441453421014717 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/efglcp.cc // Implementation of algorithm to solve extensive forms using linear // complementarity program from sequence form // // 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 #include #include #include "libgambit/libgambit.h" using namespace Gambit; #include "lhtab.h" #include "lemketab.h" extern int g_numDecimals; extern int g_stopAfter; extern int g_maxDepth; extern bool g_printDetail; namespace { // // Pseudo-exception raised when maximum number of equilibria to compute // has been reached. A convenience for unraveling a potentially // deep recursion. // // FIXME: There is an identical twin of this in nfglcp.cc. This should be // refactored into a more generally-useful and generally-visible location. // class EquilibriumLimitReachedEfg : public Exception { public: virtual ~EquilibriumLimitReachedEfg() { } std::string GetDescription(void) const { return "Reached target number of equilibria"; } }; } // end anonymous namespace void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedBehavProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << "," << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedBehavProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream << "," << p_profile[i]; } p_stream << std::endl; } template void PrintProfileDetail(std::ostream &p_stream, const MixedBehavProfile &p_profile) { char buffer[256]; for (int pl = 1; pl <= p_profile.GetGame()->NumPlayers(); pl++) { GamePlayer player = p_profile.GetGame()->GetPlayer(pl); p_stream << "Behavior profile for player " << pl << ":\n"; p_stream << "Infoset Action Prob Value\n"; p_stream << "------- ------- ----------- -----------\n"; for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); for (int act = 1; act <= infoset->NumActions(); act++) { GameAction action = infoset->GetAction(act); if (infoset->GetLabel() != "") { sprintf(buffer, "%7s ", infoset->GetLabel().c_str()); } else { sprintf(buffer, "%7d ", iset); } p_stream << buffer; if (action->GetLabel() != "") { sprintf(buffer, "%7s ", action->GetLabel().c_str()); } else { sprintf(buffer, "%7d ", act); } p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile(pl, iset, act), g_numDecimals).c_str()); p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile.GetActionValue(infoset->GetAction(act)), g_numDecimals).c_str()); p_stream << buffer; p_stream << "\n"; } } p_stream << "\n"; p_stream << "Infoset Node Belief Prob\n"; p_stream << "------- ------- ----------- -----------\n"; for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); for (int n = 1; n <= infoset->NumMembers(); n++) { sprintf(buffer, "%7d ", iset); p_stream << buffer; sprintf(buffer, "%7d ", n); p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile.GetBeliefProb(infoset->GetMember(n)), g_numDecimals).c_str()); p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile.GetRealizProb(infoset->GetMember(n)), g_numDecimals).c_str()); p_stream << buffer; p_stream << "\n"; } } p_stream << "\n"; } } template class SolveEfgLcp { private: int ns1,ns2,ni1,ni2; T maxpay,eps; List > m_list; List isets1, isets2; void FillTableau(const BehavSupport &, Matrix &, const GameNode &, T, int, int, int, int); int AddBFS(const LTableau &tab); int AllLemke(const BehavSupport &, int dup, LTableau &B, int depth, Matrix &, bool p_print, List > &); void GetProfile(const BehavSupport &, const LTableau &tab, MixedBehavProfile &, const Vector &, const GameNode &n, int,int); public: SolveEfgLcp(void) { } List > Solve(const BehavSupport &, bool p_print = true); }; //--------------------------------------------------------------------------- // SolveEfgLcp: member functions //--------------------------------------------------------------------------- // // Sets the action probabilities at unreached information sets // which are left undefined by the sequence form method to // the centroid. This helps IsNash and LiapValue work correctly. // template void UndefinedToCentroid(MixedBehavProfile &p_profile) { Game efg = p_profile.GetGame(); for (int pl = 1; pl <= efg->NumPlayers(); pl++) { GamePlayer player = efg->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); if (p_profile.GetInfosetProb(infoset) > (T) 0) { continue; } T total = (T) 0; for (int act = 1; act <= infoset->NumActions(); act++) { total += p_profile.GetActionProb(infoset->GetAction(act)); } if (total == (T) 0) { for (int act = 1; act <= infoset->NumActions(); act++) { p_profile(pl, iset, act) = (T) 1.0 / (T) infoset->NumActions(); } } } } } // // Lemke implements the Lemke's algorithm (as refined by Eaves // for degenerate problems) for Linear Complementarity // problems, starting from the primary ray. // template List > SolveEfgLcp::Solve(const BehavSupport &p_support, bool p_print /*= true*/) { BFS cbfs((T) 0); int i, j; isets1 = p_support.ReachableInfosets(p_support.GetGame()->GetPlayer(1)); isets2 = p_support.ReachableInfosets(p_support.GetGame()->GetPlayer(2)); m_list = List >(); int ntot; ns1 = p_support.NumSequences(1); ns2 = p_support.NumSequences(2); ni1 = p_support.GetGame()->GetPlayer(1)->NumInfosets()+1; ni2 = p_support.GetGame()->GetPlayer(2)->NumInfosets()+1; ntot = ns1+ns2+ni1+ni2; Matrix A(1,ntot,0,ntot); Vector b(1,ntot); maxpay = p_support.GetGame()->GetMaxPayoff() + Rational(1); T prob = (T)1; for (i = A.MinRow(); i <= A.MaxRow(); i++) { b[i] = (T) 0; for (j = A.MinCol(); j <= A.MaxCol(); j++) { A(i,j) = (T) 0; } } FillTableau(p_support, A, p_support.GetGame()->GetRoot(), prob, 1, 1, 0, 0); for (i = A.MinRow(); i <= A.MaxRow(); i++) { A(i,0) = -(T) 1; } A(1,ns1+ns2+1) = (T)1; A(ns1+ns2+1,1) = -(T)1; A(ns1+1,ns1+ns2+ni1+1) = (T)1; A(ns1+ns2+ni1+1,ns1+1) = -(T)1; b[ns1+ns2+1] = -(T)1; b[ns1+ns2+ni1+1] = -(T)1; LTableau tab(A,b); eps = tab.Epsilon(); MixedBehavProfile profile(p_support); Vector sol(tab.MinRow(),tab.MaxRow()); List > solutions; try { if (g_stopAfter != 1) { try { AllLemke(p_support, ns1+ns2+1, tab, 0, A, p_print, solutions); } catch (EquilibriumLimitReachedEfg &) { // Just handle this silently; equilibria are already printed // as they are found. } } else { tab.Pivot(ns1+ns2+1,0); tab.SF_LCPPath(ns1+ns2+1); AddBFS(tab); tab.BasisVector(sol); GetProfile(p_support, tab, profile,sol,p_support.GetGame()->GetRoot(),1,1); UndefinedToCentroid(profile); PrintProfile(std::cout, "NE", profile); if (g_printDetail) { PrintProfileDetail(std::cout, profile); } } } catch (...) { // catch exception; return solutions computed (if any) } return solutions; } template int SolveEfgLcp::AddBFS(const LTableau &tableau) { BFS cbfs((T) 0); Vector v(tableau.MinRow(), tableau.MaxRow()); tableau.BasisVector(v); for (int i = tableau.MinCol(); i <= tableau.MaxCol(); i++) if (tableau.Member(i)) { cbfs.Define(i, v[tableau.Find(i)]); } if (m_list.Contains(cbfs)) return 0; m_list.Append(cbfs); return 1; } // // All_Lemke finds all accessible Nash equilibria by recursively // calling itself. List maintains the list of basic variables // for the equilibria that have already been found. // From each new accessible equilibrium, it follows // all possible paths, adding any new equilibria to the List. // template int SolveEfgLcp::AllLemke(const BehavSupport &p_support, int j, LTableau &B, int depth, Matrix &A, bool p_print, List > &p_solutions) { if (g_maxDepth != 0 && depth > g_maxDepth) { return 1; } int i,newsol,missing; T small_num = (T)1/(T)1000; Vector sol(B.MinRow(),B.MaxRow()); MixedBehavProfile profile(p_support); newsol =0; for (i = B.MinRow(); i <= B.MaxRow() && newsol == 0; i++) { if (i != j) { LTableau BCopy(B); A(i,0) = -small_num; BCopy.Refactor(); if (depth == 0) { BCopy.Pivot(j, 0); missing = -j; } else { missing = BCopy.SF_PivotIn(0); } newsol = 0; if (BCopy.SF_LCPPath(-missing) == 1) { newsol = AddBFS(BCopy); BCopy.BasisVector(sol); GetProfile(p_support, BCopy, profile, sol, p_support.GetGame()->GetRoot(), 1, 1); UndefinedToCentroid(profile); if (newsol) { if (p_print) { PrintProfile(std::cout, "NE", profile); if (g_printDetail) { PrintProfileDetail(std::cout, profile); } } p_solutions.Append(profile); if (g_stopAfter > 0 && p_solutions.Length() >= g_stopAfter) { throw EquilibriumLimitReachedEfg(); } } } else { // gout << ": Dead End"; } A(i,0) = (T) -1; if (newsol) { BCopy.Refactor(); AllLemke(p_support, i, BCopy, depth+1, A, p_print, p_solutions); } } } return 1; } template void SolveEfgLcp::FillTableau(const BehavSupport &p_support, Matrix &A, const GameNode &n, T prob, int s1, int s2, int i1, int i2) { int snew; GameOutcome outcome = n->GetOutcome(); if (outcome) { A(s1,ns1+s2) = Rational(A(s1,ns1+s2)) + Rational(prob) * (outcome->GetPayoff(1) - Rational(maxpay)); A(ns1+s2,s1) = Rational(A(ns1+s2,s1)) + Rational(prob) * (outcome->GetPayoff(2) - Rational(maxpay)); } if (n->GetInfoset()) { if (n->GetPlayer()->IsChance()) { GameInfoset infoset = n->GetInfoset(); for (int i = 1; i <= n->NumChildren(); i++) { FillTableau(p_support, A, n->GetChild(i), Rational(prob) * infoset->GetActionProb(i), s1,s2,i1,i2); } } int pl = n->GetPlayer()->GetNumber(); if (pl==1) { i1=isets1.Find(n->GetInfoset()); snew=1; for (int i = 1; i < i1; i++) { snew+=p_support.NumActions(isets1[i]->GetPlayer()->GetNumber(), isets1[i]->GetNumber()); } A(s1,ns1+ns2+i1+1) = -(T)1; A(ns1+ns2+i1+1,s1) = (T)1; for (int i = 1; i <= p_support.NumActions(n->GetInfoset()->GetPlayer()->GetNumber(), n->GetInfoset()->GetNumber()); i++) { A(snew+i,ns1+ns2+i1+1) = (T)1; A(ns1+ns2+i1+1,snew+i) = -(T)1; FillTableau(p_support, A, n->GetChild(p_support.GetAction(n->GetInfoset()->GetPlayer()->GetNumber(), n->GetInfoset()->GetNumber(), i)->GetNumber()),prob,snew+i,s2,i1,i2); } } if(pl==2) { i2=isets2.Find(n->GetInfoset()); snew=1; for (int i = 1; i < i2; i++) { snew+=p_support.NumActions(isets2[i]->GetPlayer()->GetNumber(), isets2[i]->GetNumber()); } A(ns1+s2,ns1+ns2+ni1+i2+1) = -(T)1; A(ns1+ns2+ni1+i2+1,ns1+s2) = (T)1; for (int i = 1; i <= p_support.NumActions(n->GetInfoset()->GetPlayer()->GetNumber(), n->GetInfoset()->GetNumber()); i++) { A(ns1+snew+i,ns1+ns2+ni1+i2+1) = (T)1; A(ns1+ns2+ni1+i2+1,ns1+snew+i) = -(T)1; FillTableau(p_support, A, n->GetChild(p_support.GetAction(n->GetInfoset()->GetPlayer()->GetNumber(), n->GetInfoset()->GetNumber(), i)->GetNumber()),prob,s1,snew+i,i1,i2); } } } } template void SolveEfgLcp::GetProfile(const BehavSupport &p_support, const LTableau &tab, MixedBehavProfile &v, const Vector &sol, const GameNode &n, int s1,int s2) { if (n->GetInfoset()) { int pl = n->GetPlayer()->GetNumber(); int iset = n->GetInfoset()->GetNumber(); if (n->GetPlayer()->IsChance()) { for (int i = 1; i <= n->NumChildren(); i++) { GetProfile(p_support, tab, v, sol, n->GetChild(i), s1, s2); } } else if (pl == 1) { int inf = isets1.Find(n->GetInfoset()); int snew = 1; for (int i = 1; i < inf; i++) { snew += p_support.NumActions(1, isets1[i]->GetNumber()); } for (int i = 1; i <= p_support.NumActions(pl, iset); i++) { v(pl,inf,i) = (T) 0; if (tab.Member(s1)) { int ind = tab.Find(s1); if (sol[ind] > eps) { if (tab.Member(snew+i)) { int ind2 = tab.Find(snew+i); if (sol[ind2] > eps) { v(pl,inf,i) = sol[ind2] / sol[ind]; } } } } GetProfile(p_support, tab, v, sol, n->GetChild(p_support.GetAction(pl, iset, i)->GetNumber()), snew+i, s2); } } else if (pl == 2) { int inf = isets2.Find(n->GetInfoset()); int snew = 1; for (int i = 1; i < inf; i++) { snew += p_support.NumActions(2, isets2[i]->GetNumber()); } for (int i = 1; i<= p_support.NumActions(pl, iset); i++) { v(pl,inf,i) = (T) 0; if (tab.Member(ns1+s2)) { int ind = tab.Find(ns1+s2); if (sol[ind] > eps) { if (tab.Member(ns1+snew+i)) { int ind2 = tab.Find(ns1+snew+i); if (sol[ind2] > eps) { v(pl,inf,i) = sol[ind2] / sol[ind]; } } } } GetProfile(p_support, tab, v, sol, n->GetChild(p_support.GetAction(pl, iset, i)->GetNumber()), s1, snew+i); } } } } template List > SolveExtensive(const BehavSupport &p_support) { SolveEfgLcp algorithm; return algorithm.Solve(p_support); } template List > SolveExtensive(const BehavSupport &); template List > SolveExtensive(const BehavSupport &); template List > SolveExtensiveSilent(const BehavSupport &p_support) { SolveEfgLcp algorithm; return algorithm.Solve(p_support, false); } template List > SolveExtensiveSilent(const BehavSupport &); template List > SolveExtensiveSilent(const BehavSupport &); gambit-0.2010.09.01/src/tools/lcp/lcp.cc0000644000076500007650000001232311435216102014226 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/lcp.cc // Compute Nash equilibria via linear complementarity program // // 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 #include #include #include "libgambit/libgambit.h" #include "libgambit/subgame.h" using namespace Gambit; template List > SolveExtensive(const BehavSupport &p); template List > SolveExtensiveSilent(const BehavSupport &p); template void SolveStrategic(const Game &p_game); void PrintBanner(std::ostream &p_stream) { p_stream << "Compute Nash equilibria by solving a linear complementarity program\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "With no options, reports all Nash equilibria found.\n\n"; std::cerr << "Options:\n"; std::cerr << " -d DECIMALS compute using floating-point arithmetic;\n"; std::cerr << " display results with DECIMALS digits\n"; std::cerr << " -S use strategic game\n"; std::cerr << " -P find only subgame-perfect equilibria\n"; std::cerr << " -e EQA terminate after finding EQA equilibria\n"; std::cerr << " (default is to find all accessible equilbria\n"; std::cerr << " -r DEPTH terminate recursion at DEPTH\n"; std::cerr << " (only if number of equilibria sought is not 1)\n"; std::cerr << " -D print detailed information about equilibria\n"; std::cerr << " -h print this help message\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; exit(1); } int g_numDecimals = 6; bool g_printDetail = false; int g_stopAfter = 0; int g_maxDepth = 0; extern void PrintProfile(std::ostream &, const std::string &, const MixedBehavProfile &); extern void PrintProfile(std::ostream &, const std::string &, const MixedBehavProfile &); int main(int argc, char *argv[]) { int c; bool useFloat = false, useStrategic = false, bySubgames = false, quiet = false; while ((c = getopt(argc, argv, "d:DhqSPe:r:")) != -1) { switch (c) { case 'd': useFloat = true; g_numDecimals = atoi(optarg); break; case 'D': g_printDetail = true; break; case 'e': g_stopAfter = atoi(optarg); break; case 'h': PrintHelp(argv[0]); break; case 'q': quiet = true; break; case 'r': g_maxDepth = atoi(optarg); break; case 'S': useStrategic = true; break; case 'P': bySubgames = true; break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Game game = ReadGame(std::cin); if (game->NumPlayers() != 2) { std::cerr << "Error: Game does not have two players.\n"; return 1; } if (!game->IsTree() || useStrategic) { game->BuildComputedValues(); if (useFloat) { SolveStrategic(game); } else { SolveStrategic(game); } } else { if (!bySubgames) { if (useFloat) { SolveExtensive(game); } else { SolveExtensive(game); } } else { if (useFloat) { List > solutions; solutions = SolveBySubgames(BehavSupport(game), &SolveExtensiveSilent); for (int i = 1; i <= solutions.Length(); i++) { PrintProfile(std::cout, "NE", solutions[i]); } } else { List > solutions; solutions = SolveBySubgames(BehavSupport(game), &SolveExtensiveSilent); for (int i = 1; i <= solutions.Length(); i++) { PrintProfile(std::cout, "NE", solutions[i]); } } } } return 0; } catch (InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } } gambit-0.2010.09.01/src/tools/lcp/lemketab.cc0000644000076500007650000000175511435216102015243 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/lemketab.cc // Lemke tableau instantiations // // 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 "lemketab.imp" template class LTableau; template class LTableau; gambit-0.2010.09.01/src/tools/lcp/lemketab.h0000644000076500007650000000334211435216102015077 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/lemketab.h // Declaration of Lemke tableau class // // 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 LEMKETAB_H #define LEMKETAB_H #include "tableau.h" template class LTableau : public Tableau { protected: // T eps2; public: // LTableau(void); class BadPivot : public Gambit::Exception { public: virtual ~BadPivot(); std::string GetDescription(void) const; }; class BadExitIndex : public Gambit::Exception { public: virtual ~BadExitIndex(); std::string GetDescription(void) const; }; LTableau(const Gambit::Matrix &A, const Gambit::Vector &b); LTableau(Tableau &); virtual ~LTableau(); int SF_PivotIn(int i); int SF_ExitIndex(int i); int SF_LCPPath(int dup); // follow a path of ACBFS's from one CBFS to another int PivotIn(int i); int ExitIndex(int i); int LemkePath(int dup); // follow a path of ACBFS's from one CBFS to another }; #endif // LEMKETAB_H gambit-0.2010.09.01/src/tools/lcp/lemketab.imp0000644000076500007650000002101211435216102015427 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/lemketab.imp // Implementation of Lemke tableau class // // 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 "lemketab.h" //--------------------------------------------------------------------------- // Lemke Tableau: member functions //--------------------------------------------------------------------------- template LTableau::LTableau(const Gambit::Matrix &A, const Gambit::Vector &b) : Tableau(A,b) { } template LTableau::LTableau(Tableau &tab) : Tableau(tab) { } template LTableau::~LTableau(void) { } template int LTableau::SF_PivotIn(int inlabel) { //* gout << "\n inlabel = " << inlabel; int outindex = SF_ExitIndex(inlabel); // gout << " outindex = " << outindex; if(outindex==0) { //* gout << "\nPivotIn: outindex=0, inlabel=" << inlabel; return inlabel; } int outlabel = this->Label(outindex); //* gout << " outlabel = " << outlabel; //* gout << " outindex = " << outindex; this->Pivot(outindex,inlabel); return outlabel; } template int LTableau::PivotIn(int inlabel) { // gout << "\n inlabel = " << inlabel; int outindex = ExitIndex(inlabel); // gout << " outindex = " << outindex; if(outindex==0) return inlabel; int outlabel = this->Label(outindex); if(outlabel==0) throw BadPivot(); // gout << " outlabel = " << outlabel; // gout << " outindex = " << outindex; this->Pivot(outindex,inlabel); return outlabel; } template int LTableau::SF_ExitIndex(int inlabel) { Gambit::Array BestSet; int i, c; T ratio, tempmax; Gambit::Vector incol(this->MinRow(), this->MaxRow()); Gambit::Vector col(this->MinRow(), this->MaxRow()); SolveColumn(inlabel,incol); //* gout << "\nincol = " << incol; // Find all row indices for which column col has positive entries. for (i = this->MinRow(); i <= this->MaxRow(); i++) if (incol[i] > this->eps2) BestSet.Append(i); if(BestSet.Length()==0) { //* gout << "\nBestSet.Length() == 0, Find(0): " << Find(0); return 0; } // Is this really needed? /* if(BestSet.Length()==0 && incol[Find(0)]<=eps2 && incol[Find(0)] >= (-eps2) ) return Find(0); */ if(BestSet.Length() <= 0) throw BadExitIndex(); // If there are multiple candidates, break ties by // looking at ratios with other columns, // eliminating nonmaximizers of // a similar ratio, until only one candidate remains. c = this->MinRow()-1; BasisVector(col); // gout << "\nLength = " << BestSet.Length(); //* gout << "\n x = " << col << "\n"; while (BestSet.Length() > 1) { if(c > this->MaxRow()) throw BadExitIndex(); if(c>=this->MinRow()) { SolveColumn(-c,col); // gout << "\n-c = " << -c << " col = " << col; } // Initialize tempmax. tempmax = col[BestSet[1]] / incol[BestSet[1]]; // Find the maximum ratio. for (i = 2; i <= BestSet.Length(); i++) { ratio = col[BestSet[i]] / incol[BestSet[i]]; //* if (ratio > tempmax) tempmax = ratio; if (ratio < tempmax) tempmax = ratio; } // if (tempmax <= (T 2)*eps1) throw BadExitIndex(); // Remove nonmaximizers from the list of candidate columns. for (i = BestSet.Length(); i >= 1; i--) { ratio = col[BestSet[i]] / incol[BestSet[i]]; //* if (ratio < tempmax -eps1) if (ratio > tempmax +this->eps2) BestSet.Remove(i); } // else { // if(!Member(FindColumn(c))) throw BadExitIndex(); // if (BestSet.Contains(c_row)) return c_row; // } c++; } if(BestSet.Length() <= 0) throw BadExitIndex(); return BestSet[1]; } // // ExitIndex determines, for the current tableau and variable to // to be added to the basis, which element should leave the basis. // The choice is the one specified by Eaves, which is guaranteed // to not cycle, even if the problem is degenerate. // template int LTableau::ExitIndex(int inlabel) { Gambit::Array BestSet; int i, c; T ratio, tempmax; Gambit::Vector incol(this->MinRow(), this->MaxRow()); Gambit::Vector col(this->MinRow(), this->MaxRow()); SolveColumn(inlabel,incol); // gout << "\nincol = " << incol; // Find all row indices for which column col has positive entries. for (i = this->MinRow(); i <= this->MaxRow(); i++) if (incol[i] > this->eps2) BestSet.Append(i); // Is this really needed? if(BestSet.Length()==0) // gout << "\nBestSet.Length() == 0, Find(0):\n" << Find(0); if(BestSet.Length()==0 && incol[this->Find(0)]<=this->eps2 && incol[this->Find(0)] >= (-this->eps2) ) return this->Find(0); if(BestSet.Length() <= 0) throw BadExitIndex(); // If there are multiple candidates, break ties by // looking at ratios with other columns, // eliminating nonmaximizers of // a similar ratio, until only one candidate remains. c = this->MinRow()-1; BasisVector(col); // gout << "\nLength = " << BestSet.Length(); // gout << "\n x = " << col << "\n"; while (BestSet.Length() > 1) { // this is where ITEM 001 is failing if(c > this->MaxRow()) throw BadExitIndex(); if(c>=this->MinRow()) { SolveColumn(-c,col); // gout << "\n-c = " << -c << " col = " << col; } // Initialize tempmax. tempmax = col[BestSet[1]] / incol[BestSet[1]]; // Find the maximum ratio. for (i = 2; i <= BestSet.Length(); i++) { ratio = col[BestSet[i]] / incol[BestSet[i]]; if (ratio > tempmax) tempmax = ratio; } // if(tempmax <= (T 2)*eps1) throw BadExitIndex(); // Remove nonmaximizers from the list of candidate columns. for (i = BestSet.Length(); i >= 1; i--) { ratio = col[BestSet[i]] / incol[BestSet[i]]; if (ratio < tempmax -this->eps1) BestSet.Remove(i); } // else { // if(!Member(FindColumn(c))) throw BadExitIndex(); // if (BestSet.Contains(c_row)) return c_row; // } c++; } if(BestSet.Length() <= 0) throw BadExitIndex(); return BestSet[1]; } // // Executes one step of the Lemke-Howson algorithm // template int LTableau::SF_LCPPath(int dup) { int enter, exit; enter = dup; /* if(dup) Pivot(dup,0); else { enter = -SF_PivotIn(dup); if(enter==0) throw BadPivot(); } */ // Central loop - pivot until another CBFS is found long nits = 0; do { // Talk about optimism! This is dumb, but better than nothing (I guess): nits++; //* gout << "\nBasis:\n"; //* Dump(gout); exit = SF_PivotIn(enter); if(exit==enter) { //* gout << "\nenter, exit: " << enter << " " << exit; return 0; } enter = -exit; } while (exit != 0); return 1; } template int LTableau::LemkePath(int dup) { // if (!At_CBFS()) return 0; int enter, exit; // if(params.plev >=2) { // (*params.output) << "\nbegin path " << dup << "\n"; // Dump(*params.output); // } // gout << "\nbegin path " << dup << "\n"; // Dump(gout); enter = dup; if (this->Member(dup)) enter = -dup; // Central loop - pivot until another CBFS is found do { exit = PivotIn(enter); // if(params.plev >=2) // Dump(*params.output); // Dump(gout); enter = -exit; } while ((exit != dup) && (exit != -dup)); // Quit when at a CBFS. // if(params.plev >=2 ) (*params.output) << "\nend of path " << dup; // gout << "\nend of path " << dup; return 1; } template LTableau::BadPivot::~BadPivot() { } template std::string LTableau::BadPivot::GetDescription(void) const { return "Bad Pivot in LTableau"; } template LTableau::BadExitIndex::~BadExitIndex() { } template std::string LTableau::BadExitIndex::GetDescription(void) const { return "Bad Exit Index in LTableau"; } gambit-0.2010.09.01/src/tools/lcp/lhtab.cc0000644000076500007650000000302411435216102014540 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/lhtab.cc // Tableau class for Lemke-Howson algorithm // // 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 "lhtab.imp" template class LHTableau; template class LHTableau; template Matrix Make_A1(const StrategySupport &); template Matrix Make_A1(const StrategySupport &); template Vector Make_b1(const StrategySupport &); template Vector Make_b1(const StrategySupport &); template Matrix Make_A2(const StrategySupport &); template Matrix Make_A2(const StrategySupport &); template Vector Make_b2(const StrategySupport &); template Vector Make_b2(const StrategySupport &); gambit-0.2010.09.01/src/tools/lcp/lhtab.h0000644000076500007650000000432111435216102014403 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/lhtab.h // Tableau class for Lemke-Howson algorithm // // 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 LHTAB_H #define LHTAB_H // includes #include "lemketab.h" class Nfg; template class LHTableau : public BaseTableau{ protected: LTableau T1,T2; Gambit::Vector tmp1,tmp2; // temporary column vectors, to avoid allocation Gambit::Vector solution; public: // constructors and destructors LHTableau(const Gambit::Matrix &A1, const Gambit::Matrix &A2, const Gambit::Vector &b1, const Gambit::Vector &b2); LHTableau(const LHTableau&); virtual ~LHTableau(); LHTableau& operator=(const LHTableau&); // information int MinRow() const; int MaxRow() const; int MinCol() const; int MaxCol() const; T Epsilon() const; bool Member(int i) const; int Label(int i) const; // return variable in i'th position of Tableau int Find(int i) const; // return Tableau position of variable i // pivoting int CanPivot(int outgoing,int incoming); void Pivot(int outrow,int inlabel); // perform pivot operation -- outgoing is row, incoming is column long NumPivots() const; // raw Tableau functions void Refactor(); // miscellaneous functions BFS GetBFS(void); int PivotIn(int i); int ExitIndex(int i); int LemkePath(int dup); // follow a path of ACBFS's from one CBFS to another }; #endif // LHTAB_H gambit-0.2010.09.01/src/tools/lcp/lhtab.imp0000644000076500007650000001647411435216102014755 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/lhtab.imp // Tableau class for Lemke-Howson algorithm // // 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 "lhtab.h" #include "libgambit/libgambit.h" using namespace Gambit; //--------------------------------------------------------------------------- // LemkeHowson Tableau: member functions //--------------------------------------------------------------------------- template Matrix Make_A1(const StrategySupport &S) { int n1, n2, i,j; n1=S.NumStrategies(1); n2=S.NumStrategies(2); Matrix A1(1,n1,n1+1,n1+n2); PureStrategyProfile profile(S.GetGame()); Rational min = S.GetGame()->GetMinPayoff(); if (min > Rational(0)) { min = Rational(0); } min -= Rational(1); Rational max = S.GetGame()->GetMaxPayoff(); if (max < Rational(0)) { max = Rational(0); } Rational fac(1, max - min); for (i = 1; i <= n1; i++) { profile.SetStrategy(S.GetStrategy(1, i)); for (j = 1; j <= n2; j++) { profile.SetStrategy(S.GetStrategy(2, j)); A1(i, n1 + j) = fac * (profile.GetPayoff(1) - min); } } return A1; } template Matrix Make_A2(const StrategySupport &S) { int n1, n2, i,j; n1=S.NumStrategies(1); n2=S.NumStrategies(2); Matrix A2(n1+1,n1+n2,1,n1); PureStrategyProfile profile(S.GetGame()); Rational min = S.GetGame()->GetMinPayoff(); if (min > Rational(0)) { min = Rational(0); } min -= Rational(1); Rational max = S.GetGame()->GetMaxPayoff(); if (max < Rational(0)) { max = Rational(0); } Rational fac(1, max - min); for (i = 1; i <= n1; i++) { profile.SetStrategy(S.GetStrategy(1, i)); for (j = 1; j <= n2; j++) { profile.SetStrategy(S.GetStrategy(2, j)); A2(n1 + j, i) = fac * (profile.GetPayoff(2) - min); } } return A2; } template Vector Make_b1(const StrategySupport &S) { int n1 = S.NumStrategies(1); Vector b1(1,n1); for (int i = 1; i <= n1; i++) b1[i]=-(T)1; return b1; } template Vector Make_b2(const StrategySupport &S) { int n1, n2, i; n1=S.NumStrategies(1); n2=S.NumStrategies(2); Vector b2(n1+1,n1+n2); for (i = n1+1; i <= n1+n2; i++) b2[i]=-(T)1; return b2; } template LHTableau::LHTableau(const Matrix &A1, const Matrix &A2, const Vector &b1, const Vector &b2) : T1(A1,b1), T2(A2,b2), // tmpcol(b1.First(),b2.Last()), tmp1(b1.First(),b1.Last()),tmp2(b2.First(),b2.Last()), solution(b1.First(), b2.Last()) { } template LHTableau ::LHTableau(const LHTableau &orig) : T1(orig.T1), T2(orig.T2), // tmpcol(orig.tmpcol), tmp1(orig.tmp1), tmp2(orig.tmp2), solution(orig.solution) { } template LHTableau::~LHTableau(void) { } template LHTableau& LHTableau::operator=(const LHTableau &orig) { if(this!= &orig) { T1 = orig.T1; T2 = orig.T2; // tmpcol = orig.tmpcol; tmp1 = orig.tmp1; tmp2 = orig.tmp2; solution = orig.solution; } return *this; } template int LHTableau::MinRow() const { return T1.MinRow(); } template int LHTableau::MaxRow() const { return T2.MaxRow(); } template int LHTableau::MinCol() const { return T2.MinCol(); } template int LHTableau::MaxCol() const { return T1.MaxCol(); } template T LHTableau::Epsilon() const { return T1.Epsilon(); } template bool LHTableau::Member(int i) const {return (T1.Member(i) || T2.Member(i));} template int LHTableau::Label(int i) const { if(T1.RowIndex(i)) return T1.Label(i); if(T2.RowIndex(i)) return T2.Label(i); return 0; } template int LHTableau::Find(int i) const { if(T1.ValidIndex(i)) return T1.Find(i); if(T2.ValidIndex(i)) return T2.Find(i); return 0; } // // pivoting operations // template int LHTableau::CanPivot(int outlabel, int inlabel) { if(T1.ValidIndex(outlabel)) { if(T1.CanPivot(outlabel,inlabel)) return 1;} else if(T2.ValidIndex(outlabel)) { if(T2.CanPivot(outlabel,inlabel)) return 1;} return 0; } template void LHTableau::Pivot(int outrow,int inlabel) { if (!this->RowIndex(outrow)) { throw typename LTableau::BadPivot(); } if(T1.RowIndex(outrow)) T1.Pivot(outrow,inlabel); if(T2.RowIndex(outrow)) T2.Pivot(outrow,inlabel); } template long LHTableau::NumPivots() const { return T1.NumPivots() + T2.NumPivots(); } // // raw Tableau functions // template void LHTableau::Refactor() { T1.Refactor(); T2.Refactor(); } // miscellaneous functions template BFS LHTableau::GetBFS() { int i; T1.BasisVector(tmp1); T2.BasisVector(tmp2); for(i=tmp1.First();i<=tmp1.Last();i++) solution[i] = tmp1[i]; for(i=tmp2.First();i<=tmp2.Last();i++) solution[i] = tmp2[i]; BFS cbfs((T) 0); for(i=MinCol();i<=MaxCol();i++) { if(Member(i)) cbfs.Define(i,solution[Find(i)]); } return cbfs; } template int LHTableau::PivotIn(int inlabel) { // gout << "\n inlabel = " << inlabel; int outindex = ExitIndex(inlabel); int outlabel = Label(outindex); if(outlabel==0)return 0; // gout << "\n outlabel = " << outlabel; // gout << " outindex = " << outindex << "\n\n"; Pivot(outindex,inlabel); return outlabel; } // // ExitIndex determines, for the current tableau and variable to // to be added to the basis, which element should leave the basis. // The choice is the one specified by Eaves, which is guaranteed // to not cycle, even if the problem is degenerate. // template int LHTableau::ExitIndex(int inlabel) { if(T1.ValidIndex(inlabel)) return T1.ExitIndex(inlabel); if(T2.ValidIndex(inlabel)) return T2.ExitIndex(inlabel); return 0; } // // Executes one step of the Lemke-Howson algorithm // template int LHTableau::LemkePath(int dup) { // if (!At_CBFS()) return 0; int enter, exit; // if(params.plev >=2) { // (*params.output) << "\nbegin path " << dup << "\n"; // Dump(*params.output); // } // (gout) << "\nbegin path " << dup << "\n"; // Dump(gout); enter = dup; if (Member(dup)) { // gout << "\ndup is member"; enter = -dup; } // Central loop - pivot until another CBFS is found do { exit = PivotIn(enter); // if(params.plev >=2) // Dump(*params.output); // Dump(gout); enter = -exit; } while ((exit != dup) && (exit != -dup)); // Quit when at a CBFS. // if(params.plev >=2 ) (*params.output) << "\nend of path " << dup; // gout << "\nend of path " << dup; return 1; } gambit-0.2010.09.01/src/tools/lcp/ludecomp.cc0000644000076500007650000000211111435216102015252 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/ludecomp.cc // Instantiation of LU decomposition // // 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 "ludecomp.imp" template class EtaMatrix< double >; template class LUdecomp< double >; template class EtaMatrix< Gambit::Rational >; template class LUdecomp< Gambit::Rational >; gambit-0.2010.09.01/src/tools/lcp/ludecomp.h0000644000076500007650000001120111435216102015114 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/ludecomp.h // Interface to LU decomposition classes // // 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 LUDECOMP_H #define LUDECOMP_H #include "libgambit/libgambit.h" #include "basis.h" template class Tableau; // --------------------------------------------------------------------------- // Class EtaMatrix // --------------------------------------------------------------------------- template class EtaMatrix { public: int col; Gambit::Vector etadata; EtaMatrix(int c, Gambit::Vector &v) : col(c), etadata(v) {}; // required for list class bool operator==(const EtaMatrix &) const; bool operator!=(const EtaMatrix &) const; }; // --------------------------------------------------------------------------- // Class LUdecomp // --------------------------------------------------------------------------- template class LUdecomp { private: Tableau &tab; Basis &basis; Gambit::List< EtaMatrix > L; Gambit::List< EtaMatrix > U; Gambit::List< EtaMatrix > E; Gambit::List< int > P; Gambit::Vector scratch1; // scratch vectors so we don't reallocate them Gambit::Vector scratch2; // everytime we do something. int refactor_number; int iterations; int total_operations; const LUdecomp *parent; int copycount; // don't use this copy constructor LUdecomp( const LUdecomp &a); // don't use the equals operator, use the Copy function instead LUdecomp& operator=(const LUdecomp&); public: class BadPivot : public Gambit::Exception { public: virtual ~BadPivot(); std::string GetDescription(void) const; }; class BadCount : public Gambit::Exception { public: virtual ~BadCount(); std::string GetDescription(void) const; }; // ------------------------ // Constructors, Destructor // ------------------------ // copy constructor // note: Copying will fail an assertion if you try to update or delete // the original before the copy has been deleted, refactored // Or set to something else. LUdecomp( const LUdecomp &, Tableau & ); // Decompose given matrix LUdecomp( Tableau &, int rfac = 0 ); // Destructor ~LUdecomp(); // -------------------- // Public Members // -------------------- // copies the LUdecomp given (expect for the basis &). void Copy( const LUdecomp &, Tableau & ); // replace (update) the column given with the vector given. void update( int, int matcol ); // matcol is the column number in the matrix // refactor void refactor(); // solve: Bk d = a void solve (const Gambit::Vector &, Gambit::Vector & ) const; // solve: y Bk = c void solveT( const Gambit::Vector &, Gambit::Vector & ) const; // set number of etamatrices added before refactoring; // if number is set to zero, refactoring is done automatically. // if number is < 0, no refactoring is done; void SetRefactor( int ); //------------------- // Private Members //------------------- private: void FactorBasis(); void GaussElem( Gambit::Matrix &, int, int ); bool CheckBasis(); bool RefactorCheck(); void BTransE( Gambit::Vector & ) const; void FTransE( Gambit::Vector & ) const; void BTransU( Gambit::Vector & ) const; void FTransU( Gambit::Vector & ) const; void LPd_Trans( Gambit::Vector & ) const; void yLP_Trans( Gambit::Vector & ) const; void VectorEtaSolve( const Gambit::Vector &v, const EtaMatrix &, Gambit::Vector &y ) const; void EtaVectorSolve( const Gambit::Vector &v, const EtaMatrix &, Gambit::Vector &d ) const; void yLP_mult( const Gambit::Vector &y, int j, Gambit::Vector &) const; void LPd_mult( Gambit::Vector &d, int j, Gambit::Vector &) const; }; // end of class LUdecomp #endif // LUDECOMP_H gambit-0.2010.09.01/src/tools/lcp/ludecomp.imp0000644000076500007650000002564011435216102015466 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/ludecomp.imp // Implementation of LU decomposition // // 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 "ludecomp.h" #include "tableau.h" // --------------------------------------------------------------------------- // Class EtaMatrix // --------------------------------------------------------------------------- template bool EtaMatrix::operator==(const EtaMatrix &a) const { return ( col == a.col && etadata == a.etadata ); } template bool EtaMatrix::operator!=(const EtaMatrix &a) const { return ( col != a.col || etadata != a.etadata ); } // --------------------------------------------------------------------------- // Class LUdecomp // --------------------------------------------------------------------------- // ------------------------- // C-tors, D-tor, Operators // ------------------------- // copy constructor template LUdecomp::LUdecomp( const LUdecomp &a, Tableau &t) : tab(t), basis(t.GetBasis()), scratch1(basis.First(), basis.Last()), scratch2(basis.First(), basis.Last()), refactor_number( a.refactor_number ), iterations(a.iterations), total_operations( a.total_operations), parent(&a), copycount(0) { ((LUdecomp &)*parent).copycount++; } // Decomposes given matrix template LUdecomp::LUdecomp( Tableau &t, int rfac/* = 0 */) : tab(t), basis(t.GetBasis()), scratch1(basis.First(), basis.Last()), scratch2(basis.First(), basis.Last()), refactor_number(rfac), iterations(0), parent(NULL), copycount(0) { int m = basis.Last() - basis.First() +1; total_operations = (m - 1) * m * (2 * m - 1) / 6; } // Destructor template LUdecomp::~LUdecomp() { if ( parent != NULL ) ((LUdecomp &) *parent).copycount--; if(copycount != 0) throw BadCount(); } // ------------------------- // Public Members // ------------------------- // use this to copy ludecomps.... template void LUdecomp::Copy(const LUdecomp &orig, Tableau &t) { if(this != &orig) { if (parent != NULL) ((LUdecomp &) *parent).copycount--; tab = t; basis = t.GetBasis(); L = Gambit::List >(); P = Gambit::List(); E = Gambit::List >(); U = Gambit::List >(); refactor_number = orig.refactor_number; iterations = orig.iterations; total_operations = orig.total_operations; parent = &orig; copycount = 0; ((LUdecomp &)*parent).copycount++; } } template void LUdecomp::update( int col, int matcol ) { if( copycount != 0 ) throw BadCount(); int m = basis.Last() - basis.First() + 1; iterations++; if (( refactor_number > 0 && iterations >= refactor_number ) || ( refactor_number == 0 && RefactorCheck()) ) refactor(); else { tab.GetColumn( matcol, scratch1); solve( scratch1, scratch1 ); if ( scratch1[col] == (T) 0 ) throw BadPivot(); E.Append( EtaMatrix( col, scratch1 ) ); total_operations += iterations * m + 2 * m * m; } } template void LUdecomp::refactor( ) { L = Gambit::List >(); U = Gambit::List >(); E = Gambit::List >(); P = Gambit::List(); if ( !basis.IsIdent() ) FactorBasis(); iterations = 0; int m = basis.Last() - basis.First() + 1; total_operations = (m - 1) * m * (2 * m - 1) / 6; if (parent != NULL) ((LUdecomp &)*parent).copycount--; parent = NULL; } template void LUdecomp::solveT( const Gambit::Vector &c, Gambit::Vector &y ) const { if ( c.First() != y.First() || c.Last() != y.Last() ) throw Gambit::DimensionException(); if ( c.First() != basis.First() || c.Last() != basis.Last()) throw Gambit::DimensionException(); y = c; if ( basis.IsIdent() != true ) { BTransE( y ); if ( parent != NULL ) (*parent).solveT( y, y ); else { FTransU( y ); yLP_Trans( y ); } } } template void LUdecomp::solve( const Gambit::Vector &a, Gambit::Vector &d ) const { if ( a.First() != d.First() || a.Last() != d.Last() ) throw Gambit::DimensionException(); if ( a.First() != basis.First() || a.Last() != basis.Last()) throw Gambit::DimensionException(); d = a; if ( basis.IsIdent() != true ) { if ( parent != NULL ) (*parent).solve(a,d); else { LPd_Trans( d ); BTransU( d ); } FTransE( d ); } } template void LUdecomp::SetRefactor( int a ) { refactor_number = a; } // ----------------- // Private Members // ----------------- template void LUdecomp::FactorBasis() { int i, j, piv; T pivVal; Gambit::Matrix B(basis.First(), basis.Last(), basis.First(), basis.Last()); for( i = basis.First(); i <= basis.Last(); i++ ) { tab.GetColumn( basis.Label(i), scratch2 ); basis.CheckBasis(); B.SetColumn( i, scratch2 ); } for ( i = B.MinRow(); i <= B.MaxRow(); i++) { pivVal = Gambit::abs ( B(i, i)); piv = i; for ( j = i+1; j <= B.MaxRow(); j++) { if ( B( j, i ) * B( j, i ) > pivVal * pivVal ) { piv = j; pivVal = B( j, i ); } } P.Append(piv); B.SwitchRows(i,piv); scratch2 = (T) 0; scratch2[i] = (T) 1 / B( i, i ); for ( j = i+1; j <= B.MaxRow(); j++ ) { scratch2[j] = - B(j, i) / B(i,i); } L.Append( EtaMatrix(i, scratch2) ); GaussElem(B, i, i); } for ( j = B.MinCol(); j <= B.MaxCol(); j++ ) { B.GetColumn( j, scratch2 ); U.Append( EtaMatrix( j, scratch2 )); } } template void LUdecomp::GaussElem(Gambit::Matrix &B, int row, int col) { if( B(row, col) == (T) 0) throw BadPivot(); int i,j; for ( j = col+1; j <= B.MaxCol(); j++) B( row, j ) = B( row, j ) / B( row, col ); for ( i = row+1; i <= B.MaxRow(); i++ ) for ( j = col+1; j <= B.MaxCol(); j++ ) { B( i, j ) = B( i, j ) - ( B( i, col ) * B( row, j ) ); } for ( i = row+1; i <= B.MaxRow(); i++ ) B( i , col ) = 0; B( row, col ) = (T) 1; } template void LUdecomp::BTransE( Gambit::Vector &y ) const { int i; for ( i = E.Length(); i >= 1; i-- ) { ((LUdecomp &) *this).scratch2 = y; VectorEtaSolve(scratch2, E[i], y ); } } template void LUdecomp::FTransU( Gambit::Vector &y ) const { int i; for ( i = 1; i <= U.Length(); i++ ) { ((LUdecomp &) *this).scratch2 = y; VectorEtaSolve(scratch2, U[i], y ); } } template void LUdecomp::VectorEtaSolve( const Gambit::Vector &v, const EtaMatrix &eta, Gambit::Vector &y ) const { int i, j; if ( v.First() != y.First() || v.Last() != y.Last() ) throw Gambit::DimensionException(); for ( i = v.First(); i <= v.Last(); i++ ) { y[i] = v[i]; if ( i == eta.col ) { for ( j = v.First(); j <= v.Last(); j++ ) if ( j != eta.col ) y[i] -= v[j] * eta.etadata[j]; y[i] /= eta.etadata[i]; } } } template void LUdecomp::FTransE( Gambit::Vector &y ) const { int i; for ( i = 1; i <= E.Length(); i++ ) { ((LUdecomp &) *this).scratch2 = y; EtaVectorSolve(scratch2, E[i], y ); } } template void LUdecomp::BTransU( Gambit::Vector &y ) const { int i; for ( i = U.Length(); i >= 1; i-- ) { ((LUdecomp &) *this).scratch2 = y; EtaVectorSolve(scratch2, U[i], y ); } } template void LUdecomp::EtaVectorSolve( const Gambit::Vector &v, const EtaMatrix &eta, Gambit::Vector &d ) const { int i; T temp; if ( v.First() != d.First() || v.Last() != d.Last() ) throw Gambit::DimensionException(); if ( eta.etadata[eta.col] == (T)0 ) throw BadPivot(); // or we would have a singular matrix temp = v[eta.col] / eta.etadata[eta.col]; for ( i = v.First(); i <= v.Last(); i++) { if ( i == eta.col ) d[i] = temp; else { d[i] = v[i] - temp * eta.etadata[i]; } } } template void LUdecomp::yLP_Trans( Gambit::Vector &y ) const { int j; for (j = L.Length(); j >= 1; j--) { yLP_mult( y, j, ((LUdecomp &) *this).scratch2 ); y = scratch2; } } template void LUdecomp::yLP_mult( const Gambit::Vector &y, int j, Gambit::Vector &ans ) const { if ( ans.First() != y.First() || ans.Last() != y.Last() ) throw Gambit::DimensionException(); T temp; int i, k, l; l = j + y.First() - 1; for (i = y.First(); i <= y.Last(); i++) { if ( i != L[j].col) ans[i] = y[i]; else { for ( k = ans.First(), temp = (T) 0; k <= ans.Last(); k++) { temp += y[k] * L[j].etadata[k]; } ans[i] = temp; } } temp = ans[l]; ans[l] = ans[P[j]]; ans[P[j]] = temp; } template void LUdecomp::LPd_Trans( Gambit::Vector &d ) const { int j; for (j = 1; j <= L.Length(); j++) { LPd_mult( d, j, ((LUdecomp &) *this).scratch2 ); d = scratch2; } } template void LUdecomp::LPd_mult( Gambit::Vector &d, int j, Gambit::Vector &ans ) const { if ( d.First() != ans.First() || d.Last() != ans.Last() ) throw Gambit::DimensionException(); T temp; int i, k; k = j + d.First() - 1; temp = d[k]; d[k] = d[P[j]]; d[P[j]] = temp; for (i = d.First(); i <= d.Last(); i++) { if ( i == L[j].col ) ans[i] = d[i] * L[j].etadata[i]; else { ans[i] = d[i] + d[ L[j].col ] * L[j].etadata[i]; } } d[P[j]] = d[k]; d[k] = temp; } template bool LUdecomp::CheckBasis() { int i; bool ret = true; for (i = basis.First(); i <= basis.Last() && ret != false; i++) ret = ret && ( basis.Label(i) == -i ); return ret; } template bool LUdecomp::RefactorCheck() { int m = basis.Last() - basis.First() + 1; int i = iterations * (iterations * m + 2 * m * m ); int k = total_operations + iterations * m + 2 * m * m; bool tmp; tmp = ( i > k ); return tmp; } template LUdecomp::BadCount::~BadCount() { } template std::string LUdecomp::BadCount::GetDescription(void) const { return "Bad Reference count in LUdecomp"; } template LUdecomp::BadPivot::~BadPivot() { } template std::string LUdecomp::BadPivot::GetDescription(void) const { return "Bad Pivot in LUdecomp"; } gambit-0.2010.09.01/src/tools/lcp/nfglcp.cc0000644000076500007650000001541211441453421014727 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/nfglcp.cc // Compute Nash equilibria via Lemke-Howson algorithm // // 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 #include #include #include "libgambit/libgambit.h" #include "lhtab.h" using namespace Gambit; extern int g_numDecimals, g_stopAfter, g_maxDepth; extern bool g_printDetail; namespace { // // Pseudo-exception raised when maximum number of equilibria to compute // has been reached. A convenience for unraveling a potentially // deep recursion. // // FIXME: There is an identical twin of this in efglcp.cc. This should be // refactored into a more generally-useful and generally-visible location. // class EquilibriumLimitReachedNfg : public Exception { public: virtual ~EquilibriumLimitReachedNfg() { } std::string GetDescription(void) const { return "Reached target number of equilibria"; } }; } // end anonymous namespace void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedStrategyProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << "," << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedStrategyProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream << "," << p_profile[i]; } p_stream << std::endl; } template void PrintProfileDetail(std::ostream &p_stream, const MixedStrategyProfile &p_profile) { char buffer[256]; for (int pl = 1; pl <= p_profile.GetGame()->NumPlayers(); pl++) { GamePlayer player = p_profile.GetGame()->GetPlayer(pl); p_stream << "Strategy profile for player " << pl << ":\n"; p_stream << "Strategy Prob Value\n"; p_stream << "------- ----------- -----------\n"; for (int st = 1; st <= player->NumStrategies(); st++) { GameStrategy strategy = player->GetStrategy(st); if (strategy->GetLabel() != "") { sprintf(buffer, "%7s ", strategy->GetLabel().c_str()); } else { sprintf(buffer, "%7d ", st); } p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile[strategy], g_numDecimals).c_str()); p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile.GetStrategyValue(strategy), g_numDecimals).c_str()); p_stream << buffer; p_stream << "\n"; } } } template Matrix Make_A1(const StrategySupport &); template Vector Make_b1(const StrategySupport &); template Matrix Make_A2(const StrategySupport &); template Vector Make_b2(const StrategySupport &); // // Function called when a CBFS is encountered. // If it is not already in the list p_list, it is added. // The corresponding equilibrium is computed and output. // Returns 'true' if the CBFS is new; 'false' if it already appears in the // list. // template bool OnBFS(const StrategySupport &p_support, List > &p_list, LHTableau &p_tableau) { BFS cbfs(p_tableau.GetBFS()); if (p_list.Contains(cbfs)) { return false; } p_list.Append(cbfs); MixedStrategyProfile profile(p_support); int n1 = p_support.NumStrategies(1); int n2 = p_support.NumStrategies(2); T sum = (T) 0; for (int j = 1; j <= n1; j++) { if (cbfs.IsDefined(j)) sum += cbfs(j); } if (sum == (T) 0) { // This is the trivial CBFS. return false; } for (int j = 1; j <= n1; j++) { if (cbfs.IsDefined(j)) { profile[p_support.GetStrategy(1, j)] = cbfs(j) / sum; } else { profile[p_support.GetStrategy(1, j)] = (T) 0; } } sum = (T) 0; for (int j = 1; j <= n2; j++) { if (cbfs.IsDefined(n1 + j)) sum += cbfs(n1 + j); } for (int j = 1; j <= n2; j++) { if (cbfs.IsDefined(n1 + j)) { profile[p_support.GetStrategy(2, j)] = cbfs(n1 + j) / sum; } else { profile[p_support.GetStrategy(2, j)] = (T) 0; } } PrintProfile(std::cout, "NE", profile); if (g_printDetail) { PrintProfileDetail(std::cout, profile); } if (g_stopAfter > 0 && p_list.Length() >= g_stopAfter) { throw EquilibriumLimitReachedNfg(); } return true; } // // AllLemke finds all accessible Nash equilibria by recursively // calling itself. p_list maintains the list of basic variables // for the equilibria that have already been found. // From each new accessible equilibrium, it follows // all possible paths, adding any new equilibria to the List. // template void AllLemke(const StrategySupport &p_support, int j, LHTableau &B, List > &p_list, int depth) { if (g_maxDepth != 0 && depth > g_maxDepth) { return; } // On the initial depth=0 call, the CBFS we are at is the extraneous // solution. if (depth > 0 && !OnBFS(p_support, p_list, B)) { return; } for (int i = B.MinCol(); i <= B.MaxCol(); i++) { if (i != j) { LHTableau Bcopy(B); Bcopy.LemkePath(i); AllLemke(p_support, i, Bcopy, p_list, depth+1); } } } template void SolveStrategic(const Game &p_game) { StrategySupport support(p_game); List > bfsList; try { Matrix A1 = Make_A1(support); Vector b1 = Make_b1(support); Matrix A2 = Make_A2(support); Vector b2 = Make_b2(support); LHTableau B(A1, A2, b1, b2); if (g_stopAfter != 1) { try { AllLemke(support, 0, B, bfsList, 0); } catch (EquilibriumLimitReachedNfg &) { // This pseudo-exception requires no additional action; // bfsList will contain the list of equilibria found } } else { B.LemkePath(1); OnBFS(support, bfsList, B); } return; } catch (...) { // for now, we won't give *any* solutions -- but we should list // any solutions found! throw; } } template void SolveStrategic(const Game &); template void SolveStrategic(const Game &); gambit-0.2010.09.01/src/tools/lcp/tableau.cc0000644000076500007650000000174611435216102015074 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/tableau.cc // Instantiation of tableau classes // // 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 "libgambit/rational.h" #include "tableau.imp" #include gambit-0.2010.09.01/src/tools/lcp/tableau.h0000644000076500007650000001144211435216102014730 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/tableau.h // Interface to tableau class // // 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 TABLEAU_H #define TABLEAU_H #include "btableau.h" #include "ludecomp.h" template class Tableau; template class LPTableau; // --------------------------------------------------------------------------- // We have different implementations of Tableau for double and gbtRational, // but with the same interface // --------------------------------------------------------------------------- // // Tableau // template<> class Tableau : public TableauInterface{ private: LUdecomp B; // LU decomposition Gambit::Vector tmpcol; // temporary column vector, to avoid allocation public: // constructors and destructors Tableau(const Gambit::Matrix &A, const Gambit::Vector &b); Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); Tableau(const Tableau&); virtual ~Tableau(); Tableau& operator=(const Tableau&); // pivoting int CanPivot(int outgoing,int incoming); void Pivot(int outrow,int col); // pivot -- outgoing is row, incoming is column void BasisVector(Gambit::Vector &x) const; // solve M x = (*b) void SolveColumn(int, Gambit::Vector &); // column in new basis void Solve(const Gambit::Vector &b, Gambit::Vector &x); // solve M x = b void SolveT(const Gambit::Vector &c, Gambit::Vector &y); // solve y M = c // raw Tableau functions void Refactor(); void SetRefactor(int); void SetConst(const Gambit::Vector &bnew); void SetBasis( const Basis &); // set new Tableau bool IsFeasible(); bool IsLexMin(); }; // // Tableau // template<> class Tableau : public TableauInterface{ private: int remap(int col_index) const; // aligns the column indexes Gambit::Matrix GetInverse(); Gambit::Matrix Tabdat; // This caries the full tableau Gambit::Vector Coeff; // and coeffieient vector Gambit::Integer totdenom; // This carries the denominator for Q data or 1 for Z Gambit::Integer denom; // This is the denominator for the simplex Gambit::Vector tmpcol; // temporary column vector, to avoid allocation void MySolveColumn(int, Gambit::Vector &); // column in new basis protected: Gambit::Array nonbasic; //** nonbasic variables -- should be moved to Basis public: class BadDenom : public Gambit::Exception { public: virtual ~BadDenom(); std::string GetDescription(void) const; }; // constructors and destructors Tableau(const Gambit::Matrix &A, const Gambit::Vector &b); Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); Tableau(const Tableau&); virtual ~Tableau(); Tableau& operator=(const Tableau&); // pivoting int CanPivot(int outgoing,int incoming); void Pivot(int outrow,int col); // pivot -- outgoing is row, incoming is column void SolveColumn(int, Gambit::Vector &); // column in new basis void GetColumn(int, Gambit::Vector &) const; // column in new basis // raw Tableau functions void Refactor(); void SetRefactor(int); void SetConst(const Gambit::Vector &bnew); void SetBasis( const Basis &); // set new Tableau void Solve(const Gambit::Vector &b, Gambit::Vector &x); // solve M x = b void SolveT(const Gambit::Vector &c, Gambit::Vector &y); // solve y M = c bool IsFeasible(); bool IsLexMin(); void BasisVector(Gambit::Vector &out) const; Gambit::Integer TotDenom() const; }; #endif // TABLEAU_H gambit-0.2010.09.01/src/tools/lcp/tableau.imp0000644000076500007650000003672511435216102015301 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lcp/tableau.imp // Implementation of tableau class // // 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 "tableau.h" // --------------------------------------------------------------------------- // Tableau method definitions // --------------------------------------------------------------------------- // Constructors and Destructor Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Vector &b) : TableauInterface(A,b), B(*this), tmpcol(b.First(),b.Last()) { Solve(b, solution); }; Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : TableauInterface(A,art,b), B(*this), tmpcol(b.First(),b.Last()) { Solve(b, solution); }; Tableau::Tableau(const Tableau &orig) : TableauInterface(orig), B(orig.B,*this), tmpcol(orig.tmpcol) { } Tableau::~Tableau() { } Tableau& Tableau::operator=(const Tableau &orig) { TableauInterface::operator=(orig); if(this!= &orig) { B.Copy(orig.B,*this); tmpcol = orig.tmpcol; } return *this; } // // pivoting operations // int Tableau::CanPivot(int outlabel, int col) { SolveColumn(col,tmpcol); double val = tmpcol[basis.Find(outlabel)]; if(val <=eps2 && val >= -eps2) return 0; return 1; } void Tableau::Pivot(int outrow,int col) { if(!RowIndex(outrow) || !ValidIndex(col)) throw BadPivot(); // int outlabel = Label(outrow); // gout << "\noutrow:" << outrow; // gout << " outlabel: " << outlabel; // gout << " inlabel: " << col; // BigDump(gout); basis.Pivot(outrow,col); B.update(outrow, col); Solve(*b, solution); npivots++; // BigDump(gout); } void Tableau::SolveColumn(int col, Gambit::Vector &out) { //** can we use tmpcol here, instead of allocating new vector? Gambit::Vector tmpcol2(MinRow(),MaxRow()); GetColumn(col,tmpcol2); Solve(tmpcol2,out); } void Tableau::BasisVector(Gambit::Vector &out) const { out= solution; } // // raw Tableau functions // void Tableau::Refactor() { B.refactor(); //** is re-solve necessary here? Solve(*b, solution); } void Tableau::SetRefactor(int n) { B.SetRefactor(n); } void Tableau::SetConst(const Gambit::Vector &bnew) { if(bnew.First()!=b->First() || bnew.Last()!=b->Last()) throw Gambit::DimensionException(); b=&bnew; Solve(*b, solution); } //** this function is not currently used. Drop it? void Tableau::SetBasis(const Basis &in) { basis= in; B.refactor(); Solve(*b, solution); } void Tableau::Solve(const Gambit::Vector &b, Gambit::Vector &x) { B.solve(b,x); } void Tableau::SolveT(const Gambit::Vector &c, Gambit::Vector &y) { B.solveT(c,y); //** gout << "\nTableau::SolveT(), y: " << y; // gout << "\nc: " << c; } bool Tableau::IsFeasible() { //** is it really necessary to solve first here? Solve(*b, solution); for(int i=solution.First();i<=solution.Last();i++) if(solution[i]>=eps2) return false; return true; } bool Tableau::IsLexMin() { int i,j; for(i=MinRow();i<=MaxRow();i++) if(EqZero(solution[i])) for(j=-MaxRow();j method definitions // --------------------------------------------------------------------------- Gambit::Integer find_lcd(const Gambit::Matrix &mat) { Gambit::Integer lcd(1); for(int i=mat.MinRow();i<=mat.MaxRow();i++) for(int j=mat.MinCol();j<=mat.MaxCol();j++) lcd = lcm(mat(i,j).denominator(),lcd); return lcd; } Gambit::Integer find_lcd(const Gambit::Vector &vec) { Gambit::Integer lcd(1); for(int i=vec.First();i<=vec.Last();i++) lcd = lcm(vec[i].denominator(),lcd); return lcd; } // Constructors and Destructor Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Vector &b) : TableauInterface(A,b), Tabdat(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()), Coeff(b.First(),b.Last()), denom(1), tmpcol(b.First(),b.Last()), nonbasic(A.MinCol(),A.MaxCol()) { int j; for(j=MinCol();j<=MaxCol();j++) nonbasic[j] = j; totdenom = lcm(find_lcd(A),find_lcd(b)); if(totdenom<=0) throw BadDenom(); for (int i = b.First();i<=b.Last();i++) { Gambit::Rational x = b[i]*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Coeff[i] = x.numerator(); } for (int i = MinRow();i<=MaxRow();i++) for (int j = MinCol();j<=MaxCol();j++) { Gambit::Rational x = A(i,j)*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Tabdat(i,j) = x.numerator(); } for (int i = b.First();i<=b.Last();i++) solution[i] = (Gambit::Rational)Coeff[i]; } Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : TableauInterface(A,art,b), Tabdat(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()+art.Length()), Coeff(b.First(),b.Last()), denom(1), tmpcol(b.First(),b.Last()), nonbasic(A.MinCol(),A.MaxCol()+art.Length()) { int j; for(j=MinCol();j<=MaxCol();j++) nonbasic[j] = j; totdenom = lcm(find_lcd(A),find_lcd(b)); if(totdenom<=0) throw BadDenom(); for (int i = b.First();i<=b.Last();i++) { Gambit::Rational x = b[i]*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Coeff[i] = x.numerator(); } for (int i = MinRow();i<=MaxRow();i++) { for (int j = MinCol();j<=A.MaxCol();j++) { Gambit::Rational x = A(i,j)*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Tabdat(i,j) = x.numerator(); } for (int j = A.MaxCol()+1;j<=MaxCol();j++) Tabdat(artificial[j],j) = totdenom; } for (int i = b.First();i<=b.Last();i++) solution[i] = (Gambit::Rational)Coeff[i]; } Tableau::Tableau(const Tableau &orig) : TableauInterface(orig), Tabdat(orig.Tabdat), Coeff(orig.Coeff), totdenom(orig.totdenom), denom(orig.denom), tmpcol(orig.tmpcol), nonbasic(orig.nonbasic) { } Tableau::~Tableau() { } Tableau& Tableau::operator=(const Tableau &orig) { TableauInterface::operator=(orig); if(this!= &orig) { Tabdat = orig.Tabdat; Coeff = orig.Coeff; totdenom = orig.totdenom; denom = orig.denom; tmpcol = orig.tmpcol; nonbasic = orig.nonbasic; } return *this; } // Aligns the column indexes int Tableau::remap(int col_index) const { int i = nonbasic.First(); while(i <= nonbasic.Last() && nonbasic[i] !=col_index) { i++;} if(i > nonbasic.Last()) throw Gambit::DimensionException(); return i; } Gambit::Matrix Tableau::GetInverse() { Gambit::Vector mytmpcol(tmpcol.First(),tmpcol.Last()); Gambit::Matrix inv(MinRow(),MaxRow(),MinRow(),MaxRow()); for(int i=inv.MinCol();i<=inv.MaxCol();i++){ MySolveColumn(-i,mytmpcol); inv.SetColumn(i,mytmpcol); } return inv; } // pivoting operations int Tableau::CanPivot(int outlabel, int col) { MySolveColumn(col,tmpcol); Gambit::Rational val = tmpcol[basis.Find(outlabel)]; if(val == (Gambit::Rational)0) return 0; // if(val <=eps2 && val >= -eps2) return 0; return 1; } void Tableau::Pivot(int outrow,int in_col) { // gout << "\nIn Tableau::Pivot() "; // gout << " outrow:" << outrow; // gout << " inlabel: " << in_col; if(!RowIndex(outrow) || !ValidIndex(in_col)) throw BadPivot(); int outlabel = Label(outrow); // gout << "\noutrow:" << outrow; // gout << " outlabel: " << outlabel; // gout << " inlabel: " << in_col; // BigDump(gout); // gout << "\ndenom: " << denom << " totdenom: " << totdenom; // gout << " product: " << denom*totdenom; // gout << "\nTabdat: loc 1\n " << Tabdat; // gout << "\nInverse: loc 1\n " << GetInverse(); int col; int row(outrow); int i,j; // loop-control variables col = remap(in_col); // Pivot Algorithm: // i* denotes Pivot Row // j* denotes Pivot Column // C is the Tableau // Cij is the (i,j)th component of C // X denotes multiplication // d is the denominator (initially 1) // // 1: Copy row i (don't need to implement this) // 2: Zero column j excepting the Pivot Element (done second) // 3: Cij=(Ci*j*XCij-Ci*jXCij*)/d for all other elements (done first) // 4: d=Ci*j* (done last) // Step 3 for(i=Tabdat.MinRow();i<=Tabdat.MaxRow();++i){ if(i!=row){ for(j=Tabdat.MinCol();j<=Tabdat.MaxCol();++j){ if(j!=col){ Tabdat(i,j) = (Tabdat(row,col)*Tabdat(i,j)-Tabdat(row,j)*Tabdat(i,col))/denom; } } Coeff[i] = (Tabdat(row,col)*Coeff[i]-Coeff[row]*Tabdat(i,col))/denom; } } // Step 2 // Note: here we are moving the old basis column into column 'col' for(i=Tabdat.MinRow();i<=Tabdat.MaxRow();++i){ if(i!=row) Tabdat(i,col)=-Tabdat(i,col); } // Step 4 Gambit::Integer old_denom = denom; denom=Tabdat(row,col); Tabdat(row,col)=old_denom; // BigDump(gout); npivots++; basis.Pivot(outrow,in_col); nonbasic[col] = outlabel; for (i = solution.First();i<=solution.Last();i++) //** solution[i] = (Gambit::Rational)(Coeff[i])/(Gambit::Rational)(denom*totdenom); solution[i] = Gambit::Rational(Coeff[i]*sign(denom*totdenom)); //gout << "Bottom \n" << Tabdat << '\n'; // BigDump(gout); // gout << "\ndenom: " << denom << " totdenom: " << totdenom; // gout << "\nTabdat: loc 2\n " << Tabdat; // gout << "\nInverse: loc 2\n " << GetInverse(); // Refactor(); } void Tableau::SolveColumn(int in_col, Gambit::Vector &out) { Gambit::Vector tempcol(tmpcol.First(),tmpcol.Last()); if(Member(in_col)) { out = (Gambit::Rational)0; out[Find(in_col)] = Gambit::Rational(abs(denom)); } else { int col = remap(in_col); Tabdat.GetColumn(col,tempcol); for(int i=tempcol.First();i<=tempcol.Last();i++) out[i] = (Gambit::Rational)(tempcol[i]) * (Gambit::Rational)(sign(denom*totdenom)); } out=out/(Gambit::Rational)abs(denom); if(in_col < 0) out*=totdenom; for(int i=out.First();i<=out.Last();i++) if(Label(i)<0) out[i]=(Gambit::Rational)out[i]/(Gambit::Rational)totdenom; } void Tableau::MySolveColumn(int in_col, Gambit::Vector &out) { Gambit::Vector tempcol(tmpcol.First(),tmpcol.Last()); if(Member(in_col)) { out = (Gambit::Rational)0; out[Find(in_col)] = Gambit::Rational(abs(denom)); } else { int col = remap(in_col); Tabdat.GetColumn(col,tempcol); for(int i=tempcol.First();i<=tempcol.Last();i++) out[i] = (Gambit::Rational)(tempcol[i]) * (Gambit::Rational)(sign(denom*totdenom)); } } void Tableau::GetColumn(int col, Gambit::Vector &out) const { TableauInterface::GetColumn(col,out); if(col>=0) out*=Gambit::Rational(totdenom); } void Tableau::Refactor() { Gambit::Vector mytmpcol(tmpcol); //BigDump(gout); //** Note -- we may need to recompute totdenom here, if A and b have changed. //gout << "\ndenom: " << denom << " totdenom: " << totdenom; totdenom = lcm(find_lcd(*A),find_lcd(*b)); if(totdenom<=0) throw BadDenom(); // gout << "\ndenom: " << denom << " totdenom: " << totdenom; int i,j; Gambit::Matrix inv(GetInverse()); Gambit::Matrix Tabnew(Tabdat.MinRow(),Tabdat.MaxRow(),Tabdat.MinCol(),Tabdat.MaxCol()); for(i=nonbasic.First();i<=nonbasic.Last();i++) { GetColumn(nonbasic[i],mytmpcol); // if(nonbasic[i]>=0) mytmpcol*=Gambit::Rational(totdenom); Tabnew.SetColumn(i,inv * mytmpcol * (Gambit::Rational)sign(denom*totdenom)); //gout << "\nMyTmpCol \n" << mytmpcol; } //gout << "\nInv: \n" << inv; //gout << "\nTabdat:\n" << Tabdat; //gout << "\nTabnew:\n" << Tabnew; Gambit::Vector Coeffnew(Coeff.First(),Coeff.Last()); Coeffnew = inv * (*b) * totdenom * (Gambit::Rational)sign(denom*totdenom); //gout << "\nCoeff:\n" << Coeff; //gout << "\nCoeffew:\n" << Coeffnew; for(i=Tabdat.MinRow();i<=Tabdat.MaxRow();i++) { if(Coeffnew[i].denominator() != 1) throw BadDenom(); Coeff[i] = Coeffnew[i].numerator(); for(j=Tabdat.MinCol();j<=Tabdat.MaxCol();j++) { if(Tabnew(i,j).denominator() != 1) throw BadDenom(); Tabdat(i,j) = Tabnew(i,j).numerator(); } } //BigDump(gout); } void Tableau::SetRefactor(int) { } void Tableau::SetConst(const Gambit::Vector &bnew) { b=&bnew; Refactor(); } //** this function is not currently used. Drop it? void Tableau::SetBasis(const Basis &in) { basis= in; //** this has to be changed -- Need to start over and pivot to new basis. // B.refactor(); // B.solve(*b, solution); } // solve M x = b void Tableau::Solve(const Gambit::Vector &b, Gambit::Vector &x) { // Here, we do x = V * b, where V = M inverse x = (GetInverse() * b )/(Gambit::Rational)abs(denom); } // solve y M = c void Tableau::SolveT(const Gambit::Vector &c, Gambit::Vector &y) { // Here we do y = c * V, where V = M inverse y = (c * GetInverse()) /(Gambit::Rational)abs(denom); } bool Tableau::IsFeasible() { for(int i=solution.First();i<=solution.Last();i++) if(solution[i]>=eps2) return false; return true; } bool Tableau::IsLexMin() { int i,j; for(i=MinRow();i<=MaxRow();i++) if(EqZero(solution[i])) for(j=-MaxRow();j::BasisVector(Gambit::Vector &out) const { out = solution; out= out/(Gambit::Rational)abs(denom) ; for(int i=out.First();i<=out.Last();i++) if(Label(i)<0) out[i]=out[i]/(Gambit::Rational)totdenom; } Gambit::Integer Tableau::TotDenom() const { return totdenom; } Tableau::BadDenom::~BadDenom() { } std::string Tableau::BadDenom::GetDescription(void) const { return "Bad Denominator in Tableau"; } gambit-0.2010.09.01/src/tools/liap/0000777000076500007650000000000011441457123013402 500000000000000gambit-0.2010.09.01/src/tools/liap/efgliap.cc0000644000076500007650000001451211435216102015230 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/liap/efgliap.cc // Compute Nash equilibria via Lyapunov function minimization // // This file is part of Gambit // Copyright (c) 2002, The Gambit Project // // 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 #include #include #include #include "libgambit/libgambit.h" #include "funcmin.h" extern int m_stopAfter; extern int m_numTries; extern int m_maxits1; extern int m_maxitsN; extern double m_tol1; extern double m_tolN; extern std::string startFile; extern bool useRandom; extern int g_numDecimals; extern bool verbose; class EFLiapFunc : public gC1Function { private: mutable long _nevals; Gambit::Game _efg; mutable Gambit::MixedBehavProfile _p; double Value(const Gambit::Vector &x) const; bool Gradient(const Gambit::Vector &, Gambit::Vector &) const; public: EFLiapFunc(Gambit::Game, const Gambit::MixedBehavProfile &); virtual ~EFLiapFunc(); long NumEvals(void) const { return _nevals; } }; EFLiapFunc::EFLiapFunc(Gambit::Game E, const Gambit::MixedBehavProfile &start) : _nevals(0L), _efg(E), _p(start) { } EFLiapFunc::~EFLiapFunc() { } double EFLiapFunc::Value(const Gambit::Vector &v) const { _nevals++; ((Gambit::Vector &) _p).operator=(v); //_p = v; return _p.GetLiapValue(); } // // This function projects a gradient into the plane of the simplex. // (Actually, it works by computing the projection of 'x' onto the // vector perpendicular to the plane, then subtracting to compute the // component parallel to the plane.) // static void Project(Gambit::Vector &x, const Gambit::Array &lengths) { int index = 1; for (int part = 1; part <= lengths.Length(); part++) { double avg = 0.0; int j; for (j = 1; j <= lengths[part]; j++, index++) { avg += x[index]; } avg /= (double) lengths[part]; index -= lengths[part]; for (j = 1; j <= lengths[part]; j++, index++) { x[index] -= avg; } } } bool EFLiapFunc::Gradient(const Gambit::Vector &x, Gambit::Vector &grad) const { const double DELTA = .00001; ((Gambit::Vector &) _p).operator=(x); for (int i = 1; i <= x.Length(); i++) { _p[i] += DELTA; double value = _p.GetLiapValue(); _p[i] -= 2.0 * DELTA; value -= _p.GetLiapValue(); _p[i] += DELTA; grad[i] = value / (2.0 * DELTA); } Project(grad, _p.GetGame()->NumInfosets()); return true; } static void PickRandomProfile(Gambit::MixedBehavProfile &p) { double sum, tmp; for (int pl = 1; pl <= p.GetGame()->NumPlayers(); pl++) { for (int iset = 1; iset <= p.GetGame()->GetPlayer(pl)->NumInfosets(); iset++) { sum = 0.0; int act; for (act = 1; act < p.GetSupport().NumActions(pl, iset); act++) { do tmp = ((double) rand()) / ((double) RAND_MAX); while (tmp + sum > 1.0); p(pl, iset, act) = tmp; sum += tmp; } // with truncation, this is unnecessary p(pl, iset, act) = 1.0 - sum; } } } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const Gambit::MixedBehavProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << ", " << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } bool ReadProfile(std::istream &p_stream, Gambit::MixedBehavProfile &p_profile) { for (int i = 1; i <= p_profile.Length(); i++) { if (p_stream.eof() || p_stream.bad()) { return false; } p_stream >> p_profile[i]; if (i < p_profile.Length()) { char comma; p_stream >> comma; } } // Read in the rest of the line and discard std::string foo; std::getline(p_stream, foo); return true; } void SolveExtensive(const Gambit::Game &p_game) { Gambit::List > starts; if (startFile != "") { std::ifstream startPoints(startFile.c_str()); while (!startPoints.eof() && !startPoints.bad()) { Gambit::MixedBehavProfile start(p_game); if (ReadProfile(startPoints, start)) { starts.Append(start); } } } else { // Generate the desired number of points randomly for (int i = 1; i <= m_numTries; i++) { Gambit::MixedBehavProfile start(p_game); PickRandomProfile(start); starts.Append(start); } } static const double ALPHA = .00000001; for (int i = 1; i <= starts.Length(); i++) { Gambit::MixedBehavProfile p(starts[i]); if (verbose) { PrintProfile(std::cout, "start", p); } EFLiapFunc F(p_game, p); // if starting vector not interior, perturb it towards centroid int kk; for (int kk = 1; kk <= p.Length() && p[kk] > ALPHA; kk++); if (kk <= p.Length()) { Gambit::MixedBehavProfile c(p_game); for (int k = 1; k <= p.Length(); k++) { p[k] = c[k]*ALPHA + p[k]*(1.0-ALPHA); } } Gambit::Matrix xi(p.Length(), p.Length()); gConjugatePR minimizer(p.Length()); Gambit::Vector gradient(p.Length()), dx(p.Length()); double fval; minimizer.Set(F, p, fval, gradient, .01, .0001); try { for (int iter = 1; iter <= m_maxitsN; iter++) { if (!minimizer.Iterate(F, p, fval, gradient, dx)) { break; } if (sqrt(gradient.NormSquared()) < .001) { PrintProfile(std::cout, "NE", p); break; } } if (verbose && sqrt(gradient.NormSquared()) >= .001) { PrintProfile(std::cout, "end", p); } } catch (gFuncMinException &) { } } } gambit-0.2010.09.01/src/tools/liap/funcmin.cc0000644000076500007650000002055611435216102015265 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/liap/funcmin.cc // Implementation of N-dimensional function minimization routines // // These routines derive from the N-dimensional function minimization // routines in the GNU Scientific Library, version 1.2, which is // Copyright (C) 1996, 1997, 1998, 1999, 2000 Fabrice Rossi // and is released under the terms of the GNU General Public License. // Modifications consist primarily of converting the routines to // use Gambit's vector and function classes. // // 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 #include "libgambit/libgambit.h" #include "funcmin.h" //======================================================================== // Private auxiliary routines //======================================================================== static void AlphaXPlusY(double alpha, const Gambit::Vector &x, Gambit::Vector &y) { for (int i = 1; i <= y.Length(); i++) { y[i] += alpha * x[i]; } } // These routines are drawn from comparably-named ones in // multimin/directional_minimize.c in GSL. static void TakeStep(const Gambit::Vector &x, const Gambit::Vector &p, double step, double lambda, Gambit::Vector &x1, Gambit::Vector &dx) { dx = 0.0; AlphaXPlusY(-step * lambda, p, dx); x1 = x; AlphaXPlusY(1.0, dx, x1); } static void IntermediatePoint(const gC1Function &fdf, const Gambit::Vector &x, const Gambit::Vector &p, double lambda, double pg, double stepa, double stepc, double fa, double fc, Gambit::Vector &x1, Gambit::Vector &dx, Gambit::Vector &gradient, double &step, double &f) { double stepb, fb; trial: double u = fabs (pg * lambda * stepc); if ((fc - fa) + u == 0) { // TLT: Added this check 2002/08/31 due to floating point exceptions // under MSW. Not really sure how to handle this correctly. throw gFuncMinException(); } stepb = 0.5 * stepc * u / ((fc - fa) + u); TakeStep(x, p, stepb, lambda, x1, dx); fb = fdf.Value(x1); if (fb >= fa && stepb > 0.0) { /* downhill step failed, reduce step-size and try again */ fc = fb; stepc = stepb; goto trial; } step = stepb; f = fb; fdf.Gradient(x1, gradient); } static void Minimize(const gC1Function &fdf, const Gambit::Vector &x, const Gambit::Vector &p, double lambda, double stepa, double stepb, double stepc, double fa, double fb, double fc, double tol, Gambit::Vector &x1, Gambit::Vector &dx1, Gambit::Vector &x2, Gambit::Vector &dx2, Gambit::Vector &gradient, double &step, double &f, double &gnorm) { /* Starting at (x0, f0) move along the direction p to find a minimum f(x0 - lambda * p), returning the new point x1 = x0-lambda*p, f1=f(x1) and g1 = grad(f) at x1. */ double u = stepb; double v = stepa; double w = stepc; double fu = fb; double fv = fa; double fw = fc; double old2 = fabs(w - v); double old1 = fabs(v - u); double stepm, fm, pg, gnorm1; double iter = 0; x2 = x1; dx2 = dx1; f = fb; step = stepb; gnorm = sqrt(gradient.NormSquared()); mid_trial: iter++; if (iter > 10) { return; /* MAX ITERATIONS */ } double dw = w - u; double dv = v - u; double du = 0.0; double e1 = ((fv - fu) * dw * dw + (fu - fw) * dv * dv); double e2 = 2.0 * ((fv - fu) * dw + (fu - fw) * dv); if (e2 != 0.0) { du = e1 / e2; } if (du > 0 && du < (stepc - stepb) && fabs(du) < 0.5 * old2) { stepm = u + du; } else if (du < 0 && du > (stepa - stepb) && fabs(du) < 0.5 * old2) { stepm = u + du; } else if ((stepc - stepb) > (stepb - stepa)) { stepm = 0.38 * (stepc - stepb) + stepb; } else { stepm = stepb - 0.38 * (stepb - stepa); } TakeStep(x, p, stepm, lambda, x1, dx1); fm = fdf.Value(x1); if (fm > fb) { if (fm < fv) { w = v; v = stepm; fw = fv; fv = fm; } else if (fm < fw) { w = stepm; fw = fm; } if (stepm < stepb) { stepa = stepm; fa = fm; } else { stepc = stepm; fc = fm; } goto mid_trial; } else if (fm <= fb) { old2 = old1; old1 = fabs(u - stepm); w = v; v = u; u = stepm; fw = fv; fv = fu; fu = fm; x2 = x1; dx2 = dx1; fdf.Gradient(x1, gradient); pg = p * gradient; gnorm1 = sqrt(gradient.NormSquared()); f = fm; step = stepm; gnorm = gnorm1; if (gnorm1 == 0.0) { return; } if (fabs (pg * lambda / gnorm1) < tol) { return; /* SUCCESS */ } if (stepm < stepb) { stepc = stepb; fc = fb; stepb = stepm; fb = fm; } else { stepa = stepb; fa = fb; stepb = stepm; fb = fm; } goto mid_trial; } } //======================================================================== // Conjugate gradient Polak-Ribiere algorithm //======================================================================== // // These routines are based on ones found in // multimin/conjugate_pr.c in the GSL 1.2 distribution gConjugatePR::gConjugatePR(int n) : x1(n), dx1(n), x2(n), p(n), g0(n) { } void gConjugatePR::Set(const gC1Function &fdf, const Gambit::Vector &x, double &f, Gambit::Vector &gradient, double step_size, double p_tol) { iter = 0; step = step_size; max_step = step_size; tol = p_tol; f = fdf.Value(x); fdf.Gradient(x, gradient); /* Use the gradient as the initial direction */ p = gradient; g0 = gradient; double gnorm = sqrt(gradient.NormSquared()); pnorm = gnorm; g0norm = gnorm; } void gConjugatePR::Restart(void) { iter = 0; } bool gConjugatePR::Iterate(const gC1Function &fdf, Gambit::Vector &x, double &f, Gambit::Vector &gradient, Gambit::Vector &dx) { double fa = f, fb, fc; double dir; double stepa = 0.0, stepb, stepc = step, tol = tol; double g1norm; double pg; if (pnorm == 0.0 || g0norm == 0.0) { dx = 0.0; return false; } /* Determine which direction is downhill, +p or -p */ pg = p * gradient; dir = (pg >= 0.0) ? +1.0 : -1.0; /* Compute new trial point at x_c= x - step * p, where p is the current direction */ TakeStep(x, p, stepc, dir / pnorm, x1, dx); /* Evaluate function and gradient at new point xc */ fc = fdf.Value(x1); if (fc < fa) { /* Success, reduced the function value */ step = stepc * 2.0; f = fc; x = x1; fdf.Gradient(x1, gradient); g0norm = sqrt(gradient.NormSquared()); return true; } /* Do a line minimisation in the region (xa,fa) (xc,fc) to find an intermediate (xb,fb) satisifying fa > fb < fc. Choose an initial xb based on parabolic interpolation */ IntermediatePoint(fdf, x, p, dir / pnorm, pg, stepa, stepc, fa, fc, x1, dx1, gradient, stepb, fb); if (stepb == 0.0) { return false; } Minimize(fdf, x, p, dir / pnorm, stepa, stepb, stepc, fa, fb, fc, tol, x1, dx1, x2, dx, gradient, step, f, g1norm); x = x2; /* Choose a new conjugate direction for the next step */ iter = (iter + 1) % x.Length(); if (iter == 0) { p = gradient; pnorm = g1norm; } else { /* p' = g1 - beta * p */ double g0g1, beta; AlphaXPlusY(-1.0, gradient, g0); /* g0' = g0 - g1 */ g0g1 = g0 * gradient; /* g1g0 = (g0-g1).g1 */ beta = g0g1 / (g0norm*g0norm); /* beta = -((g1 - g0).g1)/(g0.g0) */ p *= -beta; AlphaXPlusY(1.0, gradient, p); pnorm = sqrt(p.NormSquared()); } g0norm = g1norm; g0 = gradient; return true; } gambit-0.2010.09.01/src/tools/liap/funcmin.h0000644000076500007650000000554411435216102015127 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/liap/funcmin.h // Interface to N-dimensional function minimization routines // // 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 GFUNCMIN_H #define GFUNCMIN_H #include "libgambit/vector.h" template class gFunction { public: virtual ~gFunction() { } virtual T Value(const Gambit::Vector &) const = 0; }; template class gC1Function : public gFunction { public: virtual ~gC1Function() { } virtual bool Gradient(const Gambit::Vector &, Gambit::Vector &) const = 0; }; class gbtFuncMinError : public Gambit::Exception { public: virtual ~gbtFuncMinError() { } std::string GetDescription(void) const { return "Internal error in minimization code"; } }; // // gFunctionMinimizer is an abstract base class for function minimization // class gFunctionMinimizer { public: virtual ~gFunctionMinimizer() { } virtual void Set(const gC1Function &fdf, const Gambit::Vector &x, double &f, Gambit::Vector &gradient, double step_size, double p_tol) = 0; virtual void Restart(void) = 0; virtual bool Iterate(const gC1Function &fdf, Gambit::Vector &x, double &f, Gambit::Vector &gradient, Gambit::Vector &dx) = 0; }; // // gConjugatePR: implements Polak-Ribiere conjugate gradient descent // class gConjugatePR : public gFunctionMinimizer { private: int iter; double step; double max_step; double tol; Gambit::Vector x1; Gambit::Vector dx1; Gambit::Vector x2; double pnorm; Gambit::Vector p; double g0norm; Gambit::Vector g0; public: gConjugatePR(int n); virtual ~gConjugatePR() { } void Set(const gC1Function &fdf, const Gambit::Vector &x, double &f, Gambit::Vector &gradient, double step_size, double p_tol); void Restart(void); bool Iterate(const gC1Function &fdf, Gambit::Vector &x, double &f, Gambit::Vector &gradient, Gambit::Vector &dx); }; class gFuncMinException { }; #endif // GFUNCMIN_H gambit-0.2010.09.01/src/tools/liap/liap.cc0000644000076500007650000000734211435216102014551 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/liap/liap.cc // Compute Nash equilibria by minimizing Liapunov function // // 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 #include #include #include "libgambit/libgambit.h" void PrintBanner(std::ostream &p_stream) { p_stream << "Compute Nash equilibria by minimizing the Lyapunov function\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "With no options, attempts to compute one equilibrium starting at centroid.\n"; std::cerr << "Options:\n"; std::cerr << " -d DECIMALS print probabilities with DECIMALS digits\n"; std::cerr << " -h print this help message\n"; std::cerr << " -n COUNT number of starting points to generate\n"; std::cerr << " -s FILE file containing starting points\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; std::cerr << " -v verbose mode (shows intermediate output)\n"; std::cerr << " (default is to only show equilibria)\n"; exit(1); } extern void SolveStrategic(const Gambit::Game &); extern void SolveExtensive(const Gambit::Game &); int m_stopAfter = 0; int m_numTries = 10; int m_maxits1 = 100; int m_maxitsN = 20; double m_tol1 = 2.0e-10; double m_tolN = 1.0e-10; std::string startFile = ""; bool useRandom = false; int g_numDecimals = 6; bool verbose = false; int main(int argc, char *argv[]) { opterr = 0; bool quiet = false, useStrategic = false; int c; while ((c = getopt(argc, argv, "d:n:s:hqvS")) != -1) { switch (c) { case 'd': g_numDecimals = atoi(optarg); break; case 'n': m_numTries = atoi(optarg); break; case 's': startFile = optarg; break; case 'h': PrintHelp(argv[0]); break; case 'S': useStrategic = true; break; case 'q': quiet = true; break; case 'v': verbose = true; break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Gambit::Game game = Gambit::ReadGame(std::cin); if (!game->IsTree() || useStrategic) { game->BuildComputedValues(); SolveStrategic(game); } else { SolveExtensive(game); } return 0; } catch (Gambit::InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } } gambit-0.2010.09.01/src/tools/liap/nfgliap.cc0000644000076500007650000001652411435216102015246 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/liap/nfgliap.cc // Compute Nash equilibria by minimizing Liapunov function // // 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 #include #include #include #include "libgambit/libgambit.h" #include "funcmin.h" extern int m_stopAfter; extern int m_numTries; extern int m_maxits1; extern int m_maxitsN; extern double m_tol1; extern double m_tolN; extern std::string startFile; extern bool useRandom; extern int g_numDecimals; extern bool verbose; //--------------------------------------------------------------------- // class NFLiapFunc //--------------------------------------------------------------------- class NFLiapFunc : public gC1Function { private: mutable long _nevals; Gambit::Game _nfg; mutable Gambit::MixedStrategyProfile _p; double Value(const Gambit::Vector &) const; bool Gradient(const Gambit::Vector &, Gambit::Vector &) const; double LiapDerivValue(int, int, const Gambit::MixedStrategyProfile &) const; public: NFLiapFunc(const Gambit::Game &, const Gambit::MixedStrategyProfile &); virtual ~NFLiapFunc(); long NumEvals(void) const { return _nevals; } }; NFLiapFunc::NFLiapFunc(const Gambit::Game &N, const Gambit::MixedStrategyProfile &start) : _nevals(0L), _nfg(N), _p(start) { } NFLiapFunc::~NFLiapFunc() { } double NFLiapFunc::LiapDerivValue(int i1, int j1, const Gambit::MixedStrategyProfile &p) const { int i, j; double x, x1, psum; x = 0.0; for (i = 1; i <= _nfg->NumPlayers(); i++) { psum = 0.0; for (j = 1; j <= p.GetSupport().NumStrategies(i); j++) { psum += p[p.GetSupport().GetStrategy(i,j)]; x1 = p.GetStrategyValue(p.GetSupport().GetStrategy(i, j)) - p.GetPayoff(i); if (i1 == i) { if (x1 > 0.0) x -= x1 * p.GetPayoffDeriv(i, p.GetSupport().GetStrategy(i1, j1)); } else { if (x1> 0.0) x += x1 * (p.GetPayoffDeriv(i, p.GetSupport().GetStrategy(i, j), p.GetSupport().GetStrategy(i1, j1)) - p.GetPayoffDeriv(i, p.GetSupport().GetStrategy(i1, j1))); } } if (i == i1) x += 100.0 * (psum - 1.0); } if (p[p.GetSupport().GetStrategy(i1, j1)] < 0.0) { x += p[p.GetSupport().GetStrategy(i1, j1)]; } return 2.0 * x; } // // This function projects a gradient into the plane of the simplex. // (Actually, it works by computing the projection of 'x' onto the // vector perpendicular to the plane, then subtracting to compute the // component parallel to the plane.) // static void Project(Gambit::Vector &x, const Gambit::Array &lengths) { int index = 1; for (int part = 1; part <= lengths.Length(); part++) { double avg = 0.0; int j; for (j = 1; j <= lengths[part]; j++, index++) { avg += x[index]; } avg /= (double) lengths[part]; index -= lengths[part]; for (j = 1; j <= lengths[part]; j++, index++) { x[index] -= avg; } } } bool NFLiapFunc::Gradient(const Gambit::Vector &v, Gambit::Vector &d) const { ((Gambit::Vector &) _p).operator=(v); int i1, j1, ii; for (i1 = 1, ii = 1; i1 <= _nfg->NumPlayers(); i1++) { for (j1 = 1; j1 <= _p.GetSupport().NumStrategies(i1); j1++) { d[ii++] = LiapDerivValue(i1, j1, _p); } } Project(d, _p.GetSupport().NumStrategies()); return true; } double NFLiapFunc::Value(const Gambit::Vector &v) const { _nevals++; ((Gambit::Vector &) _p).operator=(v); return _p.GetLiapValue(); } static void PickRandomProfile(Gambit::MixedStrategyProfile &p) { double sum, tmp; for (int pl = 1; pl <= p.GetGame()->NumPlayers(); pl++) { sum = 0.0; int st; for (st = 1; st < p.GetSupport().NumStrategies(pl); st++) { do tmp = ((double) rand()) / ((double) RAND_MAX); while (tmp + sum > 1.0); p[p.GetSupport().GetStrategy(pl, st)] = tmp; sum += tmp; } p[p.GetSupport().GetStrategy(pl, st)] = 1.0 - sum; } } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const Gambit::MixedStrategyProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << ", " << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } bool ReadProfile(std::istream &p_stream, Gambit::MixedStrategyProfile &p_profile) { for (int i = 1; i <= p_profile.Length(); i++) { if (p_stream.eof() || p_stream.bad()) { return false; } p_stream >> p_profile[i]; if (i < p_profile.Length()) { char comma; p_stream >> comma; } } // Read in the rest of the line and discard std::string foo; std::getline(p_stream, foo); return true; } extern std::string startFile; void SolveStrategic(const Gambit::Game &p_game) { Gambit::List > starts; if (startFile != "") { std::ifstream startPoints(startFile.c_str()); while (!startPoints.eof() && !startPoints.bad()) { Gambit::MixedStrategyProfile start(p_game); if (ReadProfile(startPoints, start)) { starts.Append(start); } } } else { // Generate the desired number of points randomly for (int i = 1; i <= m_numTries; i++) { Gambit::MixedStrategyProfile start(p_game); PickRandomProfile(start); starts.Append(start); } } static const double ALPHA = .00000001; for (int i = 1; i <= starts.Length(); i++) { Gambit::MixedStrategyProfile p(starts[i]); if (verbose) { PrintProfile(std::cout, "start", p); } NFLiapFunc F(p.GetGame(), p); // if starting vector not interior, perturb it towards centroid int kk; for (kk = 1; kk <= p.Length() && p[kk] > ALPHA; kk++); if (kk <= p.Length()) { Gambit::MixedStrategyProfile centroid(p.GetSupport()); for (int k = 1; k <= p.Length(); k++) { p[k] = centroid[k] * ALPHA + p[k] * (1.0-ALPHA); } } gConjugatePR minimizer(p.Length()); Gambit::Vector gradient(p.Length()), dx(p.Length()); double fval; minimizer.Set(F, p, fval, gradient, .01, .0001); try { for (int iter = 1; iter <= m_maxitsN; iter++) { if (!minimizer.Iterate(F, p, fval, gradient, dx)) { break; } if (sqrt(gradient.NormSquared()) < .001) { PrintProfile(std::cout, "NE", p); break; } } if (verbose && sqrt(gradient.NormSquared()) >= .001) { PrintProfile(std::cout, "end", p); } } catch (gFuncMinException &) { } } } gambit-0.2010.09.01/src/tools/logit/0000777000076500007650000000000011441457125013575 500000000000000gambit-0.2010.09.01/src/tools/logit/efglogit.cc0000644000076500007650000002175711435216102015623 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/logit/efglogit.cc // Computation of agent quantal response equilibrium correspondence for // extensive games. // // 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 #include #include #include "logbehav.imp" using namespace Gambit; #include "efglogit.h" //------------------------------------------------------------------------------ // Classes representing equations //------------------------------------------------------------------------------ // // This abstract base class represents one of the defining equations of the system. // class Equation { public: virtual ~Equation() { } virtual double Value(const LogBehavProfile &p_point, double p_lambda) = 0; virtual void Gradient(const LogBehavProfile &p_point, double p_lambda, Vector &p_gradient) = 0; }; // // This class represents the equation that the probabilities of actions // in information set (pl,iset) sums to one // class SumToOneEquation : public Equation { private: Game m_game; int m_pl, m_iset; GameInfoset m_infoset; public: SumToOneEquation(Game p_game, int p_player, int p_infoset) : m_game(p_game), m_pl(p_player), m_iset(p_infoset), m_infoset(p_game->GetPlayer(p_player)->GetInfoset(p_infoset)) { } double Value(const LogBehavProfile &p_profile, double p_lambda); void Gradient(const LogBehavProfile &p_profile, double p_lambda, Vector &p_gradient); }; double SumToOneEquation::Value(const LogBehavProfile &p_profile, double p_lambda) { double value = -1.0; for (int act = 1; act <= m_infoset->NumActions(); act++) { value += p_profile.GetProb(m_pl, m_iset, act); } return value; } void SumToOneEquation::Gradient(const LogBehavProfile &p_profile, double p_lambda, Vector &p_gradient) { int i = 1; for (int pl = 1; pl <= m_game->NumPlayers(); pl++) { GamePlayer player = m_game->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); for (int act = 1; act <= infoset->NumActions(); act++, i++) { if (pl == m_pl && iset == m_iset) { p_gradient[i] = p_profile.GetProb(pl, iset, act); } else { p_gradient[i] = 0.0; } } } } // Derivative wrt lambda is zero p_gradient[i] = 0.0; } // // This class represents the equation relating the probability of // playing action (pl,iset,act) to the probability of playing action // (pl,iset,1) // class RatioEquation : public Equation { private: Game m_game; int m_pl, m_iset, m_act; GameInfoset m_infoset; public: RatioEquation(Game p_game, int p_player, int p_infoset, int p_action) : m_game(p_game), m_pl(p_player), m_iset(p_infoset), m_act(p_action), m_infoset(p_game->GetPlayer(p_player)->GetInfoset(p_infoset)) { } double Value(const LogBehavProfile &p_profile, double p_lambda); void Gradient(const LogBehavProfile &p_profile, double p_lambda, Vector &p_gradient); }; double RatioEquation::Value(const LogBehavProfile &p_profile, double p_lambda) { return (p_profile.GetLogProb(m_pl, m_iset, m_act) - p_profile.GetLogProb(m_pl, m_iset, 1) - p_lambda * (p_profile.GetActionValue(m_infoset->GetAction(m_act)) - p_profile.GetActionValue(m_infoset->GetAction(1)))); } void RatioEquation::Gradient(const LogBehavProfile &p_profile, double p_lambda, Vector &p_gradient) { int i = 1; for (int pl = 1; pl <= m_game->NumPlayers(); pl++) { GamePlayer player = m_game->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); for (int act = 1; act <= infoset->NumActions(); act++, i++) { if (infoset == m_infoset) { if (act == 1) { p_gradient[i] = -1.0; } else if (act == m_act) { p_gradient[i] = 1.0; } else { p_gradient[i] = 0.0; } } else { // infoset1 != infoset2 p_gradient[i] = -p_lambda * (p_profile.DiffActionValue(m_infoset->GetAction(m_act), infoset->GetAction(act)) - p_profile.DiffActionValue(m_infoset->GetAction(1), infoset->GetAction(act))); } } } } p_gradient[i] = (p_profile.GetActionValue(m_infoset->GetAction(1)) - p_profile.GetActionValue(m_infoset->GetAction(m_act))); } //------------------------------------------------------------------------------ // AgentQREPathTracer: Lifecycle //------------------------------------------------------------------------------ AgentQREPathTracer::AgentQREPathTracer(const MixedBehavProfile &p_start) : m_start(p_start), m_fullGraph(true), m_decimals(6) { SetTargetParam(-1.0); for (int pl = 1; pl <= p_start.GetGame()->NumPlayers(); pl++) { GamePlayer player = p_start.GetGame()->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { m_equations.Append(new SumToOneEquation(p_start.GetGame(), pl, iset)); for (int act = 2; act <= player->GetInfoset(iset)->NumActions(); act++) { m_equations.Append(new RatioEquation(p_start.GetGame(), pl, iset, act)); } } } } AgentQREPathTracer::~AgentQREPathTracer() { for (int i = 1; i <= m_equations.Length(); i++) { delete m_equations[i]; } } //------------------------------------------------------------------------------ // AgentQREPathTracer: Wrapper to the tracing engine //------------------------------------------------------------------------------ void AgentQREPathTracer::TraceAgentPath(const MixedBehavProfile &p_start, double p_startLambda, double p_maxLambda, double p_omega) { Vector x(p_start.Length() + 1); for (int i = 1; i <= p_start.Length(); i++) { x[i] = log(p_start[i]); } x[x.Length()] = p_startLambda; TracePath(x, p_maxLambda, p_omega); } //------------------------------------------------------------------------------ // AgentQREPathTracer: Providing virtual functions //------------------------------------------------------------------------------ double AgentQREPathTracer::Criterion(const Vector &p_point, const Vector &p_tangent) { if (GetTargetParam() > 0.0) { return p_point[p_point.Length()] - GetTargetParam(); } else { return PathTracer::Criterion(p_point, p_tangent); } } void AgentQREPathTracer::GetLHS(const Vector &p_point, Vector &p_lhs) { Game game = m_start.GetGame(); LogBehavProfile profile(game); for (int i = 1; i <= profile.Length(); i++) { profile.SetLogProb(i, p_point[i]); } double lambda = p_point[p_point.Length()]; for (int i = 1; i <= p_lhs.Length(); i++) { p_lhs[i] = m_equations[i]->Value(profile, lambda); } } void AgentQREPathTracer::GetJacobian(const Vector &p_point, Matrix &p_matrix) { Game game = m_start.GetGame(); LogBehavProfile profile(game); for (int i = 1; i <= profile.Length(); i++) { profile.SetLogProb(i, p_point[i]); } double lambda = p_point[p_point.Length()]; for (int i = 1; i <= m_equations.Length(); i++) { Vector column(p_point.Length()); m_equations[i]->Gradient(profile, lambda, column); p_matrix.SetColumn(i, column); } } //---------------------------------------------------------------------------- // AgentQREPathTracer: Outputting profiles //---------------------------------------------------------------------------- void AgentQREPathTracer::PrintProfile(std::ostream &p_stream, const Vector &x, bool p_isTerminal) { p_stream.setf(std::ios::fixed); // By convention, we output lambda first if (!p_isTerminal) { p_stream << std::setprecision(m_decimals) << x[x.Length()]; } else { p_stream << "NE"; } p_stream.unsetf(std::ios::fixed); for (int i = 1; i < x.Length(); i++) { p_stream << "," << std::setprecision(m_decimals) << exp(x[i]); } p_stream << std::endl; } void AgentQREPathTracer::OnStep(const Vector &x, bool p_isTerminal = false) { if ((m_fullGraph && !p_isTerminal) || (!m_fullGraph && p_isTerminal)) { PrintProfile(std::cout, x, p_isTerminal); } } gambit-0.2010.09.01/src/tools/logit/efglogit.h0000644000076500007650000000430111435216102015447 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/logit/efglogit.h // Computation of agent quantal response equilibrium correspondence for // extensive games. // // 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 EFGLOGIT_H #define EFGLOGIT_H #include "path.h" class Equation; class AgentQREPathTracer : public PathTracer { public: AgentQREPathTracer(const MixedBehavProfile &p_start); virtual ~AgentQREPathTracer(); void TraceAgentPath(const MixedBehavProfile &p_start, double p_startLambda, double p_maxLambda, double p_omega); void SetFullGraph(bool p_fullGraph) { m_fullGraph = p_fullGraph; } bool GetFullGraph(void) const { return m_fullGraph; } void SetDecimals(int p_decimals) { m_decimals = p_decimals; } int GetDecimals(void) const { return m_decimals; } protected: virtual void OnStep(const Vector &, bool); virtual double Criterion(const Vector &, const Vector &); // Compute the LHS of the system of equations at the specified point. virtual void GetLHS(const Vector &p_point, Vector &p_lhs); // Compute the Jacobian matrix at the specified point. virtual void GetJacobian(const Vector &p_point, Matrix &p_matrix); private: MixedBehavProfile m_start; Array m_equations; bool m_fullGraph; int m_decimals; void PrintProfile(std::ostream &p_stream, const Vector &x, bool p_isTerminal); }; #endif // EFGLOGIT_H gambit-0.2010.09.01/src/tools/logit/logbehav.h0000644000076500007650000001645011435216102015446 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/logit/logbehav.h // Behavior strategy profile where action probabilities are represented using // logarithms. // // 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 LOGBEHAV_H #define LOGBEHAV_H using namespace Gambit; /// /// This is a modified behavior profile class used in the tracing procedure. /// It assumes that all probabilities are positive; therefore, the log /// of the probability is well-defined. Because of this, the realization /// probability for any node can be computed by taking the sum of the log /// probabilities of the actions leading up to it, and then exponentiating /// the sum. /// /// This means that beliefs can be computed accurately even for information /// sets for which the information set realization probability is going /// to zero. In computing beliefs, for each information set, we find the /// member reached with maximum probability. Observe that it must be that /// this node's realization probability divided by the information set's /// realization probability must be bounded away from zero. Beliefs are /// then computed by subtracting the other nodes' log-realization probability /// from this "leading" node's log-realization probability, and then /// exponentiating the result. /// /// This procedure is significant for this application because it is /// necessary to accurately compute beliefs for information sets whose /// realization probabilities are going to zero, so as to be able to /// get a good approximation to the limiting sequential equilibrium. /// template class LogBehavProfile : private DVector { protected: BehavSupport m_support; DVector m_logProbs; mutable bool m_cacheValid; // structures for storing cached data: nodes mutable Vector m_realizProbs, m_logRealizProbs; mutable Vector m_beliefs; mutable Matrix m_nodeValues; // structures for storing cached data: information sets mutable PVector m_infosetValues; // structures for storing cached data: actions mutable DVector m_actionValues; // aka conditional payoffs mutable DVector m_gripe; const T &ActionValue(const GameAction &act) const { return m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->GetNumber()); } T &ActionValue(const GameAction &act) { return m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->GetNumber()); } /// @name Auxiliary functions for computation of interesting values //@{ void GetPayoff(GameNodeRep *, const T &, int, T &) const; void ComputeSolutionDataPass2(const GameNode &node) const; void ComputeSolutionDataPass1(const GameNode &node) const; void ComputeSolutionData(void) const; //@} public: /// @name Lifecycle //@{ LogBehavProfile(const BehavSupport &); LogBehavProfile(const LogBehavProfile &); ~LogBehavProfile() { } LogBehavProfile &operator=(const LogBehavProfile &); LogBehavProfile &operator=(const Vector &p) { Invalidate(); Vector::operator=(p); return *this;} LogBehavProfile &operator=(const T &x) { Invalidate(); DVector::operator=(x); return *this; } //@} /// @name Operator overloading //@{ bool operator==(const LogBehavProfile &) const; bool operator!=(const LogBehavProfile &x) const { return !(*this == x); } bool operator==(const DVector &x) const { return DVector::operator==(x); } bool operator!=(const DVector &x) const { return DVector::operator!=(x); } const T &GetProb(const GameAction &p_action) const { return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), p_action->GetInfoset()->GetNumber(), m_support.GetIndex(p_action)); } const T &GetProb(int a) const { return Array::operator[](a); } const T &GetLogProb(int a) const { return m_logProbs[a]; } T GetLogProb(const GameAction &p_action) const { if (p_action->GetInfoset()->GetPlayer()->GetNumber() == 0) { GameInfoset infoset = p_action->GetInfoset(); return log(infoset->GetActionProb(p_action->GetNumber())); } else { return m_logProbs(p_action->GetInfoset()->GetPlayer()->GetNumber(), p_action->GetInfoset()->GetNumber(), m_support.GetIndex(p_action)); } } const T &GetLogProb(int a, int b, int c) const { return m_logProbs(a, b, c); } const T &GetProb(int a, int b, int c) const { return DVector::operator()(a, b, c); } void SetLogProb(int a, const T &p_value) { Invalidate(); m_logProbs[a] = p_value; Array::operator[](a) = exp(p_value); } void SetProb(int a, const T &p_value) { Invalidate(); Array::operator[](a) = p_value; m_logProbs[a] = log(p_value); } LogBehavProfile &operator+=(const LogBehavProfile &x) { Invalidate(); DVector::operator+=(x); return *this; } LogBehavProfile &operator+=(const DVector &x) { Invalidate(); DVector::operator+=(x); return *this; } LogBehavProfile &operator-=(const LogBehavProfile &x) { Invalidate(); DVector::operator-=(x); return *this; } LogBehavProfile &operator*=(const T &x) { Invalidate(); DVector::operator*=(x); return *this; } //@} /// @name Initialization, validation //@{ /// Force recomputation of stored quantities void Invalidate(void) const { m_cacheValid = false; } /// Set the profile to the centroid void Centroid(void); //@} /// @name General data access //@{ int Length(void) const { return Array::Length(); } Game GetGame(void) const { return m_support.GetGame(); } const BehavSupport &GetSupport(void) const { return m_support; } //@} /// @name Computation of interesting quantities //@{ T GetPayoff(int p_player) const; T GetLiapValue(bool p_definedOnly = false) const; const T &GetRealizProb(const GameNode &node) const; const T &GetBeliefProb(const GameNode &node) const; Vector GetNodeValue(const GameNode &node) const; T GetInfosetProb(const GameInfoset &iset) const; const T &GetInfosetValue(const GameInfoset &iset) const; T GetActionProb(const GameAction &act) const; T GetLogActionProb(const GameAction &) const; const T &GetActionValue(const GameAction &act) const; const T &GetRegret(const GameAction &act) const; T DiffActionValue(const GameAction &action, const GameAction &oppAction) const; T DiffRealizProb(const GameNode &node, const GameAction &oppAction) const; T DiffNodeValue(const GameNode &node, const GamePlayer &player, const GameAction &oppAction) const; //@} }; #endif // LOGBEHAV_H gambit-0.2010.09.01/src/tools/logit/logbehav.imp0000644000076500007650000004416211435216102016005 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/logit/logbehav.imp // Behavior strategy profile where action probabilities are represented using // logarithms. // // 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 "logbehav.h" //======================================================================== // LogBehavProfile: Lifecycle //======================================================================== template LogBehavProfile::LogBehavProfile(const LogBehavProfile &p_profile) : DVector(p_profile), m_logProbs(p_profile.m_logProbs), m_support(p_profile.m_support), m_cacheValid(false), m_realizProbs(p_profile.m_realizProbs), m_logRealizProbs(p_profile.m_logRealizProbs), m_beliefs(p_profile.m_beliefs), m_nodeValues(p_profile.m_nodeValues), m_infosetValues(p_profile.m_infosetValues), m_actionValues(p_profile.m_actionValues), m_gripe(p_profile.m_gripe) { m_realizProbs = (T) 0.0; m_logRealizProbs = (T) 0.0; m_beliefs = (T) 0.0; m_nodeValues = (T) 0.0; m_infosetValues = (T) 0.0; m_actionValues = (T) 0.0; m_gripe = (T) 0.0; } template LogBehavProfile::LogBehavProfile(const BehavSupport &p_support) : DVector(p_support.NumActions()), m_support(p_support), m_logProbs(p_support.NumActions()), m_cacheValid(false), m_realizProbs(p_support.GetGame()->NumNodes()), m_logRealizProbs(p_support.GetGame()->NumNodes()), m_beliefs(p_support.GetGame()->NumNodes()), m_nodeValues(p_support.GetGame()->NumNodes(), p_support.GetGame()->NumPlayers()), m_infosetValues(p_support.GetGame()->NumInfosets()), m_actionValues(p_support.GetGame()->NumActions()), m_gripe(p_support.GetGame()->NumActions()) { m_realizProbs = (T) 0.0; m_logRealizProbs = (T) 0.0; m_beliefs = (T) 0.0; m_nodeValues = (T) 0.0; m_infosetValues = (T) 0.0; m_actionValues = (T) 0.0; m_gripe = (T) 0.0; Centroid(); } template LogBehavProfile &LogBehavProfile::operator=(const LogBehavProfile &p_profile) { if (this != &p_profile && m_support == p_profile.m_support) { Invalidate(); DVector::operator=(p_profile); m_support = p_profile.m_support; } return *this; } //======================================================================== // LogBehavProfile: Operator overloading //======================================================================== template bool LogBehavProfile::operator==(const LogBehavProfile &p_profile) const { return (m_support == p_profile.m_support && (DVector &) *this == (DVector &) p_profile); } //======================================================================== // LogBehavProfile: General data access //======================================================================== template void LogBehavProfile::Centroid(void) { T center; for (int pl = 1; pl <= this->dvlen.Length(); pl++) for (int iset = 1; iset <= this->dvlen[pl]; iset++) if (m_support.NumActions(pl,iset) > 0) { center = ((T) 1 / (T) m_support.NumActions(pl, iset)); int act; for (act = 1; act <= this->svlen[this->dvidx[pl] + iset - 1]; act++) { this->dvptr[pl][iset][act] = center; m_logProbs(pl, iset, act) = log(center); } } } //======================================================================== // LogBehavProfile: Interesting quantities //======================================================================== // // The p_definedOnly parameter allows us to compute the LiapValue for profiles // which are incomplete. Some methods -- such as the sequence form // methods -- return all zeroes for all action probabilities at // information sets sufficiently far off the equilibrium path. // In such cases, *any* completion is Nash. // // This is really a hack because we don't have a proper way yet of // indicating this. // template T LogBehavProfile::GetLiapValue(bool p_definedOnly) const { static const T BIG1 = (T) 10000; static const T BIG2 = (T) 100; T x, result = ((T) 0), avg, sum; // HACK: force it to recompute data. FIX THIS. m_cacheValid = false; ComputeSolutionData(); for (int i = 1; i <= m_support.GetGame()->NumPlayers(); i++) { for (int iset = 1; iset <= m_support.GetGame()->GetPlayer(i)->NumInfosets(); iset++) { avg = sum = (T)0; for (int act = 1; act <= m_support.NumActions(i, iset); act++) { GameActionRep *action = m_support.GetAction(i, iset, act); x = GetActionProb(action); avg += x * m_actionValues(action->GetInfoset()->GetPlayer()->GetNumber(), action->GetInfoset()->GetNumber(), action->GetNumber()); sum += x; if (x > (T)0) x = (T)0; result += BIG1 * x * x; // add penalty for neg probabilities } for (int act = 1; act <= m_support.NumActions(i, iset); act++) { x = ActionValue(m_support.GetAction(i, iset, act)) - avg; if (x < (T)0) x = (T)0; result += x * x; // add penalty if not best response } x = sum - (T)1; if (!p_definedOnly || sum >= (T) 1.0e-4) { result += BIG2 * x * x; // add penalty for sum not equal to 1 } } } return result; } template const T &LogBehavProfile::GetRealizProb(const GameNode &node) const { ComputeSolutionData(); return m_realizProbs[node->GetNumber()]; } template const T &LogBehavProfile::GetBeliefProb(const GameNode &node) const { ComputeSolutionData(); return m_beliefs[node->GetNumber()]; } template Vector LogBehavProfile::GetNodeValue(const GameNode &node) const { ComputeSolutionData(); return m_nodeValues.Row(node->number); } template T LogBehavProfile::GetInfosetProb(const GameInfoset &iset) const { ComputeSolutionData(); T prob = (T) 0; for (int i = 1; i <= iset->NumMembers(); i++) { prob += m_realizProbs[iset->GetMember(i)->GetNumber()]; } return prob; } template const T &LogBehavProfile::GetInfosetValue(const GameInfoset &iset) const { ComputeSolutionData(); return m_infosetValues(iset->GetPlayer()->GetNumber(), iset->GetNumber()); } template T LogBehavProfile::GetActionProb(const GameAction &action) const { if (action->GetInfoset()->GetPlayer()->IsChance()) { GameInfosetRep *infoset = action->GetInfoset(); return infoset->GetActionProb(action->GetNumber()); } else if (!m_support.Contains(action)) { return (T) 0.0; } else { return (*this)(action->GetInfoset()->GetPlayer()->GetNumber(), action->GetInfoset()->GetNumber(), m_support.GetIndex(action)); } } template T LogBehavProfile::GetLogActionProb(const GameAction &action) const { if (action->GetInfoset()->GetPlayer()->IsChance()) { GameInfosetRep *infoset = action->GetInfoset(); return log(infoset->GetActionProb(action->GetNumber())); } else { return m_logProbs(action->GetInfoset()->GetPlayer()->GetNumber(), action->GetInfoset()->GetNumber(), m_support.GetIndex(action)); } } template const T &LogBehavProfile::GetActionValue(const GameAction &act) const { ComputeSolutionData(); return m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->GetNumber()); } template const T &LogBehavProfile::GetRegret(const GameAction &act) const { ComputeSolutionData(); return m_gripe(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->GetNumber()); } template void LogBehavProfile::GetPayoff(GameNodeRep *node, const T &prob, int player, T &value) const { if (node->outcome) { value += prob * node->outcome->GetPayoff(player); } if (node->children.Length()) { int pl = node->infoset->m_player->m_number, iset = node->infoset->m_number; if (pl == 0) { // chance player for (int act = 1; act <= node->NumChildren(); act++) { GetPayoff(node->GetChild(act), prob * node->infoset->GetActionProb(act), player, value); } } else { for (int act = 1; act <= m_support.NumActions(pl, iset); act++) { GameActionRep *action = m_support.GetAction(pl, iset, act); GetPayoff(node->GetChild(action->GetNumber()), prob * GetActionProb(action), player, value); } } } } template T LogBehavProfile::GetPayoff(int player) const { T value = (T) 0; GetPayoff(m_support.GetGame()->GetRoot(), (T) 1, player, value); return value; } // // The following routines compute the derivatives of quantities as // the probability of the action 'p_oppAction' is changed. // See Turocy (2001), "Computing the Quantal Response Equilibrium // Correspondence" for details. // These assume that the profile is interior (totally mixed), // and that the game is of perfect recall // template T LogBehavProfile::DiffRealizProb(const GameNode &p_node, const GameAction &p_oppAction) const { ComputeSolutionData(); T deriv = (T) 0.0; bool isPrec = false; GameNode node = p_node; while (node->GetParent()) { GameAction prevAction = node->GetPriorAction(); if (prevAction != p_oppAction) { if (prevAction->GetInfoset() != p_oppAction->GetInfoset()) { deriv += GetLogProb(prevAction); } else { // Same information set, different action -- return a bogus value deriv -= log(1.0 / (double) (p_oppAction->GetInfoset()->NumActions() - 1)); } } else { isPrec = true; } node = node->GetParent(); } return deriv; } GameAction GetPrecedingAction(const GameNode &p_node, const GameInfoset &p_infoset) { GameNode node = p_node; while (node->GetParent()) { GameAction prevAction = node->GetPriorAction(); if (prevAction->GetInfoset() == p_infoset) { return prevAction; } node = node->GetParent(); } return 0; } template T LogBehavProfile::DiffActionValue(const GameAction &p_action, const GameAction &p_oppAction) const { ComputeSolutionData(); T deriv = (T) 0; GameInfoset infoset = p_action->GetInfoset(); GamePlayer player = p_action->GetInfoset()->GetPlayer(); // derivs stores the ratio of the derivative of the realization probability // for each node, divided by the realization probability of the infoset, // times the probability with which p_oppAction is played Array derivs(infoset->NumMembers()); for (int i = 1; i <= infoset->NumMembers(); i++) { derivs[i] = 0.0; GameAction act = GetPrecedingAction(infoset->GetMember(i), p_oppAction->GetInfoset()); if (act == p_oppAction) { derivs[i] = m_beliefs[infoset->GetMember(i)->GetNumber()]; } else if (act != 0) { /* T factor = 0.0; for (int j = 1; j <= infoset->NumMembers(); j++) { factor += exp(m_logRealizProbs[infoset->GetMember(j)->GetNumber()] - m_logRealizProbs[infoset->GetMember(i)->GetNumber()] + GetLogProb(act) - GetLogProb(p_oppAction)); } derivs[i] = -1.0 / factor / (double) (p_oppAction->GetInfoset()->NumActions() - 1); */ } } for (int i = 1; i <= infoset->NumMembers(); i++) { GameNode member = infoset->GetMember(i); GameNode child = member->GetChild(p_action->GetNumber()); deriv += derivs[i] * m_nodeValues(child->GetNumber(), player->GetNumber()); deriv -= derivs[i] * GetActionValue(p_action); deriv += GetProb(p_oppAction) * m_beliefs[member->GetNumber()] * DiffNodeValue(child, player, p_oppAction); } return deriv; } template T LogBehavProfile::DiffNodeValue(const GameNode &p_node, const GamePlayer &p_player, const GameAction &p_oppAction) const { ComputeSolutionData(); if (p_node->NumChildren() > 0) { GameInfoset infoset = p_node->GetInfoset(); if (infoset == p_oppAction->GetInfoset()) { // We've encountered the action; since we assume perfect recall, // we won't encounter it again, and the downtree value must // be the same. return m_nodeValues(p_node->GetChild(p_oppAction->GetNumber())->GetNumber(), p_player->GetNumber()); } else { T deriv = (T) 0; for (int act = 1; act <= infoset->NumActions(); act++) { deriv += (DiffNodeValue(p_node->GetChild(act), p_player, p_oppAction) * GetActionProb(infoset->GetAction(act))); } return deriv; } } else { // If we reach a terminal node and haven't encountered p_oppAction, // derivative wrt this path is zero. return (T) 0; //return m_nodeValues(p_node->GetNumber(), p_player->GetNumber()); } } //======================================================================== // LogBehavProfile: Cached profile information //======================================================================== template void LogBehavProfile::ComputeSolutionDataPass2(const GameNode &node) const { if (node->GetOutcome()) { GameOutcome outcome = node->GetOutcome(); for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { m_nodeValues(node->GetNumber(), pl) += outcome->GetPayoff(pl); } } GameInfoset iset = node->GetInfoset(); if (iset) { T infosetProb = (T) 0; for (int i = 1; i <= iset->NumMembers(); i++) { infosetProb += m_realizProbs[iset->GetMember(i)->GetNumber()]; } // push down payoffs from outcomes attached to non-terminal nodes for (int child = 1; child <= node->NumChildren(); child++) { m_nodeValues.SetRow(node->GetChild(child)->GetNumber(), m_nodeValues.Row(node->GetNumber())); } for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { m_nodeValues(node->GetNumber(), pl) = (T) 0; } for (int child = 1; child <= node->NumChildren(); child++) { GameNode childNode = node->GetChild(child); ComputeSolutionDataPass2(childNode); GameAction act = childNode->GetPriorAction(); for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { m_nodeValues(node->GetNumber(), pl) += GetActionProb(act) * m_nodeValues(childNode->GetNumber(), pl); } if (!iset->IsChanceInfoset()) { T &cpay = m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(), act->GetInfoset()->GetNumber(), act->GetNumber()); cpay += m_beliefs[node->GetNumber()] * m_nodeValues(childNode->GetNumber(), iset->GetPlayer()->GetNumber()); } } } } // compute realization probabilities for nodes and isets. template void LogBehavProfile::ComputeSolutionDataPass1(const GameNode &node) const { if (node->GetParent()) { m_realizProbs[node->GetNumber()] = m_realizProbs[node->GetParent()->GetNumber()] * GetActionProb(node->GetPriorAction()); m_logRealizProbs[node->GetNumber()] = m_logRealizProbs[node->GetParent()->GetNumber()] + GetLogActionProb(node->GetPriorAction()); } else { m_realizProbs[node->GetNumber()] = (T) 1; m_logRealizProbs[node->GetNumber()] = (T) 0.0; } if (node->GetInfoset()) { for (int i = 1; i <= node->NumChildren(); i++) { ComputeSolutionDataPass1(node->GetChild(i)); } } } template void LogBehavProfile::ComputeSolutionData(void) const { if (!m_cacheValid) { m_actionValues = (T) 0; m_nodeValues = (T) 0; m_infosetValues = (T) 0; m_gripe = (T) 0; ComputeSolutionDataPass1(m_support.GetGame()->GetRoot()); // This is moved from ComputeSolutionData2 relative to original // behavior profile, to use new-style log-based computation for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { GamePlayer player = m_support.GetGame()->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); int mostLikelyNode = 1; T maxLogProb = m_logRealizProbs[infoset->GetMember(1)->GetNumber()]; for (int i = 2; i <= infoset->NumMembers(); i++) { if (m_logRealizProbs[infoset->GetMember(i)->GetNumber()] > maxLogProb) { mostLikelyNode = i; maxLogProb = m_logRealizProbs[infoset->GetMember(i)->GetNumber()]; } } T total = 0.0; for (int i = 1; i <= infoset->NumMembers(); i++) { total += exp(m_logRealizProbs[infoset->GetMember(i)->GetNumber()] - maxLogProb); } // The belief for the most likely node T mostLikelyBelief = 1.0 / total; for (int i = 1; i <= infoset->NumMembers(); i++) { m_beliefs[infoset->GetMember(i)->GetNumber()] = mostLikelyBelief * exp(m_logRealizProbs[infoset->GetMember(i)->GetNumber()] - maxLogProb); } } } ComputeSolutionDataPass2(m_support.GetGame()->GetRoot()); // At this point, mark the cache as value, so calls to GetInfosetValue() // don't create a loop. m_cacheValid = true; for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { for (int iset = 1; iset <= m_support.GetGame()->NumInfosets()[pl]; iset++) { GameInfoset infoset = m_support.GetGame()->GetPlayer(pl)->GetInfoset(iset); m_infosetValues(infoset->GetPlayer()->GetNumber(), infoset->GetNumber()) = (T) 0; for (int act = 1; act <= infoset->NumActions(); act++) { GameAction action = infoset->GetAction(act); m_infosetValues(infoset->GetPlayer()->GetNumber(), infoset->GetNumber()) += GetActionProb(action) * ActionValue(action); } for (int act = 1; act <= infoset->NumActions(); act++) { GameAction action = infoset->GetAction(act); m_gripe(action->GetInfoset()->GetPlayer()->GetNumber(), action->GetInfoset()->GetNumber(), action->GetNumber()) = (ActionValue(action) - GetInfosetValue(infoset)) * GetInfosetProb(infoset); } } } } } gambit-0.2010.09.01/src/tools/logit/logit.cc0000644000076500007650000001464211435216102015134 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/logit/logit.cc // Command-line driver program for quantal response equilibrium tracing and // maximum likelihood estimation. // // 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 #include #include #include #include "libgambit/libgambit.h" #include "efglogit.h" #include "nfglogit.h" void PrintBanner(std::ostream &p_stream) { p_stream << "Compute a branch of the logit equilibrium correspondence\n"; p_stream << "Gambit version " VERSION ", "; p_stream << "Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "Options:\n"; std::cerr << " -d DECIMALS show equilibria as floating point with DECIMALS digits\n"; std::cerr << " -s STEP initial stepsize (default is .03)\n"; std::cerr << " -a ACCEL maximum acceleration (default is 1.1)\n"; std::cerr << " -m MAXLAMBDA stop when reaching MAXLAMBDA (default is 1000000)\n"; std::cerr << " -l LAMBDA compute QRE at `lambda` accurately\n"; std::cerr << " -L FILE compute maximum likelihood estimates;\n"; std::cerr << " read strategy frequencies from FILE\n"; std::cerr << " -h print this help message\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; std::cerr << " -e print only the terminal equilibrium\n"; std::cerr << " (default is to print the entire branch)\n"; exit(1); } // // Read in a comma-separated values list of observed data values // bool ReadProfile(std::istream &p_stream, Gambit::Array &p_profile) { for (int i = 1; i <= p_profile.Length(); i++) { if (p_stream.eof() || p_stream.bad()) { return false; } p_stream >> p_profile[i]; if (i < p_profile.Length()) { char comma; p_stream >> comma; } } // Read in the rest of the line and discard std::string foo; std::getline(p_stream, foo); return true; } int main(int argc, char *argv[]) { opterr = 0; bool quiet = false, useStrategic = false; double maxLambda = 1000000.0; std::string mleFile = "", startFile = ""; double maxDecel = 1.1; double hStart = 0.03; double targetLambda = -1.0; bool fullGraph = true; int decimals = 6; int c; while ((c = getopt(argc, argv, "d:s:a:m:qehSL:p:l:")) != -1) { switch (c) { case 'q': quiet = true; break; case 'd': decimals = atoi(optarg); break; case 's': hStart = atof(optarg); break; case 'a': maxDecel = atof(optarg); break; case 'm': maxLambda = atof(optarg); break; case 'e': fullGraph = false; break; case 'h': PrintHelp(argv[0]); break; case 'S': useStrategic = true; break; case 'L': mleFile = optarg; break; case 'p': startFile = optarg; break; case 'l': targetLambda = atof(optarg); break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Gambit::Array frequencies; Gambit::Game game = Gambit::ReadGame(std::cin); if (mleFile != "" && (!game->IsTree() || useStrategic)) { frequencies = Gambit::Array(game->MixedProfileLength()); std::ifstream mleData(mleFile.c_str()); ReadProfile(mleData, frequencies); } if (!game->IsTree() || useStrategic) { game->BuildComputedValues(); if (startFile == "") { Gambit::MixedStrategyProfile start(game); StrategicQREPathTracer tracer(start); tracer.SetMaxDecel(maxDecel); tracer.SetStepsize(hStart); tracer.SetFullGraph(fullGraph); tracer.SetTargetParam(targetLambda); tracer.SetDecimals(decimals); tracer.SetMLEFrequencies(frequencies); tracer.TraceStrategicPath(start, 0.0, maxLambda, 1.0); } else { Gambit::Array profile(game->MixedProfileLength() + 1); std::ifstream startData(startFile.c_str()); ReadProfile(startData, profile); Gambit::MixedStrategyProfile start(game); for (int i = 1; i <= start.Length(); i++) { start[i] = profile[i+1]; } StrategicQREPathTracer tracer1(start); tracer1.SetMaxDecel(maxDecel); tracer1.SetStepsize(hStart); tracer1.SetFullGraph(fullGraph); tracer1.SetTargetParam(targetLambda); tracer1.SetDecimals(decimals); tracer1.TraceStrategicPath(start, profile[1], maxLambda, 1.0); std::cout << std::endl; StrategicQREPathTracer tracer2(start); tracer2.SetMaxDecel(maxDecel); tracer2.SetStepsize(hStart); tracer2.SetFullGraph(fullGraph); tracer2.SetTargetParam(targetLambda); tracer2.SetDecimals(decimals); tracer2.TraceStrategicPath(start, profile[1], maxLambda, -1.0); } } else { MixedBehavProfile start(game); AgentQREPathTracer tracer(start); tracer.SetMaxDecel(maxDecel); tracer.SetStepsize(hStart); tracer.SetFullGraph(fullGraph); tracer.SetTargetParam(targetLambda); tracer.SetDecimals(decimals); tracer.TraceAgentPath(start, 0.0, maxLambda, 1.0); } return 0; } catch (Gambit::InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } } gambit-0.2010.09.01/src/tools/logit/nfgdyn.cc0000644000076500007650000001460211435216102015277 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/logit/nfgdyn.cc // Computation of stable quantal response equilibria via perturbed // best-reply dynamics // // 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 #include #include #include #include #include #include "libgambit/libgambit.h" // // This program attempts to identify the quantal response equilibria // which are stable under the perturbed best-reply dynamics for a given // value of the logit precision parameter 'lambda'. // // The program takes a normal form game on standard input. The following // command-line parameters modify its operation: // // -f #: Number of decimal places to display in outputting profiles // (Default is 6) // -n #: Number of random starting points to generate (default is 100) // -l #: Value of lambda (required) // -t #: Tolerance for stopping criterion (parameter is exponent to // 10^(-k), default is 6). // int g_numDecimals = 6; void LogitBR(const Gambit::MixedStrategyProfile &p_profile, double p_lambda, Gambit::MixedStrategyProfile &p_br) { Gambit::Game nfg = p_profile.GetGame(); for (int pl = 1; pl <= nfg->NumPlayers(); pl++) { Gambit::Array lval(nfg->GetPlayer(pl)->NumStrategies()); double sum = 0.0; for (int st = 1; st <= nfg->GetPlayer(pl)->NumStrategies(); st++) { lval[st] = exp(p_lambda * p_profile.GetStrategyValue(nfg->GetPlayer(pl)->GetStrategy(st))); sum += lval[st]; } for (int st = 1; st <= nfg->GetPlayer(pl)->NumStrategies(); st++) { p_br[nfg->GetPlayer(pl)->GetStrategy(st)] = lval[st] / sum; } } } void Randomize(Gambit::MixedStrategyProfile &p_profile) { Gambit::Game nfg = p_profile.GetGame(); ((Gambit::Vector &) p_profile) = 0.0; for (int pl = 1; pl <= nfg->NumPlayers(); pl++) { double sum = 0.0; for (int st = 1; st < nfg->GetPlayer(pl)->NumStrategies(); st++) { p_profile[nfg->GetPlayer(pl)->GetStrategy(st)] = (1.0 - sum) * (double) rand() / (double) RAND_MAX; sum += p_profile[nfg->GetPlayer(pl)->GetStrategy(st)]; } p_profile[nfg->GetPlayer(pl)->GetStrategy(nfg->GetPlayer(pl)->NumStrategies())] = 1.0 - sum; } } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const Gambit::MixedStrategyProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << "," << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } double Distance(const Gambit::MixedStrategyProfile &a, const Gambit::MixedStrategyProfile &b) { double dist = 0.0; for (int i = 1; i <= a.Length(); i++) { if (fabs(a[i] - b[i]) > dist) { dist = fabs(a[i] - b[i]); } } return dist; } bool ReadProfile(std::istream &p_stream, Gambit::Array &p_profile) { for (int i = 1; i <= p_profile.Length(); i++) { if (p_stream.eof() || p_stream.bad()) { return false; } p_stream >> p_profile[i]; if (i < p_profile.Length()) { char comma; p_stream >> comma; } } // Read in the rest of the line and discard std::string foo; std::getline(p_stream, foo); return true; } int main(int argc, char *argv[]) { int stopAfter = 100; double lambda; bool lambdaSpec = false; double tol = 1.0e-6; std::string startFile = ""; int c; while ((c = getopt(argc, argv, "f:n:l:t:p:")) != -1) { switch (c) { case 'f': g_numDecimals = atoi(optarg); break; case 'n': stopAfter = atoi(optarg); break; case 'l': lambda = atof(optarg); lambdaSpec = true; break; case 't': tol = pow(10.0, (double) -atoi(optarg)); break; case 'p': startFile = optarg; break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!lambdaSpec) { std::cerr << argv[0] << ": Required parameter -l missing.\n"; exit(1); } Gambit::Game nfg; try { nfg = Gambit::ReadGame(std::cin); } catch (...) { return 1; } if (startFile == "") { for (int i = 1; i <= stopAfter; i++) { Gambit::MixedStrategyProfile profile(nfg); Randomize(profile); PrintProfile(std::cout, "start", profile); Gambit::MixedStrategyProfile br(nfg); double c_delta = .001; do { LogitBR(profile, lambda, br); (Gambit::Vector &) profile = (((Gambit::Vector &) profile) * (1.0 - c_delta) + ((Gambit::Vector &) br) * c_delta); } while (Distance(profile, br) > tol); PrintProfile(std::cout, "QRE", profile); } } else { Gambit::Array x(nfg->MixedProfileLength() + 1); std::ifstream startData(startFile.c_str()); ReadProfile(startData, x); Gambit::MixedStrategyProfile profile(nfg); for (int i = 1; i <= profile.Length(); i++) { profile[i] = x[i+1]; if (profile[i] == 0.0) { profile[i] = 0.0001; } } lambda = x[1]; double c_delta = .001; Gambit::MixedStrategyProfile br(nfg); do { PrintProfile(std::cout, "step", profile); LogitBR(profile, lambda, br); (Gambit::Vector &) profile = (((Gambit::Vector &) profile) * (1.0 - c_delta) + ((Gambit::Vector &) br) * c_delta); } while (Distance(profile, br) > tol); PrintProfile(std::cout, "QRE", profile); } } gambit-0.2010.09.01/src/tools/logit/nfglogit.cc0000644000076500007650000001624011435216102015623 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/logit/nfglogit.cc // Computation of quantal response equilibrium correspondence for // normal form games. // // 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 #include #include #include using namespace Gambit; #include "nfglogit.h" //---------------------------------------------------------------------------- // StrategicQREPathTracer: Wrapper to the tracing engine //---------------------------------------------------------------------------- void StrategicQREPathTracer::TraceStrategicPath(const MixedStrategyProfile &p_start, double p_startLambda, double p_maxLambda, double p_omega) { Vector x(p_start.Length() + 1); for (int i = 1; i <= p_start.Length(); i++) { x[i] = log(p_start[i]); } x[x.Length()] = p_startLambda; TracePath(x, p_maxLambda, p_omega); } //---------------------------------------------------------------------------- // StrategicQREPathTracer: Providing virtual functions //---------------------------------------------------------------------------- double StrategicQREPathTracer::Criterion(const Vector &p_point, const Vector &p_tangent) { if (IsMLEMode()) { double logL = 0.0; for (int i = 1; i <= m_frequencies.Length(); i++) { logL += m_frequencies[i] * p_tangent[i]; } return logL; } else if (GetTargetParam() > 0.0) { return p_point[p_point.Length()] - GetTargetParam(); } else { return PathTracer::Criterion(p_point, p_tangent); } } void StrategicQREPathTracer::GetLHS(const Vector &p_point, Vector &p_lhs) { const StrategySupport &support = m_start.GetSupport(); MixedStrategyProfile profile(support), logprofile(support); for (int i = 1; i <= profile.Length(); i++) { profile[i] = exp(p_point[i]); logprofile[i] = p_point[i]; } double lambda = p_point[p_point.Length()]; p_lhs = 0.0; int rowno = 0; for (int pl = 1; pl <= support.GetGame()->NumPlayers(); pl++) { GamePlayer player = support.GetGame()->GetPlayer(pl); for (int st = 1; st <= player->NumStrategies(); st++) { rowno++; if (st == 1) { // sum-to-one equation p_lhs[rowno] = -1.0; for (int j = 1; j <= player->NumStrategies(); j++) { p_lhs[rowno] += profile[player->GetStrategy(j)]; } } else { p_lhs[rowno] = (logprofile[player->GetStrategy(st)] - logprofile[player->GetStrategy(1)] - lambda * (profile.GetStrategyValue(player->GetStrategy(st)) - profile.GetStrategyValue(player->GetStrategy(1)))); } } } } void StrategicQREPathTracer::GetJacobian(const Vector &p_point, Matrix &p_matrix) { const StrategySupport &support = m_start.GetSupport(); MixedStrategyProfile profile(support), logprofile(support); for (int i = 1; i <= profile.Length(); i++) { profile[i] = exp(p_point[i]); logprofile[i] = p_point[i]; } double lambda = p_point[p_point.Length()]; p_matrix = 0.0; int rowno = 0; for (int i = 1; i <= support.GetGame()->NumPlayers(); i++) { GamePlayer player = support.GetGame()->GetPlayer(i); for (int j = 1; j <= player->NumStrategies(); j++) { rowno++; if (j == 1) { // sum-to-one equation int colno = 0; for (int ell = 1; ell <= support.GetGame()->NumPlayers(); ell++) { GamePlayer player2 = support.GetGame()->GetPlayer(ell); for (int m = 1; m <= player2->NumStrategies(); m++) { colno++; if (i == ell) { p_matrix(colno, rowno) = profile[player2->GetStrategy(m)]; } else { p_matrix(colno, rowno) = 0.0; } } } // Derivative wrt lambda is zero p_matrix(p_matrix.NumRows(), rowno) = 0.0; } else { // This is a ratio equation int colno = 0; for (int ell = 1; ell <= support.GetGame()->NumPlayers(); ell++) { GamePlayer player2 = support.GetGame()->GetPlayer(ell); for (int m = 1; m <= player2->NumStrategies(); m++) { colno++; if (i == ell) { if (m == 1) { // should be m==lead p_matrix(colno, rowno) = -1.0; } else if (m == j) { p_matrix(colno, rowno) = 1.0; } else { p_matrix(colno, rowno) = 0.0; } } else { // 1 == sum-to-one p_matrix(colno, rowno) = -lambda * profile[player2->GetStrategy(m)] * (profile.GetPayoffDeriv(i, support.GetStrategy(i, j), support.GetStrategy(ell, m)) - profile.GetPayoffDeriv(i, support.GetStrategy(i, 1), support.GetStrategy(ell, m))); } } } // column wrt lambda // 1 == sum-to-one p_matrix(p_matrix.NumRows(), rowno) = (profile.GetStrategyValue(support.GetStrategy(i, 1)) - profile.GetStrategyValue(support.GetStrategy(i, j))); } } } } //---------------------------------------------------------------------------- // StrategicQREPathTracer: Maximum likelihood estimation //---------------------------------------------------------------------------- double StrategicQREPathTracer::LogLike(const Array &p_point) { double ret = 0.0; for (int i = 1; i <= m_frequencies.Length(); i++) { ret += m_frequencies[i] * log(p_point[i]); } return ret; } //---------------------------------------------------------------------------- // StrategicQREPathTracer: Outputting profiles //---------------------------------------------------------------------------- void StrategicQREPathTracer::PrintProfile(std::ostream &p_stream, const Vector &x, bool p_isTerminal) { p_stream.setf(std::ios::fixed); // By convention, we output lambda first if (!p_isTerminal) { p_stream << std::setprecision(m_decimals) << x[x.Length()]; } else { p_stream << "NE"; } p_stream.unsetf(std::ios::fixed); for (int i = 1; i < x.Length(); i++) { p_stream << "," << std::setprecision(m_decimals) << exp(x[i]); } if (IsMLEMode()) { MixedStrategyProfile profile(m_start); for (int i = 1; i <= profile.Length(); i++) { profile[i] = exp(x[i]); } p_stream.setf(std::ios::fixed); p_stream << "," << std::setprecision(m_decimals) << LogLike(profile); p_stream.unsetf(std::ios::fixed); } p_stream << std::endl; } void StrategicQREPathTracer::OnStep(const Vector &x, bool p_isTerminal = false) { if ((m_fullGraph && !p_isTerminal) || (!m_fullGraph && p_isTerminal)) { PrintProfile(std::cout, x, p_isTerminal); } } gambit-0.2010.09.01/src/tools/logit/nfglogit.h0000644000076500007650000000512011436505532015471 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: nfglogit.cc // Computation of quantal response equilibrium correspondence for // normal form games. // // 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 NFGLOGIT_H #define NFGLOGIT_H #include "path.h" class StrategicQREPathTracer : public PathTracer { public: StrategicQREPathTracer(const MixedStrategyProfile &p_start) : m_start(p_start), m_fullGraph(true), m_decimals(6) { SetTargetParam(-1.0); } virtual ~StrategicQREPathTracer() { } void TraceStrategicPath(const MixedStrategyProfile &p_start, double p_startLambda, double p_maxLambda, double p_omega); void SetFullGraph(bool p_fullGraph) { m_fullGraph = p_fullGraph; } bool GetFullGraph(void) const { return m_fullGraph; } void SetDecimals(int p_decimals) { m_decimals = p_decimals; } int GetDecimals(void) const { return m_decimals; } void SetMLEFrequencies(const Array &p_frequencies) { m_frequencies = p_frequencies; } const Array &GetMLEFrequencies(void) const { return m_frequencies; } bool IsMLEMode(void) const { return (m_frequencies.Length() > 0); } protected: virtual void OnStep(const Vector &, bool); virtual double Criterion(const Vector &, const Vector &); // Compute the LHS of the system of equations at the specified point. virtual void GetLHS(const Vector &p_point, Vector &p_lhs); // Compute the Jacobian matrix at the specified point. virtual void GetJacobian(const Vector &p_point, Matrix &p_matrix); private: void PrintProfile(std::ostream &, const Vector &, bool); // Used in maximum likelihood estimation double LogLike(const Array &p_point); MixedStrategyProfile m_start; bool m_fullGraph; Array m_frequencies; int m_decimals; }; #endif // NFGLOGIT_H gambit-0.2010.09.01/src/tools/logit/path.cc0000644000076500007650000001411311435216102014743 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/logit/path.cc // Implementation of generic smooth path-following algorithm. // // 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 #include #include using namespace Gambit; #include "path.h" //---------------------------------------------------------------------------- // PathTracer: Auxiliary functions //---------------------------------------------------------------------------- inline double sqr(double x) { return x*x; } static void Givens(Matrix &b, Matrix &q, double &c1, double &c2, int l1, int l2, int l3) { if (fabs(c1) + fabs(c2) == 0.0) { return; } double sn; if (fabs(c2) >= fabs(c1)) { sn = sqrt(1.0 + sqr(c1/c2)) * fabs(c2); } else { sn = sqrt(1.0 + sqr(c2/c1)) * fabs(c1); } double s1 = c1/sn; double s2 = c2/sn; for (int k = 1; k <= q.NumColumns(); k++) { double sv1 = q(l1, k); double sv2 = q(l2, k); q(l1, k) = s1 * sv1 + s2 * sv2; q(l2, k) = -s2 * sv1 + s1 * sv2; } for (int k = l3; k <= b.NumColumns(); k++) { double sv1 = b(l1, k); double sv2 = b(l2, k); b(l1, k) = s1 * sv1 + s2 * sv2; b(l2, k) = -s2 * sv1 + s1 * sv2; } c1 = sn; c2 = 0.0; } static void QRDecomp(Matrix &b, Matrix &q) { q.MakeIdent(); for (int m = 1; m <= b.NumColumns(); m++) { for (int k = m + 1; k <= b.NumRows(); k++) { Givens(b, q, b(m, m), b(k, m), m, k, m + 1); } } } static void NewtonStep(Matrix &q, Matrix &b, Vector &u, Vector &y, double &d) { for (int k = 1; k <= b.NumColumns(); k++) { for (int l = 1; l <= k - 1; l++) { y[k] -= b(l, k) * y[l]; } y[k] /= b(k, k); } d = 0.0; for (int k = 1; k <= b.NumRows(); k++) { double s = 0.0; for (int l = 1; l <= b.NumColumns(); l++) { s += q(l, k) * y[l]; } u[k] -= s; d += s * s; } d = sqrt(d); } //---------------------------------------------------------------------------- // PathTracer: Implementation of path-following engine //---------------------------------------------------------------------------- void PathTracer::TracePath(const Vector &p_start, double p_maxLambda, double p_omega) { const double c_tol = 1.0e-4; // tolerance for corrector iteration const double c_maxDist = 0.4; // maximal distance to curve const double c_maxContr = 0.6; // maximal contraction rate in corrector const double c_eta = 0.1; // perturbation to avoid cancellation // in calculating contraction rate double h = m_hStart; // initial stepsize const double c_hmin = 1.0e-8; // minimal stepsize const int c_maxIter = 100; // maximum iterations in corrector bool newton = false; // using Newton steplength (for zero-finding) Vector x(p_start); Vector u(p_start.Length()); // t is current tangent at x; newT is tangent at u, which is the next point. Vector t(p_start.Length()), newT(p_start.Length()); Vector y(p_start.Length() - 1); Matrix b(p_start.Length(), p_start.Length() - 1); SquareMatrix q(p_start.Length()); OnStep(x, false); GetJacobian(x, b); QRDecomp(b, q); q.GetRow(q.NumRows(), t); while (x[x.Length()] >= 0.0 && x[x.Length()] < p_maxLambda) { bool accept = true; if (fabs(h) <= c_hmin) { return; } // Predictor step for (int k = 1; k <= x.Length(); k++) { u[k] = x[k] + h * p_omega * t[k]; } double decel = 1.0 / m_maxDecel; // initialize deceleration factor GetJacobian(u, b); QRDecomp(b, q); int iter = 1; double disto = 0.0; while (true) { double dist; GetLHS(u, y); NewtonStep(q, b, u, y, dist); if (dist >= c_maxDist) { accept = false; break; } decel = max(decel, sqrt(dist / c_maxDist) * m_maxDecel); if (iter >= 2) { double contr = dist / (disto + c_tol * c_eta); if (contr > c_maxContr) { accept = false; break; } decel = max(decel, sqrt(contr / c_maxContr) * m_maxDecel); } if (dist <= c_tol) { // Success; break out of iteration break; } disto = dist; iter++; if (iter > c_maxIter) { return; } } if (!accept) { h /= m_maxDecel; // PC not accepted; change stepsize and retry if (fabs(h) <= c_hmin) { return; } continue; } // Determine new stepsize if (decel > m_maxDecel) { decel = m_maxDecel; } // Obtain the tangent at the next step q.GetRow(q.NumRows(), newT); if (!newton && Criterion(x, t) * Criterion(u, newT) < 0.0) { newton = true; } if (newton) { // Newton-type steplength adaptation, secant method h *= -Criterion(u, newT) / (Criterion(u, newT) - Criterion(x, t)); } else { // Standard steplength adaptation h = fabs(h / decel); } // PC step was successful; update and iterate x = u; OnStep(x, false); if (t * newT < 0.0) { // Bifurcation detected; for now, just "jump over" and continue, // taking into account the change in orientation of the curve. // Someday, we need to do more here! p_omega = -p_omega; } t = newT; } OnStep(x, true); } gambit-0.2010.09.01/src/tools/logit/path.h0000644000076500007650000000466511435216102014620 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/logit/path.h // Interface to generic smooth path-following algorithm. // // 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 PATH_H #define PATH_H using namespace Gambit; // // This class implements a generic path-following algorithm for smooth curves. // It is based on the ideas and codes presented in Allgower and Georg's // _Numerical Continuation Methods_. // class PathTracer { public: void SetMaxDecel(double p_maxDecel) { m_maxDecel = p_maxDecel; } double GetMaxDecel(void) const { return m_maxDecel; } void SetStepsize(double p_hStart) { m_hStart = p_hStart; } double GetStepsize(void) const { return m_hStart; } void SetTargetParam(double p_targetParam) { m_targetParam = p_targetParam; } double GetTargetParam(void) const { return m_targetParam; } protected: PathTracer(void) : m_maxDecel(1.1), m_hStart(0.03), m_targetParam(0.0) { } virtual ~PathTracer() { } void TracePath(const Vector &p_start, double p_maxLambda, double p_omega); // Criterion function: path tracer attempts to compute a zero of this function. virtual double Criterion(const Vector &p_point, const Vector &p_tangent) { return -1.0; } // Called on each accepted step of the tracing process. virtual void OnStep(const Vector &, bool) = 0; // Compute the LHS of the system of equations at the specified point. virtual void GetLHS(const Vector &p_point, Vector &p_lhs) = 0; // Compute the Jacobian matrix at the specified point. virtual void GetJacobian(const Vector &p_point, Matrix &p_matrix) = 0; private: double m_maxDecel, m_hStart, m_targetParam; }; #endif // PATH_H gambit-0.2010.09.01/src/tools/lp/0000777000076500007650000000000011441457125013072 500000000000000gambit-0.2010.09.01/src/tools/lp/basis.cc0000644000076500007650000001026611435216102014412 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/basis.cc // Implementation of Basis class // // 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 "basis.h" // --------------------------------------------------------------------------- // Class Basis // --------------------------------------------------------------------------- // ----------------------- // C-tor, D-tor, Operators // ----------------------- Basis::Basis(int first, int last, int firstlabel, int lastlabel) : basis(first, last), cols(firstlabel, lastlabel), slacks(first, last), colBlocked(firstlabel,lastlabel), rowBlocked(first,last) { int i; for(i = cols.First(); i <= cols.Last(); i++) { cols[i] = 0; colBlocked[i] = false; } for(i = basis.First(); i <= basis.Last(); i++) { basis[i]= - i; slacks[i] = i; rowBlocked[i] = false; } IsBasisIdent = true; } Basis::Basis(const Basis &bas) : basis(bas.basis), cols( bas.cols ), slacks( bas.slacks ), colBlocked(bas.colBlocked), rowBlocked(bas.rowBlocked), IsBasisIdent(bas.IsBasisIdent) { } Basis::~Basis() { } Basis& Basis::operator=(const Basis &orig) { if(this != &orig) { basis = orig.basis; cols = orig.cols; slacks = orig.slacks; rowBlocked = orig.rowBlocked; colBlocked = orig.colBlocked; IsBasisIdent = orig.IsBasisIdent; } return *this; } // ------------------------- // Public Members // ------------------------- int Basis::First() const { return basis.First();} int Basis::Last() const { return basis.Last();} int Basis::MinCol() const { return cols.First();} int Basis::MaxCol() const { return cols.Last();} bool Basis::IsRegColumn( int col ) const {return col >= cols.First() && col <= cols.Last();} bool Basis::IsSlackColumn( int col ) const {return -col >= basis.First() && -col <= basis.Last();} int Basis::Pivot(int outindex, int col) { int outlabel = basis[outindex]; if (IsSlackColumn(col)) slacks[-col] = outindex; else if (IsRegColumn(col)) cols[col] = outindex; else throw Gambit::IndexException(); // not a valid column to pivot in. if (IsSlackColumn(outlabel)) slacks[-outlabel] = 0; else if (IsRegColumn(outlabel)) cols[outlabel] = 0; else { // Note: here, should back out outindex. throw Gambit::IndexException(); // not a valid column to pivot out. } basis[outindex] = col; CheckBasis(); return outlabel; } bool Basis::Member( int col ) const { int ret; if (IsSlackColumn(col)) ret = slacks[-col]; else if (IsRegColumn(col)) ret = cols[col]; else ret = 0; return (ret != 0); } int Basis::Find( int col ) const { int ret; if ( IsSlackColumn(col)) ret = slacks[-col]; else if (IsRegColumn(col)) ret = cols[col]; else throw Gambit::IndexException(); return ret; } int Basis::Label(int index) const { return basis[index]; } void Basis::Mark(int col ) { if (IsSlackColumn(col)) rowBlocked[-col] = true; else if (IsRegColumn(col)) colBlocked[col] = true; } void Basis::UnMark(int col ) { if (IsSlackColumn(col)) rowBlocked[-col] = false; else if (IsRegColumn(col)) colBlocked[col] = false; } bool Basis::IsBlocked(int col) const { if (IsSlackColumn(col)) return rowBlocked[-col]; else if (IsRegColumn(col)) return colBlocked[col]; return false; } void Basis::CheckBasis() { bool check = true; for (int i =basis.First(); i <= basis.Last() && check; i++) if(basis[i] != -i) check = false; IsBasisIdent = check; } bool Basis::IsIdent() { return IsBasisIdent; } gambit-0.2010.09.01/src/tools/lp/basis.h0000644000076500007650000000543611435216102014257 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/basis.h // Declaration of basis class for tableaus // // 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 BASIS_H #define BASIS_H #include "libgambit/libgambit.h" //--------------------------------------------------------------------------- // Class Basis //--------------------------------------------------------------------------- class Basis { private: Gambit::Array basis; // current members of basis (neg for slacks) Gambit::Array cols; // location of col in basis (0 if not in basis) Gambit::Array slacks; // location of slacks in basis Gambit::Array colBlocked; Gambit::Array rowBlocked; bool IsBasisIdent; public: //------------------------------------------- // Constructors, Destructor, Operators //------------------------------------------- Basis(int first, int last, int firstlabel, int lastlabel); Basis(const Basis &); virtual ~Basis(); Basis& operator=(const Basis&); //------------------------------ // Public Members //------------------------------ int First() const; // First basis index int Last() const; // Last basis index int MinCol() const; // First Column label int MaxCol() const; // Last Column label bool IsRegColumn( int col ) const; bool IsSlackColumn( int col ) const; //remove outindex, insert label, return outlabel int Pivot(int outindex, int col); // return true iff label is a Basis member bool Member(int label) const; // finds Basis index corresponding to label number, int Find(int label) const; // finds label of variable corresponding to Basis index int Label(int index) const; // marks/unmarks label to block it from entering basis void Mark(int label); void UnMark(int label); // returns true if label is blocked from entering basis bool IsBlocked(int label) const; // Check if Basis is Ident virtual void CheckBasis(); // returns whether the basis is the identity matrix bool IsIdent(); }; #endif // BASIS_H gambit-0.2010.09.01/src/tools/lp/bfs.cc0000644000076500007650000000336611435216102014066 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/bfs.cc // Implementation of basic feasible solution class // // 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 "bfs.h" #include "libgambit/rational.h" //-------------------------------------------------------------------------- // class BFS: member functions //-------------------------------------------------------------------------- template BFS::BFS(void) : Gambit::Map((T) 0) { } template BFS::BFS(const T &d) : Gambit::Map((T) d) { } template BFS::BFS(const BFS &m) : Gambit::Map(m) { } template int BFS::operator==(const BFS &M) const { if (this->length != M.length) return 0; for (int i = 0; i < this->length; i++) if (this->keys[i] != M.keys[i]) return 0; return 1; } template int BFS::operator!=(const BFS &M) const { return !(*this == M); } template class BFS; template class BFS; gambit-0.2010.09.01/src/tools/lp/bfs.h0000644000076500007650000000237211435216102013724 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/bfs.h // Interface to basic feasible solution class // // 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 BFS_H #define BFS_H #include "libgambit/map.h" template class BFS : public Gambit::Map { public: BFS(void); BFS(const T &d); BFS(const BFS &m); // define two BFS's to be equal if their bases are equal int operator==(const BFS &M) const; int operator!=(const BFS &M) const; }; #endif // BFS_H gambit-0.2010.09.01/src/tools/lp/btableau.cc0000644000076500007650000000217311435216102015066 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/btableau.cc // Instantiation of base tableau classes // // 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 "libgambit/libgambit.h" #include "btableau.imp" template class BaseTableau; template class BaseTableau; template class TableauInterface; template class TableauInterface; gambit-0.2010.09.01/src/tools/lp/btableau.h0000644000076500007650000001150211435216102014724 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/btableau.h // Interface to base tableau classes // // 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 BTABLEAU_H #define BTABLEAU_H #include "libgambit/rational.h" #include "bfs.h" #include "basis.h" // --------------------------------------------------------------------------- // BaseTableau Stuff // --------------------------------------------------------------------------- template class BaseTableau { public: class BadPivot : public Gambit::Exception { public: virtual ~BadPivot() { } std::string GetDescription(void) const { return "Bad Pivot in BaseTableau"; } }; virtual ~BaseTableau() { } bool ColIndex(int) const; bool RowIndex(int) const; bool ValidIndex(int) const; virtual int MinRow() const = 0; virtual int MaxRow() const = 0; virtual int MinCol() const = 0; virtual int MaxCol() const = 0; virtual bool Member(int i) const = 0; // is variable i is a member of basis virtual int Label(int i) const = 0; // return variable in i'th position of Tableau virtual int Find(int i) const = 0; // return position of variable i // pivoting virtual int CanPivot(int outgoing,int incoming) = 0; virtual void Pivot(int outrow,int col) = 0; // perform pivot operation -- outgoing is row, incoming is column void CompPivot(int outlabel,int col); virtual long NumPivots() const = 0; // raw Tableau functions virtual void Refactor() = 0; }; // --------------------------------------------------------------------------- // TableauInterface Stuff // --------------------------------------------------------------------------- template class TableauInterface : public BaseTableau{ protected: const Gambit::Matrix *A; // should this be private? const Gambit::Vector *b; // should this be private? Basis basis; Gambit::Vector solution; // current solution vector. should this be private? long npivots; T eps1,eps2; Gambit::Array artificial; // artificial variables public: TableauInterface(const Gambit::Matrix &A, const Gambit::Vector &b); TableauInterface(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); TableauInterface(const TableauInterface&); virtual ~TableauInterface(); TableauInterface& operator=(const TableauInterface&); // information int MinRow() const; int MaxRow() const; int MinCol() const; int MaxCol() const; Basis & GetBasis(void); const Gambit::Matrix & Get_A(void) const; const Gambit::Vector & Get_b(void) const; bool Member(int i) const; int Label(int i) const; // return variable in i'th position of Tableau int Find(int i) const; // return Tableau position of variable i long NumPivots() const; long &NumPivots(); void Mark(int label); // marks label to block it from entering basis void UnMark(int label); // unmarks label bool IsBlocked(int label) const; // returns true if label is blocked virtual void BasisVector(Gambit::Vector &x) const = 0; // solve M x = (*b) void GetColumn( int , Gambit::Vector &) const; // raw column void GetBasis( Basis & ) const; // return Basis for current Tableau BFS GetBFS1(void) const; BFS GetBFS(void); // used in lpsolve for some reason virtual int CanPivot(int outgoing,int incoming) = 0; virtual void Pivot(int outrow,int col) = 0; // pivot -- outgoing is row, incoming is column virtual void SolveColumn(int, Gambit::Vector &) = 0; // column in new basis virtual void Solve(const Gambit::Vector &b, Gambit::Vector &x) = 0; // solve M x = b virtual void SolveT(const Gambit::Vector &c, Gambit::Vector &y) = 0; // solve y M = c virtual void Refactor() = 0; virtual void SetRefactor(int) = 0; // miscellaneous functions bool EqZero(T x) const; bool LtZero(T x) const; bool GtZero(T x) const; bool LeZero(T x) const; bool GeZero(T x) const; T Epsilon(int i = 2) const; bool IsArtifColumn(int col) const; }; #endif // BTABLEAU_H gambit-0.2010.09.01/src/tools/lp/btableau.imp0000644000076500007650000001534111435216102015267 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/btableau.imp // Implementation of base tableau classes // // 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. // // --------------------------------------------------------------------------- // BaseTableau method definitions // --------------------------------------------------------------------------- #include "btableau.h" template bool BaseTableau::ColIndex(int x) const { return MinCol()<=x && x<=MaxCol(); } template bool BaseTableau::RowIndex(int x) const { return MinRow()<=x && x<=MaxRow(); } template bool BaseTableau::ValidIndex(int x) const { return (ColIndex(x) || RowIndex(-x)); } template void BaseTableau::CompPivot(int outlabel, int col) { Pivot(Find(outlabel),col); Pivot(Find(-col),-outlabel); } // --------------------------------------------------------------------------- // TableauInterface method definitions // --------------------------------------------------------------------------- // Constructors and Destructor template TableauInterface::TableauInterface(const Gambit::Matrix &A, const Gambit::Vector &b) : A(&A), b(&b), basis(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()), solution(A.MinRow(),A.MaxRow()), npivots(0), artificial(A.MaxCol()+1,A.MaxCol()) { // These are the values recommended by Murtagh (1981) for 15 digit // accuracy in LP problems // Note: for gRational, eps1 and eps2 resolve to 0 Gambit::Epsilon(eps1,5); Gambit::Epsilon(eps2); } template TableauInterface::TableauInterface(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : A(&A), b(&b), basis(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()+art.Length()), solution(A.MinRow(),A.MaxRow()), npivots(0), artificial(A.MaxCol()+1,A.MaxCol()+art.Length()) { Gambit::Epsilon(eps1,5); Gambit::Epsilon(eps2); for(int i = 0;i TableauInterface::TableauInterface(const TableauInterface &orig) : A(orig.A), b(orig.b), basis(orig.basis), solution(orig.solution), npivots(orig.npivots), eps1(orig.eps1), eps2(orig.eps2), artificial(orig.artificial) { } template TableauInterface::~TableauInterface() { } template TableauInterface& TableauInterface::operator=(const TableauInterface &orig) { if(this!= &orig) { A = orig.A; b = orig.b; basis= orig.basis; solution= orig.solution; npivots = orig.npivots; artificial = orig.artificial; } return *this; } // getting information template int TableauInterface::MinRow() const { return A->MinRow(); } template int TableauInterface::MaxRow() const { return A->MaxRow(); } template int TableauInterface::MinCol() const { return basis.MinCol(); } template int TableauInterface::MaxCol() const { return basis.MaxCol(); } template Basis & TableauInterface::GetBasis(void) {return basis; } template const Gambit::Matrix & TableauInterface::Get_A(void) const {return *A; } template const Gambit::Vector & TableauInterface::Get_b(void) const {return *b;} template bool TableauInterface::Member(int i) const { return basis.Member(i);} template int TableauInterface::Label(int i) const { return basis.Label(i);} template int TableauInterface::Find(int i) const { return basis.Find(i);} template long TableauInterface::NumPivots() const { return npivots; } template long &TableauInterface::NumPivots() { return npivots; } template void TableauInterface::Mark(int label) {basis.Mark(label);} template void TableauInterface::UnMark(int label) {basis.UnMark(label);} template bool TableauInterface::IsBlocked(int label) const { return basis.IsBlocked(label); } template void TableauInterface::GetColumn(int col, Gambit::Vector &ret) const { if(IsArtifColumn(col)) { ret = (T) 0; ret[artificial[col]] = (T)1; } else if(basis.IsRegColumn(col)) A->GetColumn(col, ret); else if (basis.IsSlackColumn(col)) { ret = (T) 0; ret[-col] = (T) 1; } } template void TableauInterface::GetBasis(Basis &out) const { out= basis; } template BFS TableauInterface::GetBFS() { Gambit::Vector sol(basis.First(),basis.Last()); BasisVector(sol); BFS cbfs((T) 0); for(int i=MinCol();i<=MaxCol();i++) if(Member(i)) cbfs.Define(i,sol[basis.Find(i)]); return cbfs; } template BFS TableauInterface::GetBFS1() const { Gambit::Vector sol(basis.First(),basis.Last()); BasisVector(sol); BFS cbfs((T) 0); int i; for(i=-MaxRow();i<=-MinRow();i++) if(Member(i)) cbfs.Define(i,sol[basis.Find(i)]); for(i=MinCol();i<=MaxCol();i++) if(Member(i)) cbfs.Define(i,sol[basis.Find(i)]); return cbfs; } // miscellaneous functions template bool TableauInterface::EqZero(T x) const { return (LeZero(x) && GeZero(x)); } template bool TableauInterface::LtZero(T x) const { return !GeZero(x); } template bool TableauInterface::GtZero(T x) const { return !LeZero(x); } template bool TableauInterface::LeZero(T x) const { if(x <=eps2) return 1; return 0; } template bool TableauInterface::GeZero(T x) const { if(x >= -eps2) return 1; return 0; } template T TableauInterface::Epsilon(int i) const { if(i!=1 && i!=2) { throw Gambit::IndexException(); } if(i==1) return eps1; return eps2; } template bool TableauInterface::IsArtifColumn(int col) const { return col>=artificial.First() && col<=artificial.Last(); } /* template BaseTableau::BadPivot::~BadPivot() { } template gText BaseTableau::BadPivot::Description(void) const { return "Bad Pivot in BaseTableau"; } */ gambit-0.2010.09.01/src/tools/lp/efglp.cc0000644000076500007650000003255511441453421014417 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/efglp.cc // Implementation of algorithm to solve efgs via linear programming // // 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 #include #include #include "libgambit/libgambit.h" #include "tableau.h" #include "lpsolve.h" using namespace Gambit; extern int g_numDecimals; // // Structure for caching data which might take a little time to compute // struct GameData { int ns1, ns2, ni1, ni2; Rational minpay; PVector infosetIndex, infosetOffset; GameData(const Game &p_game) : infosetIndex(p_game->NumInfosets()), infosetOffset(p_game->NumInfosets()) { infosetIndex = 0; infosetOffset = 0; } }; // // Recursively fills the constraint matrix A for the subtree rooted at 'n'. // template void BuildConstraintMatrix(GameData &p_data, const BehavSupport &p_support, Matrix &A, const GameNode &n, const T &prob, int s1, int s2, int i1, int i2) { GameOutcome outcome = n->GetOutcome(); if (outcome) { A(s1,s2) += (T) (Rational(prob) * outcome->GetPayoff(1) - p_data.minpay); } if (n->NumChildren() == 0) { // Terminal node, recursion ends return; } if (n->GetPlayer()->IsChance()) { GameInfoset infoset = n->GetInfoset(); for (int i = 1; i <= n->NumChildren(); i++) { BuildConstraintMatrix(p_data, p_support, A, n->GetChild(i), prob * infoset->GetActionProb(i), s1, s2, i1, i2); } } else if (n->GetPlayer()->GetNumber() == 1) { i1 = p_data.infosetIndex(1, n->GetInfoset()->GetNumber()); int snew = p_data.infosetOffset(1, n->GetInfoset()->GetNumber()); A(s1, p_data.ns2+i1+1) = (T) 1; for (int i = 1; i <= p_support.NumActions(n->GetInfoset()); i++) { A(snew+i, p_data.ns2+i1+1) = (T) -1; BuildConstraintMatrix(p_data, p_support, A, n->GetChild(p_support.GetAction(n->GetInfoset(), i)->GetNumber()), prob, snew+i, s2, i1, i2); } } else { // Must be player 2 i2 = p_data.infosetIndex(2, n->GetInfoset()->GetNumber()); int snew = p_data.infosetOffset(2, n->GetInfoset()->GetNumber()); A(p_data.ns1+i2+1, s2) = (T) -1; for (int i = 1; i <= p_support.NumActions(n->GetInfoset()); i++) { A(p_data.ns1+i2+1, snew+i) = (T) 1; BuildConstraintMatrix(p_data, p_support, A, n->GetChild(p_support.GetAction(n->GetInfoset(), i)->GetNumber()), prob, s1, snew+i, i1, i2); } } } #ifdef UNUSED // // This function outputs the LP problem in CPLEX format to the specified // stream. // template void PrintCPLEX(std::ostream &p_stream, const Matrix &A, const Vector &b, const Vector &c, int nequals) { p_stream << "Minimize" << std::endl; for (int i = 1; i <= c.Length(); i++) { if (i > 1 && c[i] >= (T) 0) { p_stream << "+"; } p_stream << c[i] << " x" << i << " "; } p_stream << std::endl; p_stream << std::endl << "Subject To" << std::endl; for (int j = 1; j <= b.Length(); j++) { for (int i = 1; i <= c.Length(); i++) { if (i > 1 && A(j, i) >= (T) 0) { p_stream << "+"; } p_stream << A(j, i) << " x" << i << " "; } if (j + nequals > b.Length()) { p_stream << " = " << b[j] << std::endl; } else { p_stream << " >= " << b[j] << std::endl; } } p_stream << std::endl << "Bounds" << std::endl; for (int i = 1; i <= c.Length(); i++) { p_stream << "x" << i << " >= 0" << std::endl; } p_stream << "End" << std::endl; } #endif // UNUSED // // The routine to actually solve the LP // This routine takes an LP of the form // maximize c x subject to Ax>=b and x>=0, // except the last 'nequals' constraints in A hold with equality. // It expects the array p_primal to be the same length as the // number of columns in A, and the routine returns the primal solution; // similarly, the array p_dual should have the same length as the // number of rows in A, and the routine returns the dual solution. // // To implement your own custom solver for this problem, simply // replace this function. // template bool SolveLP(const Matrix &A, const Vector &b, const Vector &c, int nequals, Array &p_primal, Array &p_dual) { LPSolve LP(A, b, c, nequals); if (!LP.IsAborted()) { BFS cbfs((T) 0); LP.OptBFS(cbfs); for (int i = 1; i <= A.NumColumns(); i++) { if (cbfs.IsDefined(i)) { p_primal[i] = cbfs(i); } else { p_primal[i] = (T) 0; } } for (int i = 1; i <= A.NumRows(); i++) { if (cbfs.IsDefined(-i)) { p_dual[i] = cbfs(-i); } else { p_dual[i] = (T) 0; } } return true; } else { return false; } } template void PrintProfileDetail(std::ostream &p_stream, const MixedBehavProfile &p_profile) { char buffer[256]; for (int pl = 1; pl <= p_profile.GetGame()->NumPlayers(); pl++) { GamePlayer player = p_profile.GetGame()->GetPlayer(pl); p_stream << "Behavior profile for player " << pl << ":\n"; p_stream << "Infoset Action Prob Value\n"; p_stream << "------- ------- ----------- -----------\n"; for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); for (int act = 1; act <= infoset->NumActions(); act++) { GameAction action = infoset->GetAction(act); if (infoset->GetLabel() != "") { sprintf(buffer, "%7s ", infoset->GetLabel().c_str()); } else { sprintf(buffer, "%7d ", iset); } p_stream << buffer; if (action->GetLabel() != "") { sprintf(buffer, "%7s ", action->GetLabel().c_str()); } else { sprintf(buffer, "%7d ", act); } p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile(pl, iset, act), g_numDecimals).c_str()); p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile.GetActionValue(infoset->GetAction(act)), g_numDecimals).c_str()); p_stream << buffer; p_stream << "\n"; } } p_stream << "\n"; p_stream << "Infoset Node Belief Prob\n"; p_stream << "------- ------- ----------- -----------\n"; for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); for (int n = 1; n <= infoset->NumMembers(); n++) { sprintf(buffer, "%7d ", iset); p_stream << buffer; sprintf(buffer, "%7d ", n); p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile.GetBeliefProb(infoset->GetMember(n)), g_numDecimals).c_str()); p_stream << buffer; sprintf(buffer, "%11s ", ToText(p_profile.GetRealizProb(infoset->GetMember(n)), g_numDecimals).c_str()); p_stream << buffer; p_stream << "\n"; } } p_stream << "\n"; } } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedBehavProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << ',' << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedBehavProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream << ',' << p_profile[i]; } p_stream << std::endl; } // // Sets the action probabilities at unreached information sets // which are left undefined by the sequence form method to // the centroid. This is useful for the LiapValue, since that // implements a penalty for having information sets where the // action probabilities do not sum to one. // // This is really a hack; in the future, behavior profiles need to be // "smarter" about the possibility they are not defined off the // equilibrium path. // template void UndefinedToCentroid(MixedBehavProfile &p_profile) { Game efg = p_profile.GetGame(); for (int pl = 1; pl <= efg->NumPlayers(); pl++) { GamePlayer player = efg->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); if (p_profile.GetInfosetProb(infoset) > (T) 0) { continue; } T total = (T) 0; for (int act = 1; act <= infoset->NumActions(); act++) { total += p_profile.GetActionProb(infoset->GetAction(act)); } if (total == (T) 0) { for (int act = 1; act <= infoset->NumActions(); act++) { p_profile(pl, iset, act) = (T) 1.0 / (T) infoset->NumActions(); } } } } } // // Recursively construct the behavior profile from the sequence form // solution represented by 'p_primal' (containing player 2's // sequences) and 'p_dual' (containing player 1's sequences). // // Any information sets not reached with positive probability have // their action probabilities set to zero. // template void GetBehavior(const GameData &p_data, const BehavSupport &p_support, MixedBehavProfile &v, const Array &p_primal, const Array &p_dual, const GameNode &n, int s1, int s2) { if (n->NumChildren() == 0) { return; } if (n->GetPlayer()->IsChance()) { for(int i = 1; i <= n->NumChildren(); i++) { GetBehavior(p_data, p_support, v, p_primal, p_dual, n->GetChild(i), s1, s2); } } else if (n->GetPlayer()->GetNumber() == 2) { int inf = p_data.infosetIndex(2, n->GetInfoset()->GetNumber()); int snew = p_data.infosetOffset(2, n->GetInfoset()->GetNumber()); for (int i = 1; i <= p_support.NumActions(n->GetInfoset()); i++) { if (p_primal[s1] > (T) 0) { v(2,inf,i) = p_primal[snew+i] / p_primal[s1]; } else { v(2,inf,i) = (T) 0; } GetBehavior(p_data, p_support, v, p_primal, p_dual, n->GetChild(p_support.GetAction(n->GetInfoset(), i)->GetNumber()), snew+i, s2); } } else { // Must be player 1 int inf = p_data.infosetIndex(1, n->GetInfoset()->GetNumber()); int snew = p_data.infosetOffset(1, n->GetInfoset()->GetNumber()); for (int i = 1; i <= p_support.NumActions(n->GetInfoset()); i++) { if (p_dual[s2] > (T) 0) { v(1,inf,i) = p_dual[snew+i] / p_dual[s2]; } else { v(1,inf,i) = (T) 0; } GetBehavior(p_data, p_support, v, p_primal, p_dual, n->GetChild(p_support.GetAction(n->GetInfoset(), i)->GetNumber()), s1, snew+i); } } } // // Convert the sequence form solution represented by the vectors // (p_primal, p_dual) back to a behavior profile. // Information sets not reached with positive probability have their // probabilities set to the centroid // template void SequenceToBehavior(const GameData &p_data, const BehavSupport &p_support, const Array &p_primal, const Array &p_dual) { MixedBehavProfile profile(p_support); GetBehavior(p_data, p_support, profile, p_primal, p_dual, p_support.GetGame()->GetRoot(), 1, 1); UndefinedToCentroid(profile); PrintProfile(std::cout, "NE", profile); //PrintProfileDetail(std::cout, profile); } // // Compute and print one equilibrium by solving a linear program based // on the sequence form representation of the game. // template void SolveExtensive(const Game &p_game) { BFS cbfs((T) 0); BehavSupport support(p_game); // Cache some data for convenience GameData data(p_game); data.ns1 = support.NumSequences(1); data.ns2 = support.NumSequences(2); data.ni1 = support.GetGame()->GetPlayer(1)->NumInfosets()+1; data.ni2 = support.GetGame()->GetPlayer(2)->NumInfosets()+1; support.ReachableInfosets(p_game->GetRoot(), data.infosetIndex); for (int iset = 1, offset = 1, index = 1; iset < data.ni1; iset++) { if (data.infosetIndex(1, iset) > 0) { data.infosetOffset(1, iset) = offset; data.infosetIndex(1, iset) = index++; offset += support.NumActions(1, iset); } } for (int iset = 1, offset = 1, index = 1; iset < data.ni2; iset++) { if (data.infosetIndex(2, iset) > 0) { data.infosetOffset(2, iset) = offset; data.infosetIndex(2, iset) = index++; offset += support.NumActions(2, iset); } } data.minpay = p_game->GetMinPayoff(); Matrix A(1, data.ns1 + data.ni2, 1, data.ns2 + data.ni1); Vector b(1, data.ns1 + data.ni2); Vector c(1, data.ns2 + data.ni1); A = (T) 0; b = (T) 0; c = (T) 0; BuildConstraintMatrix(data, support, A, p_game->GetRoot(), (T) 1, 1, 1, 0, 0); A(1, data.ns2 + 1) = (T) -1; A(data.ns1 + 1, 1) = (T) 1; b[data.ns1 + 1] = (T) 1; c[data.ns2 + 1] = (T) -1; Array primal(A.NumColumns()), dual(A.NumRows()); if (SolveLP(A, b, c, data.ni2, primal, dual)) { SequenceToBehavior(data, support, primal, dual); } } template void SolveExtensive(const Game &); template void SolveExtensive(const Game &); gambit-0.2010.09.01/src/tools/lp/lp.cc0000644000076500007650000000731511435216102013725 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/lp.cc // Implementation of algorithm to compute mixed strategy equilibria // of constant sum normal form games via linear programming // // 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 #include #include #include "libgambit/libgambit.h" template void SolveExtensive(const Gambit::Game &p_game); template void SolveStrategic(const Gambit::Game &p_game); void PrintBanner(std::ostream &p_stream) { p_stream << "Compute Nash equilibria by solving a linear program\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "With no options, reports all Nash equilibria found.\n\n"; std::cerr << "Options:\n"; std::cerr << " -d DECIMALS compute using floating-point arithmetic;\n"; std::cerr << " display results with DECIMALS digits\n"; std::cerr << " -S use strategic game\n"; std::cerr << " -h print this help message\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; exit(1); } int g_numDecimals = 6; int main(int argc, char *argv[]) { int c; bool useFloat = false, useStrategic = false, quiet = false; while ((c = getopt(argc, argv, "d:hqS")) != -1) { switch (c) { case 'd': useFloat = true; g_numDecimals = atoi(optarg); break; case 'h': PrintHelp(argv[0]); break; case 'q': quiet = true; break; case 'S': useStrategic = true; break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Gambit::Game game = Gambit::ReadGame(std::cin); if (game->NumPlayers() != 2) { std::cerr << "Error: Game does not have two players.\n"; return 1; } if (!game->IsConstSum()) { std::cerr << "Error: Game is not constant-sum.\n"; return 1; } if (!game->IsTree() || useStrategic) { game->BuildComputedValues(); if (useFloat) { SolveStrategic(game); } else { SolveStrategic(game); } } else { if (useFloat) { SolveExtensive(game); } else { SolveExtensive(game); } } return 0; } catch (Gambit::InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } } gambit-0.2010.09.01/src/tools/lp/lpsolve.cc0000644000076500007650000000225511435216102014774 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/lpsolve.cc // Instantiation of common LP solvers // // 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 "lpsolve.imp" #include "libgambit/rational.h" template class LPSolve; template class LPSolve; template Gambit::Array Artificials(const Gambit::Vector &); template Gambit::Array Artificials(const Gambit::Vector &); gambit-0.2010.09.01/src/tools/lp/lpsolve.h0000644000076500007650000000536411435216102014642 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/lpsolve.h // Interface to LP solvers // // 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 LPSOLVE_H #define LPSOLVE_H #include "libgambit/libgambit.h" #include "lptab.h" #include "bfs.h" // // This class implements a LP solver. Its constructor takes as input a // LP problem of the form maximize c x subject to A x<=b, x >= 0. // The last k equations can represent equalities (indicated by the // parameter "nequals"). // // All computation is done in the class constructor; when the constructor // returns the computation has completed. OptimumVector() returns the // solution. The components are indexed by the columns of A, with the // excess columns representing the artificial and slack variables. // template class LPSolve { private: int well_formed, feasible, bounded, aborted, flag, nvars, neqns,nequals; T total_cost,eps1,eps2,eps3,tmin; BFS opt_bfs,dual_bfs; LPTableau tab; Gambit::Array *UB, *LB; Gambit::Array *ub, *lb; Gambit::Vector *xx, *cost; Gambit::Vector y, x, d; void Solve(int phase = 0); int Enter(void); int Exit(int); public: LPSolve(const Gambit::Matrix &A, const Gambit::Vector &B, const Gambit::Vector &C, int nequals); // nequals = number of equalities (last nequals rows) // LPSolve(const Gambit::Matrix &A, const Gambit::Vector &B, // const Gambit::Vector &C, const Gambit::Vector &sense, // const Gambit::Vector &LB, const Gambit::Vector &lb, // const Gambit::Vector &UB, const Gambit::Vector &ub); ~LPSolve(); T OptimumCost(void) const; const Gambit::Vector &OptimumVector(void) const; const Gambit::List< BFS > &GetAll(void); const LPTableau &GetTableau(); int IsAborted(void) const; int IsWellFormed(void) const; int IsFeasible(void) const; int IsBounded(void) const; long NumPivots(void) const; void OptBFS(BFS &b) const; T Epsilon(int i = 2) const; }; #endif // LPSOLVE_H gambit-0.2010.09.01/src/tools/lp/lpsolve.imp0000644000076500007650000003215211435216102015173 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/lpsolve.imp // Implementation of LP solver // // 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 "lpsolve.h" template Gambit::Array Artificials(const Gambit::Vector &b) { Gambit::Array ret; for(int i=b.First();i<=b.Last();i++) if(b[i]<(T)0) ret.Append(i); return ret; } template LPSolve::LPSolve(const Gambit::Matrix &A, const Gambit::Vector &b, const Gambit::Vector &c, int nequals) : well_formed(1), feasible(1), bounded(1), aborted(0), nvars(c.Length()),neqns(b.Length()), nequals(nequals), total_cost(0),tmin(0), opt_bfs((T)0), dual_bfs((T)0) , tab(A,Artificials(b),b), UB(0),LB(0),ub(0),lb(0),xx(0), cost(0), y(b.Length()),x(b.Length()),d(b.Length()) { // These are the values recommended by Murtagh (1981) for 15 digit // accuracy in LP problems Gambit::Epsilon(eps1,5); Gambit::Epsilon(eps2,8); Gambit::Epsilon(eps3,6); // Check dimensions if (A.NumRows() != b.Length() || A.NumColumns() != c.Length()) { well_formed = 0; return; } // gout << "\n--- Begin LPSolve ---\n"; // tab.BigDump(gout); // initialize data int i,j,num_inequals,xlab,num_artific; num_inequals = A.NumRows() - nequals; num_artific=Artificials(b).Length(); nvars+=num_artific; // gout << "\n--- Begin Phase I ---\n"; UB = new Gambit::Array(nvars+neqns); LB = new Gambit::Array(nvars+neqns); ub = new Gambit::Array(nvars+neqns); lb = new Gambit::Array(nvars+neqns); xx = new Gambit::Vector(nvars+neqns); cost = new Gambit::Vector(nvars+neqns); for(j=(*UB).First();j<=(*UB).Last();j++) { (*UB)[j] = false; (*LB)[j] = false; (*ub)[j] = (T)0; (*lb)[j] = (T)0; } // Define Phase I upper and lower bounds for(i=1;i<=nvars;i++) { (*LB)[i]=true; // original and artificial variables // (*lb)[i]=(T)0; // have lower bounds of 0 } // for slack variables for(i = 1;i<= neqns;i++) { if(b[i] >= (T)0) (*LB)[nvars+i] = true; else (*UB)[nvars+i] = true; } // define Phase 1 unit cost vector (*cost) = (T)0; for (i = 1; i <= neqns; i++) { (*cost)[nvars+i] = (T)0; if ((*UB)[nvars+i]) { (*cost)[nvars+i] = (T)1; } else if(i > num_inequals) (*cost)[nvars+i] = -(T)1; } // gout << "\nUB = " << *UB << " " << "\nLB = " << *LB; // gout << "\nub = " << *ub << " " << "\nlb = " << *lb; // gout << "\ncost = " << (*cost); // Initialize the tableau tab.SetCost((*cost)); // gout << "\nInitial Tableau = \n"; // tab.Dump(gout); // set xx to be initial feasible solution to phase II for(i=1;i<=(*xx).Length();i++) { if((*LB)[i]) (*xx)[i]=(*lb)[i]; else if((*UB)[i]) (*xx)[i]=(*ub)[i]; else (*xx)[i]=(T)0; } tab.BasisVector(x); for(i=1;i<=x.Length();i++) { xlab = tab.Label(i); if(xlab<0) xlab=nvars-xlab; (*xx)[xlab]=x[i]; } // gout << "\nxx: " << (*xx); Solve(1); total_cost = tab.TotalCost(); // gout << "\nFinal Phase I tableau: "; // tab.Dump(gout); // gout << ", cost: " << total_cost; // gout << "\n--- End Phase I ---\n"; if(!bounded) { // gout << "\nPhase 1 Unbounded\n"; } //assert(bounded); // which eps should be used here? if(total_cost < -eps1) { feasible = 0; // gout << "\nProblem Infeasible\n\n"; return; } // gout << "\n--- Begin Phase II ---\n"; // Define Phase II upper and lower bounds for slack variables // gout << "\nxx: " << (*xx); for(i=num_inequals+1;i<=neqns;i++) (*UB)[nvars+i] = true; for(i=1;i<=neqns;i++) { if(b[i] < (T)0) (*LB)[nvars+i] = true; } // install Phase II unit cost vector for(i=c.First();i<=c.Last();i++) (*cost)[i] = c[i]; for(i=c.Last()+1;i<=nvars+neqns;i++) (*cost)[i] = (T)0; // gout << "\nUB = " << *UB << " " << " LB = " << *LB; // gout << "\nub = " << *ub << " " << " lb = " << *lb; // gout << "\nc = " << (*cost); tab.SetCost((*cost)); // gout << "\nInitial basis: "; // tab.Dump(gout); gout << '\n'; Solve(2); // gout << "\n--- End Phase II ---\n"; if(!bounded) { // gout << "\nPhase II Unbounded\n"; } total_cost = tab.TotalCost(); tab.DualVector(y); opt_bfs = tab.GetBFS(); dual_bfs = tab.DualBFS(); // gout << "\nFinal basis: "; // tab.Dump(gout); gout << '\n'; // gout << "\ncost: " << total_cost; // gout << "DualVector = " << y << "\n"; // gout << "\nopt_bfs:\n"; // opt_bfs.Dump(gout); // gout << "\n"; // dual_bfs.Dump(gout); for(i=1;i<=neqns;i++) if(dual_bfs.IsDefined(-i)) opt_bfs.Define(-i,dual_bfs(-i)); // gout << "\n--- End LPSolve ---\n"; } //template LPSolve:: //LPSolve(const Gambit::Matrix &A, const Gambit::Vector &/*B*/, // const Gambit::Vector &/*C*/, const Gambit::Vector &/*sense*/, // const Gambit::Vector &/*LB*/, const Gambit::Vector &/*lb*/, // const Gambit::Vector &/*UB*/, const Gambit::Vector &/*ub*/) // : well_formed(1), feasible(1), bounded(1), // nvars(c.Length()),neqns(b.Length()), total_cost(0), // opt_bfs((T)0), dual_bfs((T)0), A(A), b(b), c(c), tab(0), // UB(c.Length()+b.Length()), LB(b.Length()+c.Length()), // ub(c.Length()+b.Length()),lb(c.Length()+b.Length()), // xx(c.Length()+b.Length()), // y(b.Length()),x(b.Length()),d(b.Length()), // cost(c.Length()+b.Length()) //{ // gout << "\n This constructor not implemented yet"; // assert(0); //} template void LPSolve::Solve(int phase) { int i, in,xlab; int outlab = 0; int out = 0; Gambit::Vector a(neqns); double npiv; do { // step 1: Solve y B = c_B // tab.DualVector(y); // step 1: Solve y B = c_B // gout << "\nstep 1, y: " << y; do { in = Enter(); // step 2: Choose entering variable // gout << "\nstep 2, in: " << in; if(in) { // tab.GetColumn(in,a); // tab.Solve(a,d); // step 3: Solve B d = a tab.SolveColumn(in,d); // step 3: Solve B d = a, where a col #in of A out = Exit(in); // step 4: Choose leaving variable if(out==0) { bounded=0; return; } else if (out<0) outlab = in; else { // gout << "\nstep 4, in: " << in << " out: " << out; outlab = tab.Label(out); } // update xx for(i=1;i<=x.Length();i++) { // step 5a: // gout << "\nstep 5a, i: " << i; xlab=tab.Label(i); if(xlab<0)xlab=nvars-xlab; (*xx)[xlab]=(*xx)[xlab]+(T)flag*tmin*d[i]; } if(in>0) (*xx)[in] -= (T)flag*tmin; if(in<0) (*xx)[nvars-in] -= (T)flag*tmin; // gout << "\nstep 5a, xx: " << (*xx); } } while(outlab==in && outlab !=0); if(in) { // gout << "\nstep 5b, Pivot in: " << in << " out: " << out; tab.Pivot(out,in); // step5b: Pivot new variable into basis npiv=(double)tab.NumPivots(); tab.BasisVector(x); // gout << "\n tab = "; // tab.Dump(gout); // gout << "\nxx: " << (*xx); // gout << ", Cost = " << tab.TotalCost() << "\n"; if(phase ==1 && tab.TotalCost() >= -eps1) return; // gout << "\nAfter pivot tab = \n"; } } while(in); } template int LPSolve::Enter() { // gout << "\nIn LPSolve::Enter()"; int i,in; T rc; in = 0; T test = (T)0; for(i=1;i<=nvars+neqns;i++) { int lab = i; if(i>nvars)lab=nvars-i; if(!tab.Member(lab)) { rc = tab.RelativeCost(lab); // gout << "\nCost: " << tab.GetCost(); // gout << "\n i = " << i << " cost: " << (*cost)[i] << " rc: " << rc << " test: " << test; if(rc > test+eps1) if((*UB)[i]==false || ((*UB)[i]==true && (*xx)[i] - (*ub)[i] < -eps1)) { {test=rc;in = lab;flag = -1;} // gout << "\nflag: -1 in: " << in << " test: " << test; } if(-rc > test+eps1) if((*LB)[i]==false || ((*LB)[i]==true && (*xx)[i] - (*lb)[i] > eps1)) { {test=-rc;in=lab;flag = 1;} // gout << "\nflag: +1 in: " << in << " test: " << test; } } } return in; } template int LPSolve::Exit(int in) { int j,out,lab,col; T t; // gout << "\nin Exit(), flag: " << flag; out=0; tmin = (T)100000000; for (j=1; j<=neqns; j++) { lab=tab.Label(j); col=lab; if(lab<0)col=nvars-lab; if(flag == -1) { t = (T)1000000000; if (d[j] > eps2 && (*LB)[col]==true) { t = ((*xx)[col]-(*lb)[col])/d[j]; } if (d[j] < -eps2 && (*UB)[col]==true) { t = ((*xx)[col]-(*ub)[col])/d[j]; } if(t>=-eps2 && t < tmin-eps2) { tmin = t; out = j; } // gout << "\nd[" << j << "]: " << d[j] << " col: " << col << " xx: " << (*xx)[col]; // gout << " t: " << t << " tmin: " << tmin; } if(flag == 1) { t = (T)1000000000; if (d[j] > eps2 && (*UB)[col]==true) { t = ((*ub)[col]-(*xx)[col])/d[j]; } if (d[j] < -eps2 && (*LB)[col]==true) { t = ((*lb)[col]-(*xx)[col])/d[j]; } if(t >= -eps2 && t < tmin-eps2) { tmin = t; out = j; } // gout << "\nd[" << j << "]: " << d[j] << " col: " << col << " xx: " << (*xx)[col]; // gout << " t: " << t << " tmin: " << tmin; } } col=in; if(in<0)col=nvars-in; t = (T)1000000000; if(flag == -1 && (*UB)[col]) t = (*ub)[col]-(*xx)[col]; if(flag == 1 && (*LB)[col]) t = (*xx)[col]-(*lb)[col]; if(t > eps2 && t < tmin-eps2) { tmin = t; out = -1; } return out; } template T LPSolve::OptimumCost(void) const { return total_cost; } template const Gambit::Vector &LPSolve::OptimumVector(void) const { return (*xx); } template const LPTableau &LPSolve::GetTableau(void) { return tab; } #ifdef UNUSED // // This method does not work correctly, so is disabled // template const Gambit::List > &LPSolve::GetAll(void) { Gambit::Vector c(tab.GetCost()); Gambit::Vector uc(tab.GetUnitCost()); // gout << "\nc: " << c; // gout << "\nuc: " << uc; Gambit::Vector x(tab.MinRow(),tab.MaxRow()); tab.BasisVector(x); int i; for(i=c.First();i<=c.Last();i++) { // gout << "\ncol: " << i << " cost: " << tab.RelativeCost(i); // gout << " label: " << tab.Label(i) << " x: " << x[tab.Label(i)]; if(tab.RelativeCost(i) < -eps2 && x[tab.Label(i)]>eps2) { // gout << " mark"; tab.Mark(i); } } for(i=uc.First();i<=uc.Last();i++) { // gout << "\nrow: " << i << " cost: " << tab.RelativeCost(-i); // gout << " label: " << tab.Label(-i) << " x: " << x[tab.Label(-i)]; if(tab.RelativeCost(-i) < -eps2 && x[tab.Label(-i)]>eps2) { // gout << " mark"; tab.Mark(-i); } } VertEnum AllSolutions(tab); Gambit::List > verts; Gambit::List > *bfs = new Gambit::List >(AllSolutions.VertexList()); Gambit::List > *dual_bfs = new Gambit::List >(AllSolutions.DualVertexList()); AllSolutions.Vertices(verts); // gout << "\nHere are the BFSs: \n"; for( i=1;i<=(*bfs).Length();i++) { // gout << "\n" << i << ": "; // (*bfs)[i].Dump(gout); } // gout << "\nHere are the Dual BFSs: \n"; for( i=1;i<=(*dual_bfs).Length();i++) { // gout << "\n" << i << ": "; //n (*dual_bfs)[i].Dump(gout); } // gout << "\nHere are the vertices:\n"; // for( i=1;i<=verts.Length();i++) // gout << "\n" << i << ": " << verts[i]; for( i=1;i<=(*bfs).Length();i++) for(int j=1;j<=neqns;j++) if((*dual_bfs)[i].IsDefined(-j)) (*bfs)[i].Define(-j,(*dual_bfs)[i](-j)); // gout << "\nHere are the BFSs: \n"; for( i=1;i<=(*bfs).Length();i++) { // gout << "\n" << i << ": "; // (*bfs)[i].Dump(gout); } return *bfs; } #endif // UNUSED template int LPSolve::IsFeasible(void) const { return feasible; } template int LPSolve::IsBounded(void) const { return bounded; } template int LPSolve::IsWellFormed(void) const { return well_formed; } template int LPSolve::IsAborted(void) const { return aborted; } template long LPSolve::NumPivots(void) const { return tab.NumPivots(); } template void LPSolve::OptBFS(BFS &b) const { b = opt_bfs; } template LPSolve::~LPSolve() { if(UB) delete UB; if(LB) delete LB; if(ub) delete ub; if(lb) delete lb; if(xx) delete xx; if(cost) delete cost; } template T LPSolve::Epsilon(int i/* = 2*/) const { if(i == 1) return eps1; if(i == 3)return eps3; return eps2; } gambit-0.2010.09.01/src/tools/lp/lptab.cc0000644000076500007650000000174711435216102014417 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/lptab.cc // Instantiation of LP tableau // // 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 "lptab.imp" template class LPTableau; template class LPTableau; gambit-0.2010.09.01/src/tools/lp/lptab.h0000644000076500007650000000601311435216102014250 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/lptab.h // Interface to LP tableaus // // 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. // // --------------------------------------------------------------------------- // LPTableau Stuff (For Linear Programming code) // --------------------------------------------------------------------------- #ifndef LPTAB_H #define LPTAB_H #include "tableau.h" template class LPTableau : public Tableau { private: Gambit::Vector dual; Gambit::Array unitcost; Gambit::Array cost; Gambit::Array UB,LB; // does col have upper/lower bound? Gambit::Array ub,lb; // upper/lower bound void SolveDual(); public: class BadPivot : public Gambit::Exception { public: virtual ~BadPivot(); std::string GetDescription(void) const; }; LPTableau(const Gambit::Matrix &A, const Gambit::Vector &b); LPTableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); LPTableau(const LPTableau&); virtual ~LPTableau(); LPTableau& operator=(const LPTableau&); // cost information void SetCost(const Gambit::Vector& ); // unit column cost := 0 void SetCost(const Gambit::Vector&, const Gambit::Vector& ); Gambit::Vector GetCost() const; Gambit::Vector GetUnitCost() const; T TotalCost(); // cost of current solution T RelativeCost(int) const; // negative index convention void RelativeCostVector(Gambit::Vector &, Gambit::Vector &); void DualVector(Gambit::Vector &) const; // column vector // Redefined functions void Refactor(); void Pivot(int outrow,int col); void ReversePivots(Gambit::List > &); bool IsReversePivot(int i, int j); void DualReversePivots(Gambit::List > &); bool IsDualReversePivot(int i, int j); BFS DualBFS(void) const; // returns the label of the index of the last artificial variable int LastLabel( void ); // select Basis elements according to Tableau rows and cols void BasisSelect(const Gambit::Array&rowv, Gambit::Vector &colv) const; // as above, but unit column elements nonzero void BasisSelect(const Gambit::Array&unitv, const Gambit::Array&rowv, Gambit::Vector&colv) const; }; #endif // LPTAB_H gambit-0.2010.09.01/src/tools/lp/lptab.imp0000644000076500007650000004641311435216102014616 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/lptab.imp // Implementation of LP tableaus // // 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 "lptab.h" // --------------------------------------------------------------------------- // LPTableau member definitions // --------------------------------------------------------------------------- template LPTableau::LPTableau(const Gambit::Matrix &A, const Gambit::Vector &b) : Tableau(A,b), dual(A.MinRow(),A.MaxRow()), unitcost(A.MinRow(),A.MaxRow()), cost(A.MinCol(),A.MaxCol()) { }; template LPTableau::LPTableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : Tableau(A,art,b), dual(A.MinRow(),A.MaxRow()), unitcost(A.MinRow(),A.MaxRow()), cost(A.MinCol(),A.MaxCol()+art.Length()) { }; template LPTableau::LPTableau(const LPTableau &orig) : Tableau(orig), dual(orig.dual), unitcost(orig.unitcost), cost(orig.cost) { } template LPTableau::~LPTableau() { } template LPTableau& LPTableau::operator=(const LPTableau &orig) { Tableau::operator=(orig); if(this!= &orig) { dual=orig.dual; unitcost= orig.unitcost; cost= orig.cost; } return *this; } // cost-based functions template<> void LPTableau::SetCost(const Gambit::Vector& c) { int i; if(cost.First()==c.First() && cost.Last()==c.Last()) { for(i=cost.First();i<=cost.Last();i++) cost[i] = c[i]*(Gambit::Rational)Tableau::TotDenom(); for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i] = (Gambit::Rational)0; Refactor(); SolveDual(); return; } if(c.First()!=cost.First()) throw Gambit::DimensionException(); if(c.Last()!=(cost.Last()+unitcost.Length())) throw Gambit::DimensionException(); for(i=c.First();i<=cost.Last();i++) cost[i]=c[i]*(Gambit::Rational)Tableau::TotDenom(); for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i]=c[cost.Length()+i-unitcost.First()+1]; // gout << "\nc: " << c.First() << " " << c.Last() << " " << c; // gout << "\ncost: " << cost.First() << " " << cost.Last() << " " << cost; // gout << "\nunit: " << unitcost.First() << " " << unitcost.Last() << " " << unitcost; //** added for Gambit::Rational Refactor(); SolveDual(); } template<> void LPTableau::SetCost(const Gambit::Vector& c) { int i; if(cost.First()==c.First() && cost.Last()==c.Last()) { for(i=cost.First();i<=cost.Last();i++) cost[i] = c[i]; for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i] = (double)0; Refactor(); SolveDual(); return; } if(c.First()!=cost.First()) throw Gambit::DimensionException(); if(c.Last()!=(cost.Last()+unitcost.Length())) throw Gambit::DimensionException(); for(i=c.First();i<=cost.Last();i++) cost[i]=c[i]; for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i]=c[cost.Length()+i-unitcost.First()+1]; // gout << "\nc: " << c.First() << " " << c.Last() << " " << c; // gout << "\ncost: " << cost.First() << " " << cost.Last() << " " << cost; // gout << "\nunit: " << unitcost.First() << " " << unitcost.Last() << " " << unitcost; //** added for Gambit::Rational Refactor(); SolveDual(); } template void LPTableau::SetCost(const Gambit::Vector &uc, const Gambit::Vector &c) { if(cost.First()!=c.First() || cost.Last()!=c.Last()) throw Gambit::DimensionException(); if(unitcost.First()!=uc.First() || unitcost.Last()!=uc.Last()) throw Gambit::DimensionException(); int i; for(i=cost.First();i<=cost.Last();i++) cost[i]=c[i]; for(i=unitcost.First();i<=unitcost.Last();i++) unitcost[i]=uc[i]; SolveDual(); } template Gambit::Vector LPTableau::GetCost(void) const { Gambit::Vector x(cost.First(),cost.Last()); for(int i=x.First();i<=x.Last();i++)x[i]=cost[i]; return x; // return cost; } template Gambit::Vector LPTableau::GetUnitCost(void) const { Gambit::Vector x(unitcost.First(),unitcost.Last()); for(int i=x.First();i<=x.Last();i++)x[i]=unitcost[i]; return x; } template<> double LPTableau::TotalCost(void) { Gambit::Vector tmpcol(MinRow(),MaxRow()); BasisSelect(unitcost,cost,tmpcol); return tmpcol*solution; } template<> Gambit::Rational LPTableau::TotalCost(void) { Gambit::Vector tmpcol(MinRow(),MaxRow()); Gambit::Vector sol(MinRow(),MaxRow()); BasisSelect(unitcost,cost,tmpcol); BasisVector(sol); for(int i=tmpcol.First();i<=tmpcol.Last();i++) if(Label(i)>0)tmpcol[i]/=(Gambit::Rational)Tableau::TotDenom(); return tmpcol*sol; } template<> void LPTableau::DualVector(Gambit::Vector &L) const { L= dual; } template<> void LPTableau::DualVector(Gambit::Vector &out) const { out= dual; // for(int i=out.First();i<=out.Last();i++) // if(Label(i)>=0) out[i]*=TotDenom(); } template T LPTableau::RelativeCost(int col) const { Gambit::Vector tmpcol(this->MinRow(),this->MaxRow()); if( col<0 ) { return unitcost[-col] - dual[-col]; } else { GetColumn(col, (Gambit::Vector &)tmpcol); return cost[col] - dual*tmpcol; } } /* template void LPTableau::RelativeCostVector(Gambit::Vector &relunitcost, Gambit::Vector &relcost) const { if(!A->CheckColumn(relunitcost)) throw Gambit::DimensionException(); if(!A->CheckRow(relcost)) throw Gambit::DimensionException(); relunitcost= unitcost - dual; relcost= cost - dual*A; // pre multiplication not defined? } */ template void LPTableau::SolveDual() { Gambit::Vector tmpcol1(this->MinRow(),this->MaxRow()); BasisSelect(unitcost,cost,tmpcol1); SolveT(tmpcol1,dual); } // Redefined functions template void LPTableau::Refactor() { // gout << "\nIn LPTableau::Refactor()"; Tableau::Refactor(); SolveDual(); } template void LPTableau::Pivot(int outrow,int col) { // gout << "\nIn LPTableau::Pivot() "; // gout << "outrow: " << outrow << " col: " << col; // BigDump(gout); Tableau::Pivot(outrow,col); SolveDual(); } template void LPTableau::ReversePivots(Gambit::List > &PivotList) { Gambit::Vector tmpcol(this->MinRow(),this->MaxRow()); // gout << "\nIn LPTableau::ReversePivots"; bool flag; int i,j,k,enter; T ratio,a_ij,a_ik,b_i,b_k,c_j,c_k,c_jo,x; Gambit::List BestSet; Gambit::Array pivot(2); Gambit::Vector tmpdual(this->MinRow(),this->MaxRow()); Gambit::Vector solution(tmpcol); //$$ BasisVector(solution); //$$ // BigDump(gout); // gout << "\ncost: " << GetCost(); // gout << "\nunitcost: " << GetUnitCost() << "\n"; // for(i=MinCol();i<=MaxCol();i++) gout << " " << RelativeCost(i); // for(i=MinRow();i<=MaxRow();i++) gout << " " << RelativeCost(-i); for(j=-this->MaxRow();j<=this->MaxCol();j++) if(j && !this->Member(j) && !this->IsBlocked(j)) { SolveColumn(j,tmpcol); // gout << "\nColumn " << j; // gout << "\nPivCol = " << tmpcol; // gout << "\ncurrentSolCol = " << solution; // find all i where prior tableau is primal feasible BestSet = Gambit::List(); for(i=this->MinRow();i<=this->MaxRow();i++) if(GtZero(tmpcol[i])) BestSet.Append(i); if(BestSet.Length()>0) { ratio = solution[BestSet[1]]/tmpcol[BestSet[1]]; // find max ratio for(i=2;i<=BestSet.Length();i++) { x = solution[BestSet[i]]/tmpcol[BestSet[i]]; if(GtZero(x-ratio)) ratio = x; } // eliminate nonmaximizers for(i=BestSet.Length();i>=1;i--) { x = solution[BestSet[i]]/tmpcol[BestSet[i]]; if(LtZero(x-ratio)) BestSet.Remove(i); } // check that j would be the row to exit in prior tableau // first check that prior pivot entry > 0 for(i=BestSet.Length();i>=1;i--) { a_ij = (T)1/tmpcol[BestSet[i]]; if(LeZero(a_ij)) { // gout << "\nj not row to exit in prior tableau: a_ij <= 0"; BestSet.Remove(i); } else { // next check that prior pivot entry attains max ratio b_i = solution[BestSet[i]]/tmpcol[BestSet[i]]; ratio = b_i/a_ij; flag = 0; for(k=tmpcol.First();k<=tmpcol.Last() && !flag;k++) if(k!=BestSet[i]) { a_ik = - a_ij * tmpcol[k]; b_k = solution[k] - b_i*tmpcol[k]; if(GtZero(a_ik) && GtZero(b_k/a_ik -ratio)) { // gout << "\nj not row to exit in prior tableau: "; // gout << "higher ratio at row= " << k; BestSet.Remove(i); flag = 1; } else if(GtZero(a_ik) && EqZero(b_k/a_ik-ratio) && this->Label(k)GetColumn(j,tmpcol); */ GetColumn(j,tmpcol); // gout << "\ncol " << j << ": " << tmpcol; a_ij = tmpdual*tmpcol; c_j = RelativeCost(j); if(EqZero(a_ij)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "a_ij=0"; BestSet.Remove(i); } else { ratio = c_j/a_ij; // gout << " ratio: " << ratio; if(enter<0) a_ik = tmpdual[-enter]; else { GetColumn(enter,tmpcol); // A->GetColumn(enter,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(enter); c_jo = c_k - a_ik * ratio; // gout << "\ntmpdual = " << tmpdual << "\n"; // gout << " c_j:" << c_j; // gout << " c_k:" << c_k; // gout << " c_jo:" << c_jo; // gout << " a_ij:" << a_ij; // gout << " a_ik:" << a_ik; if(GeZero(c_jo)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "c_jo<0"; BestSet.Remove(i); } else { flag=0; for(k=-this->b->Last();kGetColumn(k,tmpcol); GetColumn(k,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(k); c_jo = c_k - a_ik * ratio; if(LtZero(c_jo)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "c_jo < 0 for k = " << k; BestSet.Remove(i); flag=1; } } } } } // gout << "\nafter checking cols, BestSet = "; // BestSet.Dump(gout); if(BestSet.Length()>0) for(i=1;i<=BestSet.Length();i++) { pivot[1] = BestSet[i]; pivot[2] = j; PivotList.Append(pivot); } } } template bool LPTableau::IsReversePivot(int i, int j) { Gambit::Vector tmpcol(this->MinRow(),this->MaxRow()); // first check that pivot preserves primal feasibility // gout << "\nin IsReversePivot, i= " << i << " j = "<< j; SolveColumn(j,tmpcol); Gambit::Vector solution(tmpcol); //$$ BasisVector(solution); //$$ // gout << "\ncurrentPivCol = " << tmpcol; // gout << "\ncurrentSolCol = " << solution; if(LeZero(tmpcol[i])) { // gout << "\nPrior tableau not primal feasible: currentPivCol[i] <= 0"; return 0; } int k; T ratio = solution[i]/tmpcol[i]; // gout << "\nratio = " << ratio; for(k=tmpcol.First();k<=tmpcol.Last();k++) if(GtZero(tmpcol[k]) && GtZero(solution[k]/tmpcol[k]-ratio)) { // gout << "\nPrior tableau not primal feasible: i not min ratio"; return 0; } // check that j would be the row to exit in prior tableau T a_ij,a_ik,b_i,b_k,c_j,c_k,c_jo; a_ij = (T)1/tmpcol[i]; if(LeZero(a_ij)) { // gout << "\nj not row to exit in prior tableau: a_ij <= 0"; return 0; } b_i = solution[i]/tmpcol[i]; ratio = b_i/a_ij; for(k=tmpcol.First();k<=tmpcol.Last();k++) if(k!=i) { a_ik = - a_ij * tmpcol[k]; b_k = solution[k] - b_i*tmpcol[k]; if(GtZero(a_ik) && GtZero(b_k/a_ik -ratio)) { // gout << "\nj not row to exit in prior tableau: "; // gout << "higher ratio at row= " << k; return 0; } if(GtZero(a_ik) && EqZero(b_k/a_ik-ratio) && this->Label(k)GetColumn(enter,tmpcol); GetColumn(enter,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(enter); c_jo = c_k - a_ik * ratio; if(GeZero(c_jo)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "c_jo<0"; return 0; } for(k=-this->b->Last();kGetColumn(k,tmpcol); GetColumn(k,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(k); c_jo = c_k - a_ik * ratio; if(LtZero(c_jo)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "c_jo < 0 for k = " << k; return 0; } } // gout << "\nValid Reverse pivot at i = " << i << " j = " << j; return 1; } template void LPTableau::DualReversePivots(Gambit::List > &/*list*/) { } template bool LPTableau::IsDualReversePivot(int i, int j) { // first check that pivot preserves dual feasibility // gout << "\nin IsDualReversePivot, i= " << i << " j = "<< j; int k; Gambit::Vector tmpcol(this->MinRow(),this->MaxRow()); Gambit::Vector tmpdual(this->MinRow(),this->MaxRow()); tmpcol = (T)0; tmpcol[i]=(T)1; SolveT(tmpcol,tmpdual); Gambit::Vector solution(tmpcol); //$$ BasisVector(solution); //$$ // gout << "\ncurrentPivCol = " << tmpcol; // gout << "\ncurrentSolCol = " << solution; T a_ij,a_ik,c_j,c_k,ratio; /* if( j<0 ) { tmpcol=(T)0; tmpcol[-j]=(T)1; } else A->GetColumn(j,tmpcol); */ GetColumn(j,tmpcol); a_ij = tmpdual*tmpcol; c_j = RelativeCost(j); if(GeZero(a_ij)) { // gout << "\nPrior tableau not dual feasible: "; // gout << "a_ij>=0"; return 0; } ratio = c_j/a_ij; for(k=-this->b->Last();k<=cost.Last();k++) if(k!=0) { if(k<0) a_ik=tmpdual[-k]; else { // A->GetColumn(k,tmpcol); GetColumn(k,tmpcol); a_ik = tmpdual*tmpcol; } c_k = RelativeCost(k); if(LtZero(a_ik) && GtZero(c_k/a_ik-ratio)) { // gout << "\nPrior tableau not dual feasible: "; // gout << "\nhigher ratio for k = " << k; return 0; } } // check that i would be the column to enter in prior tableau int enter = this->Label(i); // gout << "\nenter = " << enter; if(enter<0) a_ik = tmpdual[-enter]; else { // A->GetColumn(enter,tmpcol); GetColumn(enter,tmpcol); a_ik = tmpdual*tmpcol; } a_ik = a_ik/a_ij; c_k = RelativeCost(enter); c_k -= a_ik * c_j; if(GeZero(a_ik)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "a_ik>=0"; return 0; } ratio = c_k/a_ik; for(k=-this->b->Last();k<=cost.Last();k++) if(k!=0) { if(k<0) a_ik=tmpdual[-k]; else { // A->GetColumn(k,tmpcol); GetColumn(k,tmpcol); a_ik = tmpdual*tmpcol; } a_ik = a_ik/a_ij; c_k = RelativeCost(k); c_k -= a_ik * c_j; if(LtZero(a_ik) && GtZero(c_k/a_ik- ratio)) { // gout << "\ni not col to enter in prior tableau: "; // gout << "\nhigher ratio for k = " << k; return 0; } if(kb->First();k<=this->b->Last();k++) if(k!=i) { b_k = solution[k] - b_i * tmpcol[k]; if(GtZero(b_k) && this->Label(k) int LPTableau::LastLabel( void ) { return this->artificial.Last(); } template void LPTableau::BasisSelect(const Gambit::Array &rowv, Gambit::Vector &colv) const { for(int i=this->basis.First(); i<=this->basis.Last(); i++) { if(this->basis.Label(i)<0) colv[i]= 0; else colv[i]= rowv[this->basis.Label(i)]; } } template void LPTableau::BasisSelect(const Gambit::Array &unitv, const Gambit::Array &rowv, Gambit::Vector &colv ) const { for(int i=this->basis.First(); i<=this->basis.Last(); i++) { if(this->basis.Label(i)<0) colv[i]= unitv[-this->basis.Label(i)]; else colv[i]= rowv[this->basis.Label(i)]; } } template LPTableau::BadPivot::~BadPivot() { } template std::string LPTableau::BadPivot::GetDescription(void) const { return "Bad Pivot in LPTableau"; } gambit-0.2010.09.01/src/tools/lp/ludecomp.cc0000644000076500007650000000215011435216102015112 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/ludecomp.cc // Instantiation of LU decomposition // // 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 "ludecomp.imp" #include "libgambit/rational.h" template class EtaMatrix< double >; template class LUdecomp< double >; template class EtaMatrix< Gambit::Rational >; template class LUdecomp< Gambit::Rational >; gambit-0.2010.09.01/src/tools/lp/ludecomp.h0000644000076500007650000001120211435216102014752 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/ludecomp.h // Interface to LU decomposition classes // // 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 LUDECOMP_H #define LUDECOMP_H #include "libgambit/libgambit.h" #include "basis.h" template class Tableau; // --------------------------------------------------------------------------- // Class EtaMatrix // --------------------------------------------------------------------------- template class EtaMatrix { public: int col; Gambit::Vector etadata; EtaMatrix(int c, Gambit::Vector &v) : col(c), etadata(v) {}; // required for list class bool operator==(const EtaMatrix &) const; bool operator!=(const EtaMatrix &) const; }; // --------------------------------------------------------------------------- // Class LUdecomp // --------------------------------------------------------------------------- template class LUdecomp { private: Tableau &tab; Basis &basis; Gambit::List< EtaMatrix > L; Gambit::List< EtaMatrix > U; Gambit::List< EtaMatrix > E; Gambit::List< int > P; Gambit::Vector scratch1; // scratch vectors so we don't reallocate them Gambit::Vector scratch2; // everytime we do something. int refactor_number; int iterations; int total_operations; const LUdecomp *parent; int copycount; // don't use this copy constructor LUdecomp( const LUdecomp &a); // don't use the equals operator, use the Copy function instead LUdecomp& operator=(const LUdecomp&); public: class BadPivot : public Gambit::Exception { public: virtual ~BadPivot(); std::string GetDescription(void) const; }; class BadCount : public Gambit::Exception { public: virtual ~BadCount(); std::string GetDescription(void) const; }; // ------------------------ // Constructors, Destructor // ------------------------ // copy constructor // note: Copying will fail an assertion if you try to update or delete // the original before the copy has been deleted, refactored // Or set to something else. LUdecomp( const LUdecomp &, Tableau & ); // Decompose given matrix LUdecomp( Tableau &, int rfac = 0 ); // Destructor ~LUdecomp(); // -------------------- // Public Members // -------------------- // copies the LUdecomp given (expect for the basis &). void Copy( const LUdecomp &, Tableau & ); // replace (update) the column given with the vector given. void update( int, int matcol ); // matcol is the column number in the matrix // refactor void refactor(); // solve: Bk d = a void solve (const Gambit::Vector &, Gambit::Vector & ) const; // solve: y Bk = c void solveT( const Gambit::Vector &, Gambit::Vector & ) const; // set number of etamatrices added before refactoring; // if number is set to zero, refactoring is done automatically. // if number is < 0, no refactoring is done; void SetRefactor( int ); //------------------- // Private Members //------------------- private: void FactorBasis(); void GaussElem( Gambit::Matrix &, int, int ); bool CheckBasis(); bool RefactorCheck(); void BTransE( Gambit::Vector & ) const; void FTransE( Gambit::Vector & ) const; void BTransU( Gambit::Vector & ) const; void FTransU( Gambit::Vector & ) const; void LPd_Trans( Gambit::Vector & ) const; void yLP_Trans( Gambit::Vector & ) const; void VectorEtaSolve( const Gambit::Vector &v, const EtaMatrix &, Gambit::Vector &y ) const; void EtaVectorSolve( const Gambit::Vector &v, const EtaMatrix &, Gambit::Vector &d ) const; void yLP_mult( const Gambit::Vector &y, int j, Gambit::Vector &) const; void LPd_mult( Gambit::Vector &d, int j, Gambit::Vector &) const; }; // end of class LUdecomp #endif // LUDECOMP_H gambit-0.2010.09.01/src/tools/lp/ludecomp.imp0000644000076500007650000002563711435216102015331 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/ludecomp.imp // Implementation of LU decomposition // // 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 "ludecomp.h" #include "tableau.h" // --------------------------------------------------------------------------- // Class EtaMatrix // --------------------------------------------------------------------------- template bool EtaMatrix::operator==(const EtaMatrix &a) const { return ( col == a.col && etadata == a.etadata ); } template bool EtaMatrix::operator!=(const EtaMatrix &a) const { return ( col != a.col || etadata != a.etadata ); } // --------------------------------------------------------------------------- // Class LUdecomp // --------------------------------------------------------------------------- // ------------------------- // C-tors, D-tor, Operators // ------------------------- // copy constructor template LUdecomp::LUdecomp( const LUdecomp &a, Tableau &t) : tab(t), basis(t.GetBasis()), scratch1(basis.First(), basis.Last()), scratch2(basis.First(), basis.Last()), refactor_number( a.refactor_number ), iterations(a.iterations), total_operations( a.total_operations), parent(&a), copycount(0) { ((LUdecomp &)*parent).copycount++; } // Decomposes given matrix template LUdecomp::LUdecomp( Tableau &t, int rfac/* = 0 */) : tab(t), basis(t.GetBasis()), scratch1(basis.First(), basis.Last()), scratch2(basis.First(), basis.Last()), refactor_number(rfac), iterations(0), parent(NULL), copycount(0) { int m = basis.Last() - basis.First() +1; total_operations = (m - 1) * m * (2 * m - 1) / 6; } // Destructor template LUdecomp::~LUdecomp() { if ( parent != NULL ) ((LUdecomp &) *parent).copycount--; if(copycount != 0) throw BadCount(); } // ------------------------- // Public Members // ------------------------- // use this to copy ludecomps.... template void LUdecomp::Copy(const LUdecomp &orig, Tableau &t) { if(this != &orig) { if (parent != NULL) ((LUdecomp &) *parent).copycount--; tab = t; basis = t.GetBasis(); L = Gambit::List >(); P = Gambit::List(); E = Gambit::List >(); U = Gambit::List >(); refactor_number = orig.refactor_number; iterations = orig.iterations; total_operations = orig.total_operations; parent = &orig; copycount = 0; ((LUdecomp &)*parent).copycount++; } } template void LUdecomp::update( int col, int matcol ) { if( copycount != 0 ) throw BadCount(); int m = basis.Last() - basis.First() + 1; iterations++; if (( refactor_number > 0 && iterations >= refactor_number ) || ( refactor_number == 0 && RefactorCheck()) ) refactor(); else { tab.GetColumn( matcol, scratch1); solve( scratch1, scratch1 ); if ( scratch1[col] == (T) 0 ) throw BadPivot(); E.Append( EtaMatrix( col, scratch1 ) ); total_operations += iterations * m + 2 * m * m; } } template void LUdecomp::refactor( ) { L = Gambit::List >(); U = Gambit::List >(); E = Gambit::List >(); P = Gambit::List(); if ( !basis.IsIdent() ) FactorBasis(); iterations = 0; int m = basis.Last() - basis.First() + 1; total_operations = (m - 1) * m * (2 * m - 1) / 6; if (parent != NULL) ((LUdecomp &)*parent).copycount--; parent = NULL; } template void LUdecomp::solveT( const Gambit::Vector &c, Gambit::Vector &y ) const { if ( c.First() != y.First() || c.Last() != y.Last() ) throw Gambit::DimensionException(); if ( c.First() != basis.First() || c.Last() != basis.Last()) throw Gambit::DimensionException(); y = c; if ( basis.IsIdent() != true ) { BTransE( y ); if ( parent != NULL ) (*parent).solveT( y, y ); else { FTransU( y ); yLP_Trans( y ); } } } template void LUdecomp::solve( const Gambit::Vector &a, Gambit::Vector &d ) const { if ( a.First() != d.First() || a.Last() != d.Last() ) throw Gambit::DimensionException(); if ( a.First() != basis.First() || a.Last() != basis.Last()) throw Gambit::DimensionException(); d = a; if ( basis.IsIdent() != true ) { if ( parent != NULL ) (*parent).solve(a,d); else { LPd_Trans( d ); BTransU( d ); } FTransE( d ); } } template void LUdecomp::SetRefactor( int a ) { refactor_number = a; } // ----------------- // Private Members // ----------------- template void LUdecomp::FactorBasis() { int i, j, piv; T pivVal; Gambit::Matrix B(basis.First(), basis.Last(), basis.First(), basis.Last()); for( i = basis.First(); i <= basis.Last(); i++ ) { tab.GetColumn( basis.Label(i), scratch2 ); basis.CheckBasis(); B.SetColumn( i, scratch2 ); } for ( i = B.MinRow(); i <= B.MaxRow(); i++) { pivVal = Gambit::abs ( B(i, i)); piv = i; for ( j = i+1; j <= B.MaxRow(); j++) { if ( B( j, i ) * B( j, i ) > pivVal * pivVal ) { piv = j; pivVal = B( j, i ); } } P.Append(piv); B.SwitchRows(i,piv); scratch2 = (T) 0; scratch2[i] = (T) 1 / B( i, i ); for ( j = i+1; j <= B.MaxRow(); j++ ) { scratch2[j] = - B(j, i) / B(i,i); } L.Append( EtaMatrix(i, scratch2) ); GaussElem(B, i, i); } for ( j = B.MinCol(); j <= B.MaxCol(); j++ ) { B.GetColumn( j, scratch2 ); U.Append( EtaMatrix( j, scratch2 )); } } template void LUdecomp::GaussElem(Gambit::Matrix &B, int row, int col) { if( B(row, col) == (T) 0) throw BadPivot(); int i,j; for ( j = col+1; j <= B.MaxCol(); j++) B( row, j ) = B( row, j ) / B( row, col ); for ( i = row+1; i <= B.MaxRow(); i++ ) for ( j = col+1; j <= B.MaxCol(); j++ ) { B( i, j ) = B( i, j ) - ( B( i, col ) * B( row, j ) ); } for ( i = row+1; i <= B.MaxRow(); i++ ) B( i , col ) = 0; B( row, col ) = (T) 1; } template void LUdecomp::BTransE( Gambit::Vector &y ) const { int i; for ( i = E.Length(); i >= 1; i-- ) { ((LUdecomp &) *this).scratch2 = y; VectorEtaSolve(scratch2, E[i], y ); } } template void LUdecomp::FTransU( Gambit::Vector &y ) const { int i; for ( i = 1; i <= U.Length(); i++ ) { ((LUdecomp &) *this).scratch2 = y; VectorEtaSolve(scratch2, U[i], y ); } } template void LUdecomp::VectorEtaSolve( const Gambit::Vector &v, const EtaMatrix &eta, Gambit::Vector &y ) const { int i, j; if ( v.First() != y.First() || v.Last() != y.Last() ) throw Gambit::DimensionException(); for ( i = v.First(); i <= v.Last(); i++ ) { y[i] = v[i]; if ( i == eta.col ) { for ( j = v.First(); j <= v.Last(); j++ ) if ( j != eta.col ) y[i] -= v[j] * eta.etadata[j]; y[i] /= eta.etadata[i]; } } } template void LUdecomp::FTransE( Gambit::Vector &y ) const { int i; for ( i = 1; i <= E.Length(); i++ ) { ((LUdecomp &) *this).scratch2 = y; EtaVectorSolve(scratch2, E[i], y ); } } template void LUdecomp::BTransU( Gambit::Vector &y ) const { int i; for ( i = U.Length(); i >= 1; i-- ) { ((LUdecomp &) *this).scratch2 = y; EtaVectorSolve(scratch2, U[i], y ); } } template void LUdecomp::EtaVectorSolve( const Gambit::Vector &v, const EtaMatrix &eta, Gambit::Vector &d ) const { int i; T temp; if ( v.First() != d.First() || v.Last() != d.Last() ) throw Gambit::DimensionException(); if ( eta.etadata[eta.col] == (T)0 ) throw BadPivot(); // or we would have a singular matrix temp = v[eta.col] / eta.etadata[eta.col]; for ( i = v.First(); i <= v.Last(); i++) { if ( i == eta.col ) d[i] = temp; else { d[i] = v[i] - temp * eta.etadata[i]; } } } template void LUdecomp::yLP_Trans( Gambit::Vector &y ) const { int j; for (j = L.Length(); j >= 1; j--) { yLP_mult( y, j, ((LUdecomp &) *this).scratch2 ); y = scratch2; } } template void LUdecomp::yLP_mult( const Gambit::Vector &y, int j, Gambit::Vector &ans ) const { if ( ans.First() != y.First() || ans.Last() != y.Last() ) throw Gambit::DimensionException(); T temp; int i, k, l; l = j + y.First() - 1; for (i = y.First(); i <= y.Last(); i++) { if ( i != L[j].col) ans[i] = y[i]; else { for ( k = ans.First(), temp = (T) 0; k <= ans.Last(); k++) { temp += y[k] * L[j].etadata[k]; } ans[i] = temp; } } temp = ans[l]; ans[l] = ans[P[j]]; ans[P[j]] = temp; } template void LUdecomp::LPd_Trans( Gambit::Vector &d ) const { int j; for (j = 1; j <= L.Length(); j++) { LPd_mult( d, j, ((LUdecomp &) *this).scratch2 ); d = scratch2; } } template void LUdecomp::LPd_mult( Gambit::Vector &d, int j, Gambit::Vector &ans ) const { if ( d.First() != ans.First() || d.Last() != ans.Last() ) throw Gambit::DimensionException(); T temp; int i, k; k = j + d.First() - 1; temp = d[k]; d[k] = d[P[j]]; d[P[j]] = temp; for (i = d.First(); i <= d.Last(); i++) { if ( i == L[j].col ) ans[i] = d[i] * L[j].etadata[i]; else { ans[i] = d[i] + d[ L[j].col ] * L[j].etadata[i]; } } d[P[j]] = d[k]; d[k] = temp; } template bool LUdecomp::CheckBasis() { int i; bool ret = true; for (i = basis.First(); i <= basis.Last() && ret != false; i++) ret = ret && ( basis.Label(i) == -i ); return ret; } template bool LUdecomp::RefactorCheck() { int m = basis.Last() - basis.First() + 1; int i = iterations * (iterations * m + 2 * m * m ); int k = total_operations + iterations * m + 2 * m * m; bool tmp; tmp = ( i > k ); return tmp; } template LUdecomp::BadCount::~BadCount() { } template std::string LUdecomp::BadCount::GetDescription(void) const { return "Bad Reference count in LUdecomp"; } template LUdecomp::BadPivot::~BadPivot() { } template std::string LUdecomp::BadPivot::GetDescription(void) const { return "Bad Pivot in LUdecomp"; } gambit-0.2010.09.01/src/tools/lp/nfglp.cc0000644000076500007650000001126411441446351014426 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/nfglp.cc // Implementation of algorithm to compute mixed strategy equilibria // of constant sum normal form games via linear programming // // 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 #include #include "libgambit/libgambit.h" #include "lpsolve.h" using namespace Gambit; extern int g_numDecimals; // // The routine to actually solve the LP // This routine takes an LP of the form // maximize c x subject to Ax>=b and x>=0, // except the last 'nequals' constraints in A hold with equality. // It expects the array p_primal to be the same length as the // number of columns in A, and the routine returns the primal solution; // similarly, the array p_dual should have the same length as the // number of rows in A, and the routine returns the dual solution. // // To implement your own custom solver for this problem, simply // replace this function. // template bool SolveLP(const Matrix &A, const Vector &b, const Vector &c, int nequals, Array &p_primal, Array &p_dual) { LPSolve LP(A, b, c, nequals); if (!LP.IsAborted()) { BFS cbfs((T) 0); LP.OptBFS(cbfs); for (int i = 1; i <= A.NumColumns(); i++) { if (cbfs.IsDefined(i)) { p_primal[i] = cbfs(i); } else { p_primal[i] = (T) 0; } } for (int i = 1; i <= A.NumRows(); i++) { if (cbfs.IsDefined(-i)) { p_dual[i] = cbfs(-i); } else { p_dual[i] = (T) 0; } } return true; } else { return false; } } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedStrategyProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream.setf(std::ios::fixed); p_stream << "," << std::setprecision(g_numDecimals) << p_profile[i]; } p_stream << std::endl; } void PrintProfile(std::ostream &p_stream, const std::string &p_label, const MixedStrategyProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { p_stream << "," << p_profile[i]; } p_stream << std::endl; } // // Convert the LP solution represented by the vectors // (p_primal, p_dual) back to a strategy profile. // The primal vector is the mixed strategy for player 1, and the // dual the mixed strategy for player 2. // template void PrintSolution(const StrategySupport &p_support, const Array &p_primal, const Array &p_dual) { int n1 = p_support.NumStrategies(1); int n2 = p_support.NumStrategies(2); MixedStrategyProfile profile(p_support); for (int j = 1; j <= n1; j++) { profile[p_support.GetStrategy(1, j)] = p_primal[j]; } for (int j = 1; j <= n2; j++) { profile[p_support.GetStrategy(2, j)] = p_dual[j]; } PrintProfile(std::cout, "NE", profile); } // // Compute and print one equilibrium by solving a linear program based // on the strategic game representation. // template void SolveStrategic(const Game &p_game) { StrategySupport support(p_game); int m = support.NumStrategies(1); int k = support.NumStrategies(2); Matrix A(1,k+1,1,m+1); Vector b(1,k+1); Vector c(1,m+1); PureStrategyProfile profile(support.GetGame()); T minpay = p_game->GetMinPayoff() - Rational(1); for (int i = 1; i <= k; i++) { profile.SetStrategy(support.GetStrategy(2, i)); for (int j = 1; j <= m; j++) { profile.SetStrategy(support.GetStrategy(1, j)); A(i, j) = Rational(minpay) - profile.GetPayoff(1); } A(i,m+1) = (T) 1; } for (int j = 1; j <= m; j++) { A(k+1,j) = (T) 1; } A(k+1,m+1) = (T) 0; b = (T) 0; b[k+1] = (T) 1; c = (T) 0; c[m+1] = (T) 1; Array primal(A.NumColumns()), dual(A.NumRows()); if (SolveLP(A, b, c, 1, primal, dual)) { PrintSolution(support, primal, dual); } } template void SolveStrategic(const Game &); template void SolveStrategic(const Game &); gambit-0.2010.09.01/src/tools/lp/tableau.cc0000644000076500007650000000174511435216102014730 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/tableau.cc // Instantiation of tableau classes // // 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 "libgambit/rational.h" #include "tableau.imp" #include gambit-0.2010.09.01/src/tools/lp/tableau.h0000644000076500007650000001144111435216102014564 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/tableau.h // Interface to tableau class // // 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 TABLEAU_H #define TABLEAU_H #include "btableau.h" #include "ludecomp.h" template class Tableau; template class LPTableau; // --------------------------------------------------------------------------- // We have different implementations of Tableau for double and gbtRational, // but with the same interface // --------------------------------------------------------------------------- // // Tableau // template<> class Tableau : public TableauInterface{ private: LUdecomp B; // LU decomposition Gambit::Vector tmpcol; // temporary column vector, to avoid allocation public: // constructors and destructors Tableau(const Gambit::Matrix &A, const Gambit::Vector &b); Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); Tableau(const Tableau&); virtual ~Tableau(); Tableau& operator=(const Tableau&); // pivoting int CanPivot(int outgoing,int incoming); void Pivot(int outrow,int col); // pivot -- outgoing is row, incoming is column void BasisVector(Gambit::Vector &x) const; // solve M x = (*b) void SolveColumn(int, Gambit::Vector &); // column in new basis void Solve(const Gambit::Vector &b, Gambit::Vector &x); // solve M x = b void SolveT(const Gambit::Vector &c, Gambit::Vector &y); // solve y M = c // raw Tableau functions void Refactor(); void SetRefactor(int); void SetConst(const Gambit::Vector &bnew); void SetBasis( const Basis &); // set new Tableau bool IsFeasible(); bool IsLexMin(); }; // // Tableau // template<> class Tableau : public TableauInterface{ private: int remap(int col_index) const; // aligns the column indexes Gambit::Matrix GetInverse(); Gambit::Matrix Tabdat; // This caries the full tableau Gambit::Vector Coeff; // and coeffieient vector Gambit::Integer totdenom; // This carries the denominator for Q data or 1 for Z Gambit::Integer denom; // This is the denominator for the simplex Gambit::Vector tmpcol; // temporary column vector, to avoid allocation void MySolveColumn(int, Gambit::Vector &); // column in new basis protected: Gambit::Array nonbasic; //** nonbasic variables -- should be moved to Basis public: class BadDenom : public Gambit::Exception { public: virtual ~BadDenom(); std::string GetDescription(void) const; }; // constructors and destructors Tableau(const Gambit::Matrix &A, const Gambit::Vector &b); Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b); Tableau(const Tableau&); virtual ~Tableau(); Tableau& operator=(const Tableau&); // pivoting int CanPivot(int outgoing,int incoming); void Pivot(int outrow,int col); // pivot -- outgoing is row, incoming is column void SolveColumn(int, Gambit::Vector &); // column in new basis void GetColumn(int, Gambit::Vector &) const; // column in new basis // raw Tableau functions void Refactor(); void SetRefactor(int); void SetConst(const Gambit::Vector &bnew); void SetBasis( const Basis &); // set new Tableau void Solve(const Gambit::Vector &b, Gambit::Vector &x); // solve M x = b void SolveT(const Gambit::Vector &c, Gambit::Vector &y); // solve y M = c bool IsFeasible(); bool IsLexMin(); void BasisVector(Gambit::Vector &out) const; Gambit::Integer TotDenom() const; }; #endif // TABLEAU_H gambit-0.2010.09.01/src/tools/lp/tableau.imp0000644000076500007650000003672411435216102015135 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/lp/tableau.imp // Implementation of tableau class // // 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 "tableau.h" // --------------------------------------------------------------------------- // Tableau method definitions // --------------------------------------------------------------------------- // Constructors and Destructor Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Vector &b) : TableauInterface(A,b), B(*this), tmpcol(b.First(),b.Last()) { Solve(b, solution); }; Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : TableauInterface(A,art,b), B(*this), tmpcol(b.First(),b.Last()) { Solve(b, solution); }; Tableau::Tableau(const Tableau &orig) : TableauInterface(orig), B(orig.B,*this), tmpcol(orig.tmpcol) { } Tableau::~Tableau() { } Tableau& Tableau::operator=(const Tableau &orig) { TableauInterface::operator=(orig); if(this!= &orig) { B.Copy(orig.B,*this); tmpcol = orig.tmpcol; } return *this; } // // pivoting operations // int Tableau::CanPivot(int outlabel, int col) { SolveColumn(col,tmpcol); double val = tmpcol[basis.Find(outlabel)]; if(val <=eps2 && val >= -eps2) return 0; return 1; } void Tableau::Pivot(int outrow,int col) { if(!RowIndex(outrow) || !ValidIndex(col)) throw BadPivot(); // int outlabel = Label(outrow); // gout << "\noutrow:" << outrow; // gout << " outlabel: " << outlabel; // gout << " inlabel: " << col; // BigDump(gout); basis.Pivot(outrow,col); B.update(outrow, col); Solve(*b, solution); npivots++; // BigDump(gout); } void Tableau::SolveColumn(int col, Gambit::Vector &out) { //** can we use tmpcol here, instead of allocating new vector? Gambit::Vector tmpcol2(MinRow(),MaxRow()); GetColumn(col,tmpcol2); Solve(tmpcol2,out); } void Tableau::BasisVector(Gambit::Vector &out) const { out= solution; } // // raw Tableau functions // void Tableau::Refactor() { B.refactor(); //** is re-solve necessary here? Solve(*b, solution); } void Tableau::SetRefactor(int n) { B.SetRefactor(n); } void Tableau::SetConst(const Gambit::Vector &bnew) { if(bnew.First()!=b->First() || bnew.Last()!=b->Last()) throw Gambit::DimensionException(); b=&bnew; Solve(*b, solution); } //** this function is not currently used. Drop it? void Tableau::SetBasis(const Basis &in) { basis= in; B.refactor(); Solve(*b, solution); } void Tableau::Solve(const Gambit::Vector &b, Gambit::Vector &x) { B.solve(b,x); } void Tableau::SolveT(const Gambit::Vector &c, Gambit::Vector &y) { B.solveT(c,y); //** gout << "\nTableau::SolveT(), y: " << y; // gout << "\nc: " << c; } bool Tableau::IsFeasible() { //** is it really necessary to solve first here? Solve(*b, solution); for(int i=solution.First();i<=solution.Last();i++) if(solution[i]>=eps2) return false; return true; } bool Tableau::IsLexMin() { int i,j; for(i=MinRow();i<=MaxRow();i++) if(EqZero(solution[i])) for(j=-MaxRow();j method definitions // --------------------------------------------------------------------------- Gambit::Integer find_lcd(const Gambit::Matrix &mat) { Gambit::Integer lcd(1); for(int i=mat.MinRow();i<=mat.MaxRow();i++) for(int j=mat.MinCol();j<=mat.MaxCol();j++) lcd = lcm(mat(i,j).denominator(),lcd); return lcd; } Gambit::Integer find_lcd(const Gambit::Vector &vec) { Gambit::Integer lcd(1); for(int i=vec.First();i<=vec.Last();i++) lcd = lcm(vec[i].denominator(),lcd); return lcd; } // Constructors and Destructor Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Vector &b) : TableauInterface(A,b), Tabdat(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()), Coeff(b.First(),b.Last()), denom(1), tmpcol(b.First(),b.Last()), nonbasic(A.MinCol(),A.MaxCol()) { int j; for(j=MinCol();j<=MaxCol();j++) nonbasic[j] = j; totdenom = lcm(find_lcd(A),find_lcd(b)); if(totdenom<=0) throw BadDenom(); for (int i = b.First();i<=b.Last();i++) { Gambit::Rational x = b[i]*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Coeff[i] = x.numerator(); } for (int i = MinRow();i<=MaxRow();i++) for (int j = MinCol();j<=MaxCol();j++) { Gambit::Rational x = A(i,j)*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Tabdat(i,j) = x.numerator(); } for (int i = b.First();i<=b.Last();i++) solution[i] = (Gambit::Rational)Coeff[i]; } Tableau::Tableau(const Gambit::Matrix &A, const Gambit::Array &art, const Gambit::Vector &b) : TableauInterface(A,art,b), Tabdat(A.MinRow(),A.MaxRow(),A.MinCol(),A.MaxCol()+art.Length()), Coeff(b.First(),b.Last()), denom(1), tmpcol(b.First(),b.Last()), nonbasic(A.MinCol(),A.MaxCol()+art.Length()) { int j; for(j=MinCol();j<=MaxCol();j++) nonbasic[j] = j; totdenom = lcm(find_lcd(A),find_lcd(b)); if(totdenom<=0) throw BadDenom(); for (int i = b.First();i<=b.Last();i++) { Gambit::Rational x = b[i]*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Coeff[i] = x.numerator(); } for (int i = MinRow();i<=MaxRow();i++) { for (int j = MinCol();j<=A.MaxCol();j++) { Gambit::Rational x = A(i,j)*(Gambit::Rational)totdenom; if(x.denominator() != 1) throw BadDenom(); Tabdat(i,j) = x.numerator(); } for (int j = A.MaxCol()+1;j<=MaxCol();j++) Tabdat(artificial[j],j) = totdenom; } for (int i = b.First();i<=b.Last();i++) solution[i] = (Gambit::Rational)Coeff[i]; } Tableau::Tableau(const Tableau &orig) : TableauInterface(orig), Tabdat(orig.Tabdat), Coeff(orig.Coeff), totdenom(orig.totdenom), denom(orig.denom), tmpcol(orig.tmpcol), nonbasic(orig.nonbasic) { } Tableau::~Tableau() { } Tableau& Tableau::operator=(const Tableau &orig) { TableauInterface::operator=(orig); if(this!= &orig) { Tabdat = orig.Tabdat; Coeff = orig.Coeff; totdenom = orig.totdenom; denom = orig.denom; tmpcol = orig.tmpcol; nonbasic = orig.nonbasic; } return *this; } // Aligns the column indexes int Tableau::remap(int col_index) const { int i = nonbasic.First(); while(i <= nonbasic.Last() && nonbasic[i] !=col_index) { i++;} if(i > nonbasic.Last()) throw Gambit::DimensionException(); return i; } Gambit::Matrix Tableau::GetInverse() { Gambit::Vector mytmpcol(tmpcol.First(),tmpcol.Last()); Gambit::Matrix inv(MinRow(),MaxRow(),MinRow(),MaxRow()); for(int i=inv.MinCol();i<=inv.MaxCol();i++){ MySolveColumn(-i,mytmpcol); inv.SetColumn(i,mytmpcol); } return inv; } // pivoting operations int Tableau::CanPivot(int outlabel, int col) { MySolveColumn(col,tmpcol); Gambit::Rational val = tmpcol[basis.Find(outlabel)]; if(val == (Gambit::Rational)0) return 0; // if(val <=eps2 && val >= -eps2) return 0; return 1; } void Tableau::Pivot(int outrow,int in_col) { // gout << "\nIn Tableau::Pivot() "; // gout << " outrow:" << outrow; // gout << " inlabel: " << in_col; if(!RowIndex(outrow) || !ValidIndex(in_col)) throw BadPivot(); int outlabel = Label(outrow); // gout << "\noutrow:" << outrow; // gout << " outlabel: " << outlabel; // gout << " inlabel: " << in_col; // BigDump(gout); // gout << "\ndenom: " << denom << " totdenom: " << totdenom; // gout << " product: " << denom*totdenom; // gout << "\nTabdat: loc 1\n " << Tabdat; // gout << "\nInverse: loc 1\n " << GetInverse(); int col; int row(outrow); int i,j; // loop-control variables col = remap(in_col); // Pivot Algorithm: // i* denotes Pivot Row // j* denotes Pivot Column // C is the Tableau // Cij is the (i,j)th component of C // X denotes multiplication // d is the denominator (initially 1) // // 1: Copy row i (don't need to implement this) // 2: Zero column j excepting the Pivot Element (done second) // 3: Cij=(Ci*j*XCij-Ci*jXCij*)/d for all other elements (done first) // 4: d=Ci*j* (done last) // Step 3 for(i=Tabdat.MinRow();i<=Tabdat.MaxRow();++i){ if(i!=row){ for(j=Tabdat.MinCol();j<=Tabdat.MaxCol();++j){ if(j!=col){ Tabdat(i,j) = (Tabdat(row,col)*Tabdat(i,j)-Tabdat(row,j)*Tabdat(i,col))/denom; } } Coeff[i] = (Tabdat(row,col)*Coeff[i]-Coeff[row]*Tabdat(i,col))/denom; } } // Step 2 // Note: here we are moving the old basis column into column 'col' for(i=Tabdat.MinRow();i<=Tabdat.MaxRow();++i){ if(i!=row) Tabdat(i,col)=-Tabdat(i,col); } // Step 4 Gambit::Integer old_denom = denom; denom=Tabdat(row,col); Tabdat(row,col)=old_denom; // BigDump(gout); npivots++; basis.Pivot(outrow,in_col); nonbasic[col] = outlabel; for (i = solution.First();i<=solution.Last();i++) //** solution[i] = (Gambit::Rational)(Coeff[i])/(Gambit::Rational)(denom*totdenom); solution[i] = Gambit::Rational(Coeff[i]*sign(denom*totdenom)); //gout << "Bottom \n" << Tabdat << '\n'; // BigDump(gout); // gout << "\ndenom: " << denom << " totdenom: " << totdenom; // gout << "\nTabdat: loc 2\n " << Tabdat; // gout << "\nInverse: loc 2\n " << GetInverse(); // Refactor(); } void Tableau::SolveColumn(int in_col, Gambit::Vector &out) { Gambit::Vector tempcol(tmpcol.First(),tmpcol.Last()); if(Member(in_col)) { out = (Gambit::Rational)0; out[Find(in_col)] = Gambit::Rational(abs(denom)); } else { int col = remap(in_col); Tabdat.GetColumn(col,tempcol); for(int i=tempcol.First();i<=tempcol.Last();i++) out[i] = (Gambit::Rational)(tempcol[i]) * (Gambit::Rational)(sign(denom*totdenom)); } out=out/(Gambit::Rational)abs(denom); if(in_col < 0) out*=totdenom; for(int i=out.First();i<=out.Last();i++) if(Label(i)<0) out[i]=(Gambit::Rational)out[i]/(Gambit::Rational)totdenom; } void Tableau::MySolveColumn(int in_col, Gambit::Vector &out) { Gambit::Vector tempcol(tmpcol.First(),tmpcol.Last()); if(Member(in_col)) { out = (Gambit::Rational)0; out[Find(in_col)] = Gambit::Rational(abs(denom)); } else { int col = remap(in_col); Tabdat.GetColumn(col,tempcol); for(int i=tempcol.First();i<=tempcol.Last();i++) out[i] = (Gambit::Rational)(tempcol[i]) * (Gambit::Rational)(sign(denom*totdenom)); } } void Tableau::GetColumn(int col, Gambit::Vector &out) const { TableauInterface::GetColumn(col,out); if(col>=0) out*=Gambit::Rational(totdenom); } void Tableau::Refactor() { Gambit::Vector mytmpcol(tmpcol); //BigDump(gout); //** Note -- we may need to recompute totdenom here, if A and b have changed. //gout << "\ndenom: " << denom << " totdenom: " << totdenom; totdenom = lcm(find_lcd(*A),find_lcd(*b)); if(totdenom<=0) throw BadDenom(); // gout << "\ndenom: " << denom << " totdenom: " << totdenom; int i,j; Gambit::Matrix inv(GetInverse()); Gambit::Matrix Tabnew(Tabdat.MinRow(),Tabdat.MaxRow(),Tabdat.MinCol(),Tabdat.MaxCol()); for(i=nonbasic.First();i<=nonbasic.Last();i++) { GetColumn(nonbasic[i],mytmpcol); // if(nonbasic[i]>=0) mytmpcol*=Gambit::Rational(totdenom); Tabnew.SetColumn(i,inv * mytmpcol * (Gambit::Rational)sign(denom*totdenom)); //gout << "\nMyTmpCol \n" << mytmpcol; } //gout << "\nInv: \n" << inv; //gout << "\nTabdat:\n" << Tabdat; //gout << "\nTabnew:\n" << Tabnew; Gambit::Vector Coeffnew(Coeff.First(),Coeff.Last()); Coeffnew = inv * (*b) * totdenom * (Gambit::Rational)sign(denom*totdenom); //gout << "\nCoeff:\n" << Coeff; //gout << "\nCoeffew:\n" << Coeffnew; for(i=Tabdat.MinRow();i<=Tabdat.MaxRow();i++) { if(Coeffnew[i].denominator() != 1) throw BadDenom(); Coeff[i] = Coeffnew[i].numerator(); for(j=Tabdat.MinCol();j<=Tabdat.MaxCol();j++) { if(Tabnew(i,j).denominator() != 1) throw BadDenom(); Tabdat(i,j) = Tabnew(i,j).numerator(); } } //BigDump(gout); } void Tableau::SetRefactor(int) { } void Tableau::SetConst(const Gambit::Vector &bnew) { b=&bnew; Refactor(); } //** this function is not currently used. Drop it? void Tableau::SetBasis(const Basis &in) { basis= in; //** this has to be changed -- Need to start over and pivot to new basis. // B.refactor(); // B.solve(*b, solution); } // solve M x = b void Tableau::Solve(const Gambit::Vector &b, Gambit::Vector &x) { // Here, we do x = V * b, where V = M inverse x = (GetInverse() * b )/(Gambit::Rational)abs(denom); } // solve y M = c void Tableau::SolveT(const Gambit::Vector &c, Gambit::Vector &y) { // Here we do y = c * V, where V = M inverse y = (c * GetInverse()) /(Gambit::Rational)abs(denom); } bool Tableau::IsFeasible() { for(int i=solution.First();i<=solution.Last();i++) if(solution[i]>=eps2) return false; return true; } bool Tableau::IsLexMin() { int i,j; for(i=MinRow();i<=MaxRow();i++) if(EqZero(solution[i])) for(j=-MaxRow();j::BasisVector(Gambit::Vector &out) const { out = solution; out= out/(Gambit::Rational)abs(denom) ; for(int i=out.First();i<=out.Last();i++) if(Label(i)<0) out[i]=out[i]/(Gambit::Rational)totdenom; } Gambit::Integer Tableau::TotDenom() const { return totdenom; } Tableau::BadDenom::~BadDenom() { } std::string Tableau::BadDenom::GetDescription(void) const { return "Bad Denominator in Tableau"; } gambit-0.2010.09.01/src/tools/simpdiv/0000777000076500007650000000000011441457126014133 500000000000000gambit-0.2010.09.01/src/tools/simpdiv/nfgsimpdiv.cc0000644000076500007650000004646511435216102016531 00000000000000// // This file is part of Gambit // Copyright (c) 1994-2010, The Gambit Project (http://www.gambit-project.org) // // FILE: src/tools/simpdiv/nfgsimpdiv.cc // Compute Nash equilibria via simplicial subdivision on the normal form // // 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 #include #include #include #include #include "libgambit/libgambit.h" // // simpdiv is a simplicial subdivision algorithm with restart, for finding // mixed strategy solutions to general finite n-person games. It is based on // van Der Laan, Talman and van Der Heyden, Math in Oper Res, 1987. // // The program accepts a normal form game file on standard input. // // The program accepts the following command-line options: // -v: Verbose output. Lists the profile computed at each stage of the // mesh refinement. Default is off, in which case the program only // prints the (approximate) Nash equilibrium of the last refinement. // // -s : A list of strategy profiles to use as starting points // // -f: Print profiles in floating-point (even though the algorithm inherently // computes using rational numbers) // // -d #: Number of decimals to show in floating-point output // (Only has an effect in conjunction with -f) // // -r #: Generate random starting points with denominator #. // // -n #: Stop after # equilibria (only effective with -r) // // -g #: Multiplier for grid restart (default is 2) // // // Some history: // // Original code was written by R. McKelvey. The implementation was // kludged to conform to the new standard algorithm interface (namely, // by removing passing a reference to the game in the ctor); truly, // the algorithm needs recoded from the ground up to remove gotos and // simplify things. (TLT, 6/2002) // // // Global options // bool g_verbose = false; bool g_useFloat = false; int g_numDecimals = 6; int g_gridResize = 2; class nfgSimpdiv { private: int m_nRestarts, m_leashLength; int t, ibar; Gambit::Rational d,pay,maxz,bestz; Gambit::Rational Simplex(Gambit::MixedStrategyProfile &); Gambit::Rational getlabel(Gambit::MixedStrategyProfile &yy, Gambit::Array &, Gambit::PVector &); void update(Gambit::RectArray &, Gambit::RectArray &, Gambit::PVector &, const Gambit::PVector &, int j, int i); void getY(Gambit::MixedStrategyProfile &x, Gambit::PVector &, const Gambit::PVector &, const Gambit::PVector &, const Gambit::PVector &, const Gambit::RectArray &, int k); void getnexty(Gambit::MixedStrategyProfile &x, const Gambit::RectArray &, const Gambit::PVector &, int i); int get_c(int j, int h, int nstrats, const Gambit::PVector &); int get_b(int j, int h, int nstrats, const Gambit::PVector &); public: nfgSimpdiv(void); virtual ~nfgSimpdiv(); int NumRestarts(void) const { return m_nRestarts; } void SetNumRestarts(int p_nRestarts) { m_nRestarts = p_nRestarts; } int LeashLength(void) const { return m_leashLength; } void SetLeashLength(int p_leashLength) { m_leashLength = p_leashLength; } void Solve(const Gambit::Game &, const Gambit::MixedStrategyProfile &); }; //------------------------------------------------------------------------- // nfgSimpdiv: Constructor and destructor //------------------------------------------------------------------------- nfgSimpdiv::nfgSimpdiv(void) : m_nRestarts(20), m_leashLength(0) { t = 0; ibar = 1; } nfgSimpdiv::~nfgSimpdiv() { } //------------------------------------------------------------------------- // nfgSimpdiv: Private member functions //------------------------------------------------------------------------- Gambit::Rational nfgSimpdiv::Simplex(Gambit::MixedStrategyProfile &y) { Gambit::Array ylabel(2); Gambit::RectArray labels(y.Length(), 2), pi(y.Length(), 2); Gambit::PVector U(y.GetSupport().NumStrategies()), TT(y.GetSupport().NumStrategies()); Gambit::PVector ab(y.GetSupport().NumStrategies()); Gambit::PVector besty(y.GetSupport().NumStrategies()); Gambit::PVector v(y.GetSupport().NumStrategies()); for (int i = 1; i <= v.Length(); i++) { v[i] = y[i]; } besty = y; int i = 0; int j, k, h, jj, hh,ii, kk,tot; Gambit::Rational maxz; // Label step0 not currently used, hence commented // step0:; ibar=1; t=0; for(j=1;j<=y.GetGame()->NumPlayers();j++) { for(h=1;h<=y.GetSupport().NumStrategies(j);h++) { TT(j,h)=0; U(j,h)=0; if(v(j,h)==Gambit::Rational(0))U(j,h)=1; ab(j,h)=Gambit::Rational(0); y[y.GetSupport().GetStrategy(j,h)]=v(j,h); } } step1:; maxz=getlabel(y, ylabel, besty); j=ylabel[1]; h=ylabel[2]; labels(ibar,1)=j; labels(ibar,2)=h; // Label case1a not currently used, hence commented // case1a:; if(TT(j,h)==0 && U(j,h)==0) { for(hh=1,tot=0;hh<=y.GetSupport().NumStrategies(j);hh++) if(TT(j,hh)==1 || U(j,hh)==1)tot++; if(tot==y.GetSupport().NumStrategies(j)-1)goto end; else { i=t+1; goto step2; } } /* case1b */ else if(TT(j,h)) { i=1; while(labels(i,1)!=j || labels(i,2)!=h || i==ibar) i++; goto step3; } /* case1c */ else if(U(j,h)) { k=h; while(U(j,k)){k++;if(k>y.GetSupport().NumStrategies(j))k=1;} if(TT(j,k)==0)i=t+1; else { i=1; while((pi(i,1)!=j || pi(i,2)!=k) && i<=t)i++; } goto step2; } step2:; getY(y,v,U,TT,ab,pi,i); pi.RotateDown(i,t+1); pi(i,1)=j; pi(i,2)=h; labels.RotateDown(i+1,t+2); ibar=i+1; t++; getnexty(y,pi,U,i); TT(j,h)=1; U(j,h)=0; goto step1; step3:; if(i==t+1)ii=t; else ii=i; j=pi(ii,1); h=pi(ii,2); k=h; if(i=(Gambit::Rational(m_leashLength))*d)) { for(hh=1,tot=0;hh<=y.GetSupport().NumStrategies(j);hh++) if(TT(j,hh)==1 || U(j,hh)==1)tot++; if(tot==y.GetSupport().NumStrategies(j)-1) { U(j,k)=1; goto end; } else { update(pi,labels,ab,U,j,i); U(j,k)=1; getnexty(y,pi,U,t); goto step1; } } /* case3b */ else if(i>=2 && i<=t && (y[y.GetSupport().GetStrategy(j,k)]<=Gambit::Rational(0) || (v(j,k)-y[y.GetSupport().GetStrategy(j,k)])>=(Gambit::Rational(m_leashLength))*d)) { goto step4; } /* case3c */ else if(i==t+1 && ab(j,kk)==Gambit::Rational(0)) { if(y[y.GetSupport().GetStrategy(j,h)]<=Gambit::Rational(0) || (v(j,h)-y[y.GetSupport().GetStrategy(j,h)])>=(Gambit::Rational(m_leashLength))*d)goto step4; else { k=0; while(ab(j,kk)==Gambit::Rational(0) && k==0) { if(kk==h)k=1; kk++; if(kk>y.GetSupport().NumStrategies(j))kk=1; } kk--; if(kk==0)kk=y.GetSupport().NumStrategies(j); if(kk==h)goto step4; else goto step5; } } else { if(i==1) getnexty(y,pi,U,1); else if(i<=t) getnexty(y,pi,U,i); else if(i==t+1) { j=pi(t,1); h=pi(t,2); hh=get_b(j,h,y.GetSupport().NumStrategies(j),U); y[y.GetSupport().GetStrategy(j,h)]-=d; y[y.GetSupport().GetStrategy(j,hh)]+=d; } update(pi,labels,ab,U,j,i); } goto step1; step4:; getY(y,v,U,TT,ab,pi,1); j=pi(i-1,1); h=pi(i-1,2); TT(j,h)=0; if(y[y.GetSupport().GetStrategy(j,h)]<=Gambit::Rational(0) || (v(j,h)-y[y.GetSupport().GetStrategy(j,h)])>=(Gambit::Rational(m_leashLength))*d)U(j,h)=1; labels.RotateUp(i,t+1); pi.RotateUp(i-1,t); t--; ii=1; while(labels(ii,1)!=j || labels(ii,2)!=h) {ii++;} i=ii; goto step3; step5:; k=kk; labels.RotateDown(1,t+1); ibar=1; pi.RotateDown(1,t); U(j,k)=0; jj=pi(1,1); hh=pi(1,2); kk=get_b(jj,hh,y.GetSupport().NumStrategies(jj),U); y[y.GetSupport().GetStrategy(jj,hh)]-=d; y[y.GetSupport().GetStrategy(jj,kk)]+=d; k=get_c(j,h,y.GetSupport().NumStrategies(j),U); kk=1; while(kk){ if(k==h)kk=0; ab(j,k)=(ab(j,k)-(Gambit::Rational(1))); k++; if(k>y.GetSupport().NumStrategies(j))k=1; } goto step1; end:; maxz=bestz; for(i=1;i<=y.GetGame()->NumPlayers();i++) for(j=1;j<=y.GetSupport().NumStrategies(i);j++) y[y.GetSupport().GetStrategy(i,j)]=besty(i,j); return maxz; } void nfgSimpdiv::update(Gambit::RectArray &pi, Gambit::RectArray &labels, Gambit::PVector &ab, const Gambit::PVector &U, int j, int i) { int jj, hh, k,f; f=1; if(i>=2 && i<=t) { pi.SwitchRows(i,i-1); ibar=i; } else if(i==1) { labels.RotateUp(1,t+1); ibar=t+1; jj=pi(1,1); hh=pi(1,2); if(jj==j) { k=get_c(jj,hh,ab.Lengths()[jj],U); while(f) { if(k==hh)f=0; ab(j,k)=ab(j,k) + (Gambit::Rational(1)); k++; if(k>ab.Lengths()[jj])k=1; } pi.RotateUp(1,t); } } else if(i==t+1) { labels.RotateDown(1,t+1); ibar=1; jj=pi(t,1); hh=pi(t,2); if(jj==j) { k=get_c(jj,hh,ab.Lengths()[jj],U); while(f) { if(k==hh)f=0; ab(j,k)= ab(j,k)-(Gambit::Rational(1)); k++; if(k>ab.Lengths()[jj])k=1; } pi.RotateDown(1,t); } } } void nfgSimpdiv::getY(Gambit::MixedStrategyProfile &x, Gambit::PVector &v, const Gambit::PVector &U, const Gambit::PVector &TT, const Gambit::PVector &ab, const Gambit::RectArray &pi, int k) { int j, h, i,hh; for(j=1;j<=x.GetGame()->NumPlayers();j++) for(h=1;h<=x.GetSupport().NumStrategies(j);h++) x[x.GetSupport().GetStrategy(j,h)]=v(j,h); for(j=1;j<=x.GetGame()->NumPlayers();j++) for(h=1;h<=x.GetSupport().NumStrategies(j);h++) if(TT(j,h)==1 || U(j,h)==1) { x[x.GetSupport().GetStrategy(j,h)]+=(d*ab(j,h)); hh=h-1; if(hh==0)hh=x.GetSupport().NumStrategies(j); x[x.GetSupport().GetStrategy(j,hh)]-=(d*ab(j,h)); } i=2; while(i<=k) { getnexty(x,pi,U,i-1); i++; } } void nfgSimpdiv::getnexty(Gambit::MixedStrategyProfile &x, const Gambit::RectArray &pi, const Gambit::PVector &U, int i) { int j,h,hh; //assert(i>=1); j=pi(i,1); h=pi(i,2); x[x.GetSupport().GetStrategy(j,h)]+=d; hh=get_b(j,h,x.GetSupport().NumStrategies(j),U); x[x.GetSupport().GetStrategy(j,hh)]-=d; } int nfgSimpdiv::get_b(int j, int h, int nstrats, const Gambit::PVector &U) { int hh; hh=h-1; if(hh==0)hh=nstrats; while(U(j,hh)) { hh--; if(hh==0)hh=nstrats; } return hh; } int nfgSimpdiv::get_c(int j, int h, int nstrats, const Gambit::PVector &U) { int hh; hh=get_b(j,h,nstrats,U); hh++; if(hh > nstrats)hh=1; return hh; } Gambit::Rational nfgSimpdiv::getlabel(Gambit::MixedStrategyProfile &yy, Gambit::Array &ylabel, Gambit::PVector &besty) { int i,j,jj; Gambit::Rational maxz,payoff,maxval; maxz=(Gambit::Rational(-1000000)); ylabel[1]=1; ylabel[2]=1; for(i=1;i<=yy.GetGame()->NumPlayers();i++) { payoff=Gambit::Rational(0); maxval=(Gambit::Rational(-1000000)); jj=0; for(j=1;j<=yy.GetSupport().NumStrategies(i);j++) { pay=yy.GetStrategyValue(yy.GetSupport().GetStrategy(i,j)); payoff+=(yy[yy.GetSupport().GetStrategy(i,j)]*pay); if(pay>maxval) { maxval=pay; jj=j; } } //assert(jj>0); if((maxval-payoff)>maxz) { maxz=maxval-payoff; ylabel[1]=i; ylabel[2]=jj; } } if(maxzNumPlayers();i++) for(j=1;j<=yy.GetSupport().NumStrategies(i);j++) besty(i,j)=yy[yy.GetSupport().GetStrategy(i,j)]; } return maxz; } //------------------------------------------------------------------------- // nfgSimpdiv: Main solution algorithm //------------------------------------------------------------------------- void PrintProfile(std::ostream &p_stream, const std::string &p_label, const Gambit::MixedStrategyProfile &p_profile) { p_stream << p_label; for (int i = 1; i <= p_profile.Length(); i++) { if (g_useFloat) { p_stream.setf(std::ios::fixed); p_stream << "," << std::setprecision(g_numDecimals) << ((double) p_profile[i]); } else { p_stream << "," << p_profile[i]; } } p_stream << std::endl; } bool ReadProfile(std::istream &p_stream, Gambit::MixedStrategyProfile &p_profile) { for (int i = 1; i <= p_profile.Length(); i++) { if (p_stream.eof() || p_stream.bad()) { return false; } p_stream >> p_profile[i]; if (i < p_profile.Length()) { char comma; p_stream >> comma; } } // Read in the rest of the line and discard std::string foo; std::getline(p_stream, foo); return true; } Gambit::Integer find_lcd(const Gambit::Vector &vec) { Gambit::Integer lcd(1); for (int i = vec.First(); i <= vec.Last(); i++) { lcd = lcm(vec[i].denominator(), lcd); } return lcd; } void nfgSimpdiv::Solve(const Gambit::Game &p_nfg, const Gambit::MixedStrategyProfile &p_start) { // A raft of initializations moved here from the former constructor. // This algorithm is in need of some serious reorganization! t = 0; ibar = 1; if (m_leashLength == 0) { m_leashLength = 32000; // not the best way to do this. Change this! } bestz = 1.0e30; // ditto Gambit::Integer k = find_lcd(p_start); d = Gambit::Rational(1, k); Gambit::MixedStrategyProfile y(p_start); if (g_verbose) { PrintProfile(std::cout, "start", y); } while (true) { const double TOL = 1.0e-10; d /= g_gridResize; maxz = Simplex(y); if (g_verbose) { PrintProfile(std::cout, ToText(d), y); } if (maxz < Gambit::Rational(TOL)) break; } PrintProfile(std::cout, "NE", y); } void Randomize(Gambit::MixedStrategyProfile &p_profile, int p_denom) { Gambit::Game nfg = p_profile.GetGame(); ((Gambit::Vector &) p_profile) = Gambit::Rational(0); for (int pl = 1; pl <= nfg->NumPlayers(); pl++) { int sum = 0; for (int st = 1; sum < p_denom && st < nfg->GetPlayer(pl)->NumStrategies(); st++) { double r = ((double) rand() / ((double) (RAND_MAX) + 1.0)); double x = r * (p_denom - sum + 1); int y = (int) x; // y is now uniform on [0, (p_denom-sum)]. p_profile[p_profile.GetSupport().GetStrategy(pl, st)] = Gambit::Rational(y, p_denom); sum += y; } p_profile[p_profile.GetSupport().GetStrategy(pl, nfg->GetPlayer(pl)->NumStrategies())] = Gambit::Rational(p_denom - sum, p_denom); } } void PrintBanner(std::ostream &p_stream) { p_stream << "Compute Nash equilibria using simplicial subdivision\n"; p_stream << "Gambit version " VERSION ", Copyright (C) 1994-2010, The Gambit Project\n"; p_stream << "This is free software, distributed under the GNU GPL\n\n"; } void PrintHelp(char *progname) { PrintBanner(std::cerr); std::cerr << "Usage: " << progname << " [OPTIONS]\n"; std::cerr << "Accepts game on standard input.\n"; std::cerr << "With no options, computes one approximate Nash equilibrium.\n\n"; std::cerr << "Options:\n"; std::cerr << " -d DECIMALS show equilibria as floating point, with DECIMALS digits\n"; std::cerr << " (default is to show as rational numbers)\n"; std::cerr << " -g MULT granularity of grid refinement at each step (default is 2)\n"; std::cerr << " -h print this help message\n"; std::cerr << " -r DENOM generate random starting points with denominator DENOM\n"; std::cerr << " -n COUNT number of starting points to generate (requires -r)\n"; std::cerr << " -s FILE file containing starting points\n"; std::cerr << " -q quiet mode (suppresses banner)\n"; std::cerr << " -v verbose mode (shows intermediate output)\n"; std::cerr << " (default is to only show equilibria)\n"; exit(1); } int main(int argc, char *argv[]) { opterr = 0; std::string startFile; bool useRandom = false; int randDenom = 1, stopAfter = 1; bool quiet = false; int c; while ((c = getopt(argc, argv, "g:hvn:r:s:d:qS")) != -1) { switch (c) { case 'd': g_numDecimals = atoi(optarg); g_useFloat = true; break; case 'g': g_gridResize = atoi(optarg); break; case 'h': PrintHelp(argv[0]); break; case 'r': useRandom = true; randDenom = atoi(optarg); break; case 'n': stopAfter = atoi(optarg); break; case 's': startFile = optarg; break; case 'q': quiet = true; break; case 'v': g_verbose = true; break; case 'S': break; case '?': if (isprint(optopt)) { std::cerr << argv[0] << ": Unknown option `-" << ((char) optopt) << "'.\n"; } else { std::cerr << argv[0] << ": Unknown option character `\\x" << optopt << "`.\n"; } return 1; default: abort(); } } if (!quiet) { PrintBanner(std::cerr); } try { Gambit::Game game = Gambit::ReadGame(std::cin); game->BuildComputedValues(); if (startFile != "") { std::ifstream startPoints(startFile.c_str()); while (!startPoints.eof() && !startPoints.bad()) { Gambit::MixedStrategyProfile start(game); if (ReadProfile(startPoints, start)) { nfgSimpdiv algorithm; algorithm.Solve(game, start); } } } else if (useRandom) { for (int i = 1; i <= stopAfter; i++) { Gambit::MixedStrategyProfile start(game); Randomize(start, randDenom); nfgSimpdiv algorithm; algorithm.Solve(game, start); } } else { Gambit::MixedStrategyProfile start(game); for (int pl = 1; pl <= game->NumPlayers(); pl++) { start[start.GetSupport().GetStrategy(pl, 1)] = Gambit::Rational(1); for (int st = 2; st <= game->GetPlayer(pl)->NumStrategies(); st++) { start[start.GetSupport().GetStrategy(pl, st)] = Gambit::Rational(0); } } nfgSimpdiv algorithm; algorithm.Solve(game, start); } return 0; } catch (Gambit::InvalidFileException) { std::cerr << "Error: Game not in a recognized format.\n"; return 1; } catch (...) { std::cerr << "Error: An internal error occurred.\n"; return 1; } }