merged;
authorLukas Stevens <mail@lukas-stevens.de>
Tue, 17 Aug 2021 17:09:20 +0200
changeset 74554 fc41b8c3267e
parent 74553 99fa80fa46cb (current diff)
parent 74424 62b0577123a5 (diff)
child 74558 59ec97f1665c
merged;
--- a/.hgignore	Wed Jul 07 15:40:00 2021 +0200
+++ b/.hgignore	Tue Aug 17 17:09:20 2021 +0200
@@ -16,8 +16,6 @@
 ^heaps/
 ^browser_info/
 ^doc/.*\.pdf
-^lib/classes/
-^src/Tools/jEdit/dist/
 ^src/Tools/VSCode/out/
 ^src/Tools/VSCode/extension/node_modules/
 ^Admin/jenkins/ci-extras/target/
--- a/Admin/Release/CHECKLIST	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/Release/CHECKLIST	Tue Aug 17 17:09:20 2021 +0200
@@ -15,6 +15,8 @@
 
 - test Isabelle/jEdit: print buffer
 
+- test Isabelle/jEdit: deactivate main plugin;
+
 - test "#!/usr/bin/env isabelle_scala_script";
 
 - test Windows 10 subsystem for Linux:
@@ -43,7 +45,7 @@
 
 - update https://isabelle.sketis.net/repos/isabelle-website
 
-- check doc/Contents, src/Tools/jEdit/dist/doc/Contents;
+- check doc/Contents, $JEDIT_HOME/doc/Contents;
 
 - test old HD display: Linux, Windows, macOS;
 
--- a/Admin/Windows/Cygwin/README	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/Windows/Cygwin/README	Tue Aug 17 17:09:20 2021 +0200
@@ -18,6 +18,7 @@
   - https://isabelle.sketis.net/cygwin_2018  (Isabelle2018)
   - https://isabelle.sketis.net/cygwin_2019  (Isabelle2019)
   - https://isabelle.sketis.net/cygwin_2020  (Isabelle2020)
+  - https://isabelle.sketis.net/cygwin_2021  (Isabelle2021)
 
 * Apache2 redirects for virtual host isabelle.conf:
 ```
@@ -43,6 +44,8 @@
   Redirect /cygwin_2019/noarch/release https://ftp.eq.uc.pt/software/pc/prog/cygwin/noarch/release
   Redirect /cygwin_2020/x86_64/release https://ftp.eq.uc.pt/software/pc/prog/cygwin/x86_64/release
   Redirect /cygwin_2020/noarch/release https://ftp.eq.uc.pt/software/pc/prog/cygwin/noarch/release
+  Redirect /cygwin_2021/x86_64/release https://ftp.eq.uc.pt/software/pc/prog/cygwin/x86_64/release
+  Redirect /cygwin_2021/noarch/release https://ftp.eq.uc.pt/software/pc/prog/cygwin/noarch/release
 ```
 
 * Quasi-component: "isabelle build_cygwin" (as Administrator)
--- a/Admin/Windows/launch4j/isabelle.xml	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/Windows/launch4j/isabelle.xml	Tue Aug 17 17:09:20 2021 +0200
@@ -15,7 +15,7 @@
   <manifest></manifest>
   <icon>{ICON}</icon>
   <classPath>
-    <mainClass>isabelle.Main</mainClass>
+    <mainClass>isabelle.jedit.Main</mainClass>
 {CLASSPATH}
   </classPath>
   <singleInstance>
--- a/Admin/build	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-#!/usr/bin/env bash
-#
-# Administrative build for Isabelle source distribution.
-
-## directory layout
-
-if [ -z "$ISABELLE_HOME" ]; then
-  unset CDPATH
-  ISABELLE_HOME="$(cd "$(dirname "$0")"; cd "$(pwd -P)"; cd ..; pwd)"
-  ISABELLE_TOOL="$ISABELLE_HOME/bin/isabelle"
-fi
-
-
-## diagnostics
-
-PRG="$(basename "$0")"
-
-function usage()
-{
-  cat <<EOF
-
-Usage: $PRG [MODULES]
-
-  Produce Isabelle distribution modules from current repository sources.
-  The MODULES list may contain any of the following:
-
-    all             all modules below
-    browser         graph browser
-    jars            Isabelle/Scala
-    jars_fresh      fresh build of jars
-
-EOF
-  exit 1
-}
-
-function fail()
-{
-  echo "$1" >&2
-  exit 2
-}
-
-
-## process command line
-
-[ "$#" -eq 0 ] && usage
-
-MODULES="$@"; shift "$#"
-
-
-## modules
-
-function build_all ()
-{
-  build_browser
-  build_jars
-}
-
-
-function build_browser ()
-{
-  pushd "$ISABELLE_HOME/lib/browser" >/dev/null
-  "$ISABELLE_TOOL" env ./build || exit $?
-  popd >/dev/null
-}
-
-
-function build_jars ()
-{
-  pushd "$ISABELLE_HOME" >/dev/null
-  "$ISABELLE_TOOL" env src/Pure/build-jars "$@" || exit $?
-  popd >/dev/null
-}
-
-
-## main
-
-#FIXME workarounds for scalac 2.11.0
-export CYGWIN="nodosfilewarning"
-function stty() { :; }
-export -f stty
-
-for MODULE in $MODULES
-do
-  case $MODULE in
-    all) build_all;;
-    browser) build_browser;;
-    jars) build_jars;;
-    jars_fresh) build_jars -f;;
-    *) fail "Bad module $MODULE"
-  esac
-done
--- a/Admin/build_history	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/build_history	Tue Aug 17 17:09:20 2021 +0200
@@ -5,5 +5,5 @@
 unset CDPATH
 THIS="$(cd "$(dirname "$0")"; pwd)"
 
-"$THIS/build" jars > /dev/null || exit $?
-exec "$THIS/../bin/isabelle_java" isabelle.Build_History "$@"
+"$THIS/../bin/isabelle" scala_build -q || exit $?
+"$THIS/../bin/isabelle_java" isabelle.Build_History "$@"
--- a/Admin/build_release	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/build_release	Tue Aug 17 17:09:20 2021 +0200
@@ -5,5 +5,5 @@
 unset CDPATH
 THIS="$(cd "$(dirname "$0")"; pwd)"
 
-"$THIS/build" jars || exit $?
-exec "$THIS/../bin/isabelle_java" isabelle.Build_Release "$@"
+"$THIS/../bin/isabelle" scala_build -q || exit $?
+"$THIS/../bin/isabelle_java" isabelle.Build_Release "$@"
--- a/Admin/components/PLATFORMS	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/components/PLATFORMS	Tue Aug 17 17:09:20 2021 +0200
@@ -38,9 +38,9 @@
   x86_64-darwin     macOS 10.13 High Sierra (lapbroy68 MacBookPro11,2)
                     macOS 10.14 Mojave (mini2 Macmini8,1)
                     macOS 10.15 Catalina (laramac01 Macmini8,1)
-                    macOS 11.1 Big Sur (mini1 Macmini8,1)
+                    macOS 11 Big Sur (mini1 Macmini8,1)
 
-  arm64-darwin      macOS 11.1 Big Sur
+  arm64-darwin      macOS 11 Big Sur
 
   x86_64-windows    Windows 10
   x86_64-cygwin     Cygwin 3.1.x https://isabelle.sketis.net/cygwin_2021 (x86_64/release)
--- a/Admin/components/components.sha1	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/components/components.sha1	Tue Aug 17 17:09:20 2021 +0200
@@ -123,6 +123,19 @@
 1f7a0b9829ecac6552b21e995ad0f0ac168634f3  isabelle_fonts-20210322.tar.gz
 916adccd2f40c55116b68b92ce1eccb24d4dd9a2  isabelle_setup-20210630.tar.gz
 c611e363287fcc9bdd93c33bef85fa4e66cd3f37  isabelle_setup-20210701.tar.gz
+a0e7527448ef0f7ce164a38a50dc26e98de3cad6  isabelle_setup-20210709.tar.gz
+e413706694b0968245ee15183af2d464814ce0a4  isabelle_setup-20210711.tar.gz
+d2c9fd7b73457a460111edd6eb93a133272935fb  isabelle_setup-20210715.tar.gz
+a5f478ba1088f67c2c86dc2fa7764b6d884e5ae5  isabelle_setup-20210716-1.tar.gz
+79fad009cb22aa5e7cb4aed3c810ad5f61790293  isabelle_setup-20210716.tar.gz
+692a39f716998e556ec9559c9ca362fc8fc9d5b6  isabelle_setup-20210717-1.tar.gz
+7322d6d84d75c486a58ed36630431db4499e3232  isabelle_setup-20210717-2.tar.gz
+14f8508bcae9140815bb23e430e26d2cbc504b81  isabelle_setup-20210717.tar.gz
+ca801d5c380ea896ee32b309ff19ae5f34538963  isabelle_setup-20210718.tar.gz
+ac9739e38e4fbbfce1a71a0987a57b22f83922d3  isabelle_setup-20210724-1.tar.gz
+4554679cc8ea31e539655810a14d14216b383d0e  isabelle_setup-20210724-2.tar.gz
+127a75ae33e97480d352087fcb9b47a632d77169  isabelle_setup-20210724.tar.gz
+309909ec6d43ae460338e9af54c1b2a48adcb1ec  isabelle_setup-20210726.tar.gz
 0b2206f914336dec4923dd0479d8cee4b904f544  jdk-11+28.tar.gz
 e12574d838ed55ef2845acf1152329572ab0cc56  jdk-11.0.10+9.tar.gz
 3e05213cad47dbef52804fe329395db9b4e57f39  jdk-11.0.2+9.tar.gz
@@ -166,6 +179,10 @@
 dfb087bd64c3e5da79430e0ba706b9abc559c090  jdk-8u66.tar.gz
 2ac389babd15aa5ddd1a424c1509e1c459e6fbb1  jdk-8u72.tar.gz
 caa0cf65481b6207f66437576643f41dabae3c83  jdk-8u92.tar.gz
+778fd85c827ec49d2d658a832d20e63916186b0d  jedit-20210715.tar.gz
+beb99f2cb0bd4e595c5c597d3970c46aa21616e4  jedit-20210717.tar.gz
+33dd96cd83f2c6a26c035b7a0ee57624655224c5  jedit-20210724.tar.gz
+0e4fd4d66388ddc760fa5fbd8d4a9a3b77cf59c7  jedit-20210802.tar.gz
 44775a22f42a9d665696bfb49e53c79371c394b0  jedit_build-20111217.tar.gz
 a242a688810f2bccf24587b0062ce8027bf77fa2  jedit_build-20120304.tar.gz
 4c948dee53f74361c097c08f49a1a5ff9b17bd1d  jedit_build-20120307.tar.gz
@@ -210,6 +227,7 @@
 0bdbd36eda5992396e9c6b66aa24259d4dd7559c  jedit_build-20210201.tar.gz
 a0744f1948abdde4bfb51dd4769b619e7444baf1  jedit_build-20210510-1.tar.gz
 837d6c8f72ecb21ad59a2544c69aadc9f05684c6  jedit_build-20210510.tar.gz
+7bdae3d24b10261f6cb277446cf9ecab6062bd6f  jedit_build-20210708.tar.gz
 0bd2bc2d9a491ba5fc8dd99df27c04f11a72e8fa  jfreechart-1.0.14-1.tar.gz
 8122526f1fc362ddae1a328bdbc2152853186fee  jfreechart-1.0.14.tar.gz
 d911f63a5c9b4c7335bb73f805cb1711ce017a84  jfreechart-1.5.0.tar.gz
@@ -370,6 +388,7 @@
 6e19948ff4a821e2052fc9b3ddd9ae343f4fcdbb  stack-1.9.3.tar.gz
 f969443705aa8619e93af5b34ea98d15cd7efaf1  stack-2.1.3.tar.gz
 ebd0221d038966aa8bde075f1b0189ff867b02ca  stack-2.5.1.tar.gz
+fa2d882ec45cbc8c7d2f3838b705a8316696dc66  stack-2.7.3.tar.gz
 1f4a2053cc1f34fa36c4d9d2ac906ad4ebc863fd  sumatra_pdf-2.1.1.tar.gz
 601e08d048d8e50b0729429c8928b667d9b6bde9  sumatra_pdf-2.3.2.tar.gz
 14d46c2eb1a34821703da59d543433f581e91df3  sumatra_pdf-2.4.tar.gz
--- a/Admin/components/main	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/components/main	Tue Aug 17 17:09:20 2021 +0200
@@ -8,9 +8,9 @@
 flatlaf-1.2
 idea-icons-20210508
 isabelle_fonts-20210322
-isabelle_setup-20210701
+isabelle_setup-20210726
 jdk-15.0.2+7
-jedit_build-20210510-1
+jedit-20210802
 jfreechart-1.5.1
 jortho-1.0-2
 kodkodi-1.5.6-1
@@ -23,7 +23,7 @@
 spass-3.8ds-2
 sqlite-jdbc-3.34.0
 ssh-java-20190323
-stack-2.5.1
+stack-2.7.3
 vampire-4.2.2
 verit-2020.10-rmx-1
 xz-java-1.8
--- a/Admin/cronjob/main	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/cronjob/main	Tue Aug 17 17:09:20 2021 +0200
@@ -8,6 +8,5 @@
 source "$HOME/.bashrc"
 
 export ISABELLE_IDENTIFIER="cronjob"
-"$THIS/../build" jars_fresh || exit $?
-
-exec "$THIS/../../bin/isabelle_java" isabelle.Isabelle_Cronjob "$@"
+"$THIS/../../bin/isabelle" scala_build -q || exit $?
+"$THIS/../../bin/isabelle_java" isabelle.Isabelle_Cronjob "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Admin/etc/build.props	Tue Aug 17 17:09:20 2021 +0200
@@ -0,0 +1,3 @@
+title = Isabelle/Scala/Admin
+module = $ISABELLE_HOME/lib/classes/isabelle_admin.jar
+services = isabelle.Admin_Tools
--- a/Admin/haskell/stack/README	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/haskell/stack/README	Tue Aug 17 17:09:20 2021 +0200
@@ -1,12 +1,12 @@
-This is stack 1.9.3 -- the Haskell Tool Stack.
+This is stack 2.5.1 -- the Haskell Tool Stack.
 
 See also https://www.haskellstack.org and executables from
-https://github.com/commercialhaskell/stack/releases as follows:
+https://github.com/commercialhaskell/stack/releases/tag/v2.7.3 as follows:
 
-  * x86_64-linux: stack-1.9.3-linux-x86_64-static.tar.gz
-  * x86_64-darwin: stack-1.9.3-osx-x86_64.tar.gz
-  * x86_64-windows: stack-1.9.3-windows-x86_64.tar.gz
+  * x86_64-linux: stack-2.7.3-linux-x86_64.tar.gz
+  * x86_64-darwin: stack-2.7.3-osx-x86_64.tar.gz
+  * x86_64-windows: stack-2.7.3-windows-x86_64.tar.gz
 
 
     Makarius
-    07-Dec-2018
+    25-Jul-2021
--- a/Admin/jenkins/build/ci_build_benchmark.scala	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/jenkins/build/ci_build_benchmark.scala	Tue Aug 17 17:09:20 2021 +0200
@@ -9,8 +9,8 @@
   def include = Nil
   def select = List(Path.explode("$ISABELLE_HOME/src/Benchmarks"))
 
-  def pre_hook(args: List[String]) = {}
-  def post_hook(results: Build.Results) = {}
+  def pre_hook(args: List[String]) = Result.ok
+  def post_hook(results: Build.Results) = Result.ok
 
   def selection = Sessions.Selection(session_groups = List("timing"))
 
--- a/Admin/lib/Tools/build_setup	Wed Jul 07 15:40:00 2021 +0200
+++ b/Admin/lib/Tools/build_setup	Tue Aug 17 17:09:20 2021 +0200
@@ -4,15 +4,6 @@
 #
 # DESCRIPTION: build component for Isabelle/Java setup tool
 
-## sources
-
-declare -a SOURCES=(
-  "Build_Scala.java"
-  "Environment.java"
-  "Setup.java"
-)
-
-
 ## usage
 
 PRG=$(basename "$0")
@@ -46,26 +37,6 @@
 [ -d "$COMPONENT_DIR" ] && fail "Directory already exists: \"$COMPONENT_DIR\""
 
 
-# build jar
-
-TARGET_DIR="$COMPONENT_DIR/lib"
-mkdir -p "$TARGET_DIR/isabelle/setup"
-
-declare -a ARGS=("-Xlint:unchecked")
-for SRC in "${SOURCES[@]}"
-do
-  ARGS["${#ARGS[@]}"]="$(platform_path "$ISABELLE_HOME/src/Tools/Setup/isabelle/setup/$SRC")"
-done
-
-isabelle_jdk javac -d "$TARGET_DIR" "${ARGS[@]}" || \
-  fail "Failed to compile sources"
-
-isabelle_jdk jar -c -f "$(platform_path "$TARGET_DIR/isabelle_setup.jar")" \
-  -e "isabelle.setup.Setup" -C "$TARGET_DIR" isabelle || fail "Failed to produce jar"
-
-rm -rf "$TARGET_DIR/isabelle"
-
-
 # etc/settings
 
 mkdir -p "$COMPONENT_DIR/etc"
@@ -77,6 +48,29 @@
 EOF
 
 
+# build jar
+
+TARGET_DIR="$COMPONENT_DIR/lib"
+mkdir -p "$TARGET_DIR/isabelle/setup"
+
+declare -a ARGS=("-Xlint:unchecked")
+
+SOURCES="$(perl -e 'while (<>) { if (m/(\S+\.java)/)  { print "$1 "; } }' "$ISABELLE_HOME/src/Tools/Setup/etc/build.props")"
+for SRC in $SOURCES
+do
+  ARGS["${#ARGS[@]}"]="$(platform_path "$ISABELLE_HOME/src/Tools/Setup/$SRC")"
+done
+
+isabelle_jdk javac $ISABELLE_JAVAC_OPTIONS -d "$TARGET_DIR" \
+  -classpath "$(platform_path "$ISABELLE_CLASSPATH")" "${ARGS[@]}" || \
+  fail "Failed to compile sources"
+
+isabelle_jdk jar -c -f "$(platform_path "$TARGET_DIR/isabelle_setup.jar")" \
+  -e "isabelle.setup.Setup" -C "$TARGET_DIR" isabelle || fail "Failed to produce jar"
+
+rm -rf "$TARGET_DIR/isabelle"
+
+
 # README
 
 cat > "$COMPONENT_DIR/README" <<EOF
--- a/CONTRIBUTORS	Wed Jul 07 15:40:00 2021 +0200
+++ b/CONTRIBUTORS	Tue Aug 17 17:09:20 2021 +0200
@@ -6,6 +6,15 @@
 Contributions to this Isabelle version
 --------------------------------------
 
+* July 2021: Florian Haftmann
+  Further consolidation of bit operations and word types.
+
+* July 2021: Jasmin Blanchette and Martin Desharnais
+  Various improvements to Sledgehammer.
+
+* June 2021: Florian Haftmann
+  More context situations susceptible to global_interpretation.
+
 * March 2021: Lukas Stevens
   New order prover
 
--- a/NEWS	Wed Jul 07 15:40:00 2021 +0200
+++ b/NEWS	Tue Aug 17 17:09:20 2021 +0200
@@ -33,6 +33,9 @@
 
 * Support for built-in font substitution of jEdit text area.
 
+* The main plugin for Isabelle/jEdit can be deactivated and reactivated
+as documented --- was broken at least since Isabelle2018.
+
 
 *** Document preparation ***
 
@@ -180,17 +183,41 @@
 * Combinator "Fun.swap" resolved into a mere input abbreviation in
 separate theory "Transposition" in HOL-Combinatorics. INCOMPATIBILITY.
 
+* Infix syntax for bit operations AND, OR, XOR is now organized in
+bundle bit_operations_syntax. INCOMPATIBILITY.
+
 * Bit operations set_bit, unset_bit and flip_bit are now class
 operations. INCOMPATIBILITY.
 
+* Theory Bit_Operations is now part of HOL-Main. Minor INCOMPATIBILITY.
+
+* Simplified class hierarchy for bit operations: bit operations reside
+in classes (semi)ring_bit_operations, class semiring_bit_shifts is
+gone.
+
 * Abbreviation "max_word" has been moved to session Word_Lib in the AFP,
 as also have constants "shiftl1", "shiftr1", "sshiftr1", "bshiftr1",
 "setBit", "clearBit". See there further the changelog in theory Guide.
 INCOMPATIBILITY.
 
+* Reorganized classes and locales for boolean algebras.
+INCOMPATIBILITY.
+
 * New simp rules: less_exp, min.absorb1, min.absorb2, min.absorb3,
-min.absorb4, max.absorb1, max.absorb2, max.absorb3, max.absorb4.  Minor
-INCOMPATIBILITY.
+min.absorb4, max.absorb1, max.absorb2, max.absorb3, max.absorb4. Minor
+INCOMPATIBILITY.
+
+* Sledgehammer:
+ - Removed legacy "lam_lifting" (synonym for "lifting") from option
+   "lam_trans". Minor INCOMPATIBILITY.
+ - Renamed "hide_lams" to "opaque_lifting" in option "lam_trans".
+   Minor INCOMPATIBILITY.
+ - Added "opaque_combs" to option "lam_trans": lambda expressions are rewritten
+   using combinators, but the combinators are kept opaque, i.e. without
+   definitions.
+
+* Metis:
+ - Renamed option "hide_lams" to "opaque_lifting". Minor INCOMPATIBILITY.
 
 
 *** ML ***
@@ -261,6 +288,29 @@
 
 *** System ***
 
+* Each Isabelle component may specify a Scala/Java jar module
+declaratively via etc/build.props (file names are relative to the
+component directory). E.g. see $ISABELLE_HOME/etc/build.props with
+further explanations in the "system" manual.
+
+* Command-line tool "isabelle scala_build" allows to invoke the build
+process of all Scala/Java modules explicitly. Normally this is done
+implicitly on demand, e.g. for "isabelle scala" or "isabelle jedit".
+
+* Command-line tool "isabelle scala_project" is has been improved in
+various ways:
+  - sources from all components with etc/build.props are included,
+  - sources of for the jEdit text editor and the Isabelle/jEdit
+    plugins (jedit_base and jedit_main) are included by default,
+  - more sources may be given on the command-line,
+  - options -f and -D make the tool more convenient.
+
+* Isabelle/jEdit is now composed more conventionally from the original
+jEdit text editor in $JEDIT_HOME (with minor patches), plus two Isabelle
+plugins that are produced in $JEDIT_SETTINGS/jars on demand. The main
+isabelle.jedit module is now part of Isabelle/Scala (as one big
+$ISABELLE_SCALA_JAR).
+
 * ML profiling has been updated and reactivated, after some degration in
 Isabelle2021:
 
--- a/bin/isabelle	Wed Jul 07 15:40:00 2021 +0200
+++ b/bin/isabelle	Tue Aug 17 17:09:20 2021 +0200
@@ -45,7 +45,7 @@
 
 ## internal tool or usage (Scala)
 
-isabelle_admin_build jars || exit $?
+"$ISABELLE_HOME/lib/Tools/scala_build" || exit $?
 
 eval "declare -a JAVA_ARGS=($ISABELLE_TOOL_JAVA_OPTIONS)"
 exec isabelle java "${JAVA_ARGS[@]}" isabelle.Isabelle_Tool "$@"
--- a/bin/isabelle_java	Wed Jul 07 15:40:00 2021 +0200
+++ b/bin/isabelle_java	Tue Aug 17 17:09:20 2021 +0200
@@ -18,11 +18,8 @@
 
   eval "declare -a JAVA_ARGS=($ISABELLE_JAVA_SYSTEM_OPTIONS $ISABELLE_TOOL_JAVA_OPTIONS)"
 
-  if [ -f "$ISABELLE_HOME/src/Tools/jEdit/dist/jedit.jar" ]; then
-    classpath "$ISABELLE_HOME/src/Tools/jEdit/dist/jedit.jar"
-  fi
-
-  [ -n "$CLASSPATH" ] && classpath "$CLASSPATH"
+  classpath "$ISABELLE_SETUP_CLASSPATH"
+  classpath "$CLASSPATH"
 
   echo "$ISABELLE_ROOT"
   echo "$CYGWIN_ROOT"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/build.props	Tue Aug 17 17:09:20 2021 +0200
@@ -0,0 +1,293 @@
+title = Isabelle/Scala
+module = $ISABELLE_HOME/lib/classes/isabelle.jar
+main = isabelle.jedit.Main
+resources = \
+  lib/services/java.nio.charset.spi.CharsetProvider:META-INF/services/ \
+  lib/logo/isabelle_transparent-32.gif:isabelle/ \
+  lib/logo/isabelle_transparent.gif:isabelle/
+sources = \
+  src/HOL/SPARK/Tools/spark.scala \
+  src/HOL/Tools/ATP/system_on_tptp.scala \
+  src/HOL/Tools/Mirabelle/mirabelle.scala \
+  src/HOL/Tools/Nitpick/kodkod.scala \
+  src/Pure/Admin/afp.scala \
+  src/Pure/Admin/build_csdp.scala \
+  src/Pure/Admin/build_cygwin.scala \
+  src/Pure/Admin/build_doc.scala \
+  src/Pure/Admin/build_e.scala \
+  src/Pure/Admin/build_fonts.scala \
+  src/Pure/Admin/build_history.scala \
+  src/Pure/Admin/build_jcef.scala \
+  src/Pure/Admin/build_jdk.scala \
+  src/Pure/Admin/build_jedit.scala \
+  src/Pure/Admin/build_log.scala \
+  src/Pure/Admin/build_polyml.scala \
+  src/Pure/Admin/build_release.scala \
+  src/Pure/Admin/build_spass.scala \
+  src/Pure/Admin/build_sqlite.scala \
+  src/Pure/Admin/build_status.scala \
+  src/Pure/Admin/build_vampire.scala \
+  src/Pure/Admin/build_verit.scala \
+  src/Pure/Admin/build_zipperposition.scala \
+  src/Pure/Admin/check_sources.scala \
+  src/Pure/Admin/ci_profile.scala \
+  src/Pure/Admin/isabelle_cronjob.scala \
+  src/Pure/Admin/isabelle_devel.scala \
+  src/Pure/Admin/jenkins.scala \
+  src/Pure/Admin/other_isabelle.scala \
+  src/Pure/Concurrent/consumer_thread.scala \
+  src/Pure/Concurrent/counter.scala \
+  src/Pure/Concurrent/delay.scala \
+  src/Pure/Concurrent/event_timer.scala \
+  src/Pure/Concurrent/future.scala \
+  src/Pure/Concurrent/isabelle_thread.scala \
+  src/Pure/Concurrent/mailbox.scala \
+  src/Pure/Concurrent/par_list.scala \
+  src/Pure/Concurrent/synchronized.scala \
+  src/Pure/GUI/color_value.scala \
+  src/Pure/GUI/desktop_app.scala \
+  src/Pure/GUI/gui.scala \
+  src/Pure/GUI/gui_thread.scala \
+  src/Pure/GUI/popup.scala \
+  src/Pure/GUI/wrap_panel.scala \
+  src/Pure/General/antiquote.scala \
+  src/Pure/General/bytes.scala \
+  src/Pure/General/cache.scala \
+  src/Pure/General/codepoint.scala \
+  src/Pure/General/comment.scala \
+  src/Pure/General/completion.scala \
+  src/Pure/General/csv.scala \
+  src/Pure/General/date.scala \
+  src/Pure/General/exn.scala \
+  src/Pure/General/file.scala \
+  src/Pure/General/file_watcher.scala \
+  src/Pure/General/graph.scala \
+  src/Pure/General/graph_display.scala \
+  src/Pure/General/graphics_file.scala \
+  src/Pure/General/http.scala \
+  src/Pure/General/json.scala \
+  src/Pure/General/linear_set.scala \
+  src/Pure/General/logger.scala \
+  src/Pure/General/long_name.scala \
+  src/Pure/General/mailman.scala \
+  src/Pure/General/mercurial.scala \
+  src/Pure/General/multi_map.scala \
+  src/Pure/General/output.scala \
+  src/Pure/General/path.scala \
+  src/Pure/General/position.scala \
+  src/Pure/General/pretty.scala \
+  src/Pure/General/properties.scala \
+  src/Pure/General/rdf.scala \
+  src/Pure/General/scan.scala \
+  src/Pure/General/sha1.scala \
+  src/Pure/General/sql.scala \
+  src/Pure/General/ssh.scala \
+  src/Pure/General/symbol.scala \
+  src/Pure/General/time.scala \
+  src/Pure/General/timing.scala \
+  src/Pure/General/untyped.scala \
+  src/Pure/General/url.scala \
+  src/Pure/General/utf8.scala \
+  src/Pure/General/uuid.scala \
+  src/Pure/General/value.scala \
+  src/Pure/General/word.scala \
+  src/Pure/General/xz.scala \
+  src/Pure/Isar/document_structure.scala \
+  src/Pure/Isar/keyword.scala \
+  src/Pure/Isar/line_structure.scala \
+  src/Pure/Isar/outer_syntax.scala \
+  src/Pure/Isar/parse.scala \
+  src/Pure/Isar/token.scala \
+  src/Pure/ML/ml_console.scala \
+  src/Pure/ML/ml_lex.scala \
+  src/Pure/ML/ml_process.scala \
+  src/Pure/ML/ml_profiling.scala \
+  src/Pure/ML/ml_statistics.scala \
+  src/Pure/ML/ml_syntax.scala \
+  src/Pure/PIDE/byte_message.scala \
+  src/Pure/PIDE/command.scala \
+  src/Pure/PIDE/command_span.scala \
+  src/Pure/PIDE/document.scala \
+  src/Pure/PIDE/document_id.scala \
+  src/Pure/PIDE/document_status.scala \
+  src/Pure/PIDE/editor.scala \
+  src/Pure/PIDE/headless.scala \
+  src/Pure/PIDE/line.scala \
+  src/Pure/PIDE/markup.scala \
+  src/Pure/PIDE/markup_tree.scala \
+  src/Pure/PIDE/protocol.scala \
+  src/Pure/PIDE/protocol_handlers.scala \
+  src/Pure/PIDE/protocol_message.scala \
+  src/Pure/PIDE/prover.scala \
+  src/Pure/PIDE/query_operation.scala \
+  src/Pure/PIDE/rendering.scala \
+  src/Pure/PIDE/resources.scala \
+  src/Pure/PIDE/session.scala \
+  src/Pure/PIDE/text.scala \
+  src/Pure/PIDE/xml.scala \
+  src/Pure/PIDE/yxml.scala \
+  src/Pure/ROOT.scala \
+  src/Pure/System/bash.scala \
+  src/Pure/System/command_line.scala \
+  src/Pure/System/components.scala \
+  src/Pure/System/executable.scala \
+  src/Pure/System/getopts.scala \
+  src/Pure/System/isabelle_charset.scala \
+  src/Pure/System/isabelle_fonts.scala \
+  src/Pure/System/isabelle_platform.scala \
+  src/Pure/System/isabelle_process.scala \
+  src/Pure/System/isabelle_system.scala \
+  src/Pure/System/isabelle_tool.scala \
+  src/Pure/System/java_statistics.scala \
+  src/Pure/System/linux.scala \
+  src/Pure/System/mingw.scala \
+  src/Pure/System/numa.scala \
+  src/Pure/System/options.scala \
+  src/Pure/System/platform.scala \
+  src/Pure/System/posix_interrupt.scala \
+  src/Pure/System/process_result.scala \
+  src/Pure/System/progress.scala \
+  src/Pure/System/scala.scala \
+  src/Pure/System/system_channel.scala \
+  src/Pure/System/tty_loop.scala \
+  src/Pure/Thy/bibtex.scala \
+  src/Pure/Thy/document_build.scala \
+  src/Pure/Thy/export.scala \
+  src/Pure/Thy/export_theory.scala \
+  src/Pure/Thy/file_format.scala \
+  src/Pure/Thy/html.scala \
+  src/Pure/Thy/latex.scala \
+  src/Pure/Thy/presentation.scala \
+  src/Pure/Thy/sessions.scala \
+  src/Pure/Thy/thy_element.scala \
+  src/Pure/Thy/thy_header.scala \
+  src/Pure/Thy/thy_syntax.scala \
+  src/Pure/Tools/build.scala \
+  src/Pure/Tools/build_docker.scala \
+  src/Pure/Tools/build_job.scala \
+  src/Pure/Tools/check_keywords.scala \
+  src/Pure/Tools/debugger.scala \
+  src/Pure/Tools/doc.scala \
+  src/Pure/Tools/dump.scala \
+  src/Pure/Tools/fontforge.scala \
+  src/Pure/Tools/java_monitor.scala \
+  src/Pure/Tools/logo.scala \
+  src/Pure/Tools/mkroot.scala \
+  src/Pure/Tools/phabricator.scala \
+  src/Pure/Tools/print_operation.scala \
+  src/Pure/Tools/profiling_report.scala \
+  src/Pure/Tools/scala_build.scala \
+  src/Pure/Tools/scala_project.scala \
+  src/Pure/Tools/server.scala \
+  src/Pure/Tools/server_commands.scala \
+  src/Pure/Tools/simplifier_trace.scala \
+  src/Pure/Tools/spell_checker.scala \
+  src/Pure/Tools/task_statistics.scala \
+  src/Pure/Tools/update.scala \
+  src/Pure/Tools/update_cartouches.scala \
+  src/Pure/Tools/update_comments.scala \
+  src/Pure/Tools/update_header.scala \
+  src/Pure/Tools/update_then.scala \
+  src/Pure/Tools/update_theorems.scala \
+  src/Pure/library.scala \
+  src/Pure/pure_thy.scala \
+  src/Pure/term.scala \
+  src/Pure/term_xml.scala \
+  src/Pure/thm_name.scala \
+  src/Tools/Graphview/graph_file.scala \
+  src/Tools/Graphview/graph_panel.scala \
+  src/Tools/Graphview/graphview.scala \
+  src/Tools/Graphview/layout.scala \
+  src/Tools/Graphview/main_panel.scala \
+  src/Tools/Graphview/metrics.scala \
+  src/Tools/Graphview/model.scala \
+  src/Tools/Graphview/mutator.scala \
+  src/Tools/Graphview/mutator_dialog.scala \
+  src/Tools/Graphview/mutator_event.scala \
+  src/Tools/Graphview/popups.scala \
+  src/Tools/Graphview/shapes.scala \
+  src/Tools/Graphview/tree_panel.scala \
+  src/Tools/VSCode/src/build_vscode.scala \
+  src/Tools/VSCode/src/channel.scala \
+  src/Tools/VSCode/src/dynamic_output.scala \
+  src/Tools/VSCode/src/language_server.scala \
+  src/Tools/VSCode/src/lsp.scala \
+  src/Tools/VSCode/src/preview_panel.scala \
+  src/Tools/VSCode/src/state_panel.scala \
+  src/Tools/VSCode/src/textmate_grammar.scala \
+  src/Tools/VSCode/src/vscode_model.scala \
+  src/Tools/VSCode/src/vscode_rendering.scala \
+  src/Tools/VSCode/src/vscode_resources.scala \
+  src/Tools/VSCode/src/vscode_spell_checker.scala \
+  src/Tools/jEdit/src/active.scala \
+  src/Tools/jEdit/src/base_plugin.scala \
+  src/Tools/jEdit/src/completion_popup.scala \
+  src/Tools/jEdit/src/context_menu.scala \
+  src/Tools/jEdit/src/debugger_dockable.scala \
+  src/Tools/jEdit/src/dockable.scala \
+  src/Tools/jEdit/src/document_model.scala \
+  src/Tools/jEdit/src/document_view.scala \
+  src/Tools/jEdit/src/documentation_dockable.scala \
+  src/Tools/jEdit/src/fold_handling.scala \
+  src/Tools/jEdit/src/font_info.scala \
+  src/Tools/jEdit/src/graphview_dockable.scala \
+  src/Tools/jEdit/src/info_dockable.scala \
+  src/Tools/jEdit/src/isabelle.scala \
+  src/Tools/jEdit/src/isabelle_encoding.scala \
+  src/Tools/jEdit/src/isabelle_export.scala \
+  src/Tools/jEdit/src/isabelle_options.scala \
+  src/Tools/jEdit/src/isabelle_session.scala \
+  src/Tools/jEdit/src/isabelle_vfs.scala \
+  src/Tools/jEdit/src/jedit_bibtex.scala \
+  src/Tools/jEdit/src/jedit_editor.scala \
+  src/Tools/jEdit/src/jedit_lib.scala \
+  src/Tools/jEdit/src/jedit_options.scala \
+  src/Tools/jEdit/src/jedit_rendering.scala \
+  src/Tools/jEdit/src/jedit_resources.scala \
+  src/Tools/jEdit/src/jedit_sessions.scala \
+  src/Tools/jEdit/src/jedit_spell_checker.scala \
+  src/Tools/jEdit/src/keymap_merge.scala \
+  src/Tools/jEdit/src/main.scala \
+  src/Tools/jEdit/src/main_plugin.scala \
+  src/Tools/jEdit/src/monitor_dockable.scala \
+  src/Tools/jEdit/src/output_dockable.scala \
+  src/Tools/jEdit/src/pide_docking_framework.scala \
+  src/Tools/jEdit/src/pretty_text_area.scala \
+  src/Tools/jEdit/src/pretty_tooltip.scala \
+  src/Tools/jEdit/src/process_indicator.scala \
+  src/Tools/jEdit/src/protocol_dockable.scala \
+  src/Tools/jEdit/src/query_dockable.scala \
+  src/Tools/jEdit/src/raw_output_dockable.scala \
+  src/Tools/jEdit/src/rich_text_area.scala \
+  src/Tools/jEdit/src/session_build.scala \
+  src/Tools/jEdit/src/simplifier_trace_dockable.scala \
+  src/Tools/jEdit/src/simplifier_trace_window.scala \
+  src/Tools/jEdit/src/sledgehammer_dockable.scala \
+  src/Tools/jEdit/src/state_dockable.scala \
+  src/Tools/jEdit/src/status_widget.scala \
+  src/Tools/jEdit/src/symbols_dockable.scala \
+  src/Tools/jEdit/src/syntax_style.scala \
+  src/Tools/jEdit/src/syslog_dockable.scala \
+  src/Tools/jEdit/src/text_overview.scala \
+  src/Tools/jEdit/src/text_structure.scala \
+  src/Tools/jEdit/src/theories_dockable.scala \
+  src/Tools/jEdit/src/timing_dockable.scala \
+  src/Tools/jEdit/src/token_markup.scala
+services = \
+  isabelle.Bash$Handler \
+  isabelle.Bibtex$File_Format \
+  isabelle.Document_Build$Build_Engine \
+  isabelle.Document_Build$LuaLaTeX_Engine \
+  isabelle.Document_Build$PDFLaTeX_Engine \
+  isabelle.ML_Statistics$Handler \
+  isabelle.Print_Operation$Handler \
+  isabelle.Scala$Handler \
+  isabelle.Scala_Functions \
+  isabelle.Server_Commands \
+  isabelle.Sessions$File_Format \
+  isabelle.Simplifier_Trace$Handler \
+  isabelle.Tools \
+  isabelle.nitpick.Kodkod$Handler \
+  isabelle.nitpick.Scala_Functions \
+  isabelle.spark.SPARK$Load_Command1 \
+  isabelle.spark.SPARK$Load_Command2
--- a/etc/components	Wed Jul 07 15:40:00 2021 +0200
+++ b/etc/components	Tue Aug 17 17:09:20 2021 +0200
@@ -1,6 +1,8 @@
 #built-in components
 src/Tools/jEdit
+src/Tools/GraphBrowser
 src/Tools/Graphview
+src/Tools/Setup
 src/Tools/VSCode
 src/HOL/Mutabelle
 src/HOL/Library/Sum_of_Squares
--- a/etc/options	Wed Jul 07 15:40:00 2021 +0200
+++ b/etc/options	Tue Aug 17 17:09:20 2021 +0200
@@ -305,10 +305,10 @@
 
 section "Phabricator"
 
-option phabricator_version_arcanist : string = "cdae0ac68f1fed138323fa3dbb299ef3b287723c"
+option phabricator_version_arcanist : string = "4f70fcffa8a5393e210d64f237ffdaa256256d6a"
   -- "repository version for arcanist"
 
-option phabricator_version_phabricator : string = "4f70fcffa8a5393e210d64f237ffdaa256256d6a"
+option phabricator_version_phabricator : string = "193798385bd3a7f72dca255e44f8112f4f8fc155"
   -- "repository version for phabricator"
 
 
@@ -373,3 +373,10 @@
 
 option system_channel_address : string = ""
 option system_channel_password : string = ""
+
+
+section "Bash process execution server"
+
+option bash_process_debugging : bool = false
+option bash_process_address : string = ""
+option bash_process_password : string = ""
--- a/etc/settings	Wed Jul 07 15:40:00 2021 +0200
+++ b/etc/settings	Tue Aug 17 17:09:20 2021 +0200
@@ -16,27 +16,10 @@
 
 ISABELLE_TOOL_JAVA_OPTIONS="-Djava.awt.headless=true -Xms512m -Xmx4g -Xss16m"
 
+ISABELLE_JAVAC_OPTIONS="-encoding UTF-8 -Xlint:-options -deprecation -source 11 -target 11"
 ISABELLE_SCALAC_OPTIONS="-encoding UTF-8 -Wconf:cat=other-match-analysis:silent -feature -deprecation -target:11 -Xsource:3 -J-Xms512m -J-Xmx4g -J-Xss16m"
 
-classpath "$ISABELLE_HOME/lib/classes/Pure.jar"
-
-isabelle_scala_service 'isabelle.Tools'
-[ -d "$ISABELLE_HOME/Admin" ] && isabelle_scala_service 'isabelle.Admin_Tools'
-
-isabelle_scala_service 'isabelle.Scala_Functions'
-
-isabelle_scala_service 'isabelle.Sessions$File_Format'
-isabelle_scala_service 'isabelle.Bibtex$File_Format'
-
-isabelle_scala_service 'isabelle.ML_Statistics$Handler'
-isabelle_scala_service 'isabelle.Scala$Handler'
-isabelle_scala_service 'isabelle.Print_Operation$Handler'
-isabelle_scala_service 'isabelle.Simplifier_Trace$Handler'
-isabelle_scala_service 'isabelle.Server_Commands'
-
-isabelle_scala_service 'isabelle.Document_Build$LuaLaTeX_Engine'
-isabelle_scala_service 'isabelle.Document_Build$PDFLaTeX_Engine'
-isabelle_scala_service 'isabelle.Document_Build$Build_Engine'
+ISABELLE_SCALA_JAR="$ISABELLE_HOME/lib/classes/isabelle.jar"
 
 #paranoia settings -- avoid intrusion of alien options
 unset "_JAVA_OPTIONS"
--- a/lib/Tools/browser	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-#!/usr/bin/env bash
-#
-# Author: Markus Wenzel, TU Muenchen
-#
-# DESCRIPTION: Isabelle graph browser
-
-
-PRG="$(basename "$0")"
-
-function usage()
-{
-  echo
-  echo "Usage: isabelle $PRG [OPTIONS] [GRAPHFILE]"
-  echo
-  echo "  Options are:"
-  echo "    -b           Admin/build only"
-  echo "    -c           cleanup -- remove GRAPHFILE after use"
-  echo "    -o FILE      output to FILE (ps, eps, pdf)"
-  echo
-  exit 1
-}
-
-function fail()
-{
-  echo "$1" >&2
-  exit 2
-}
-
-
-## process command line
-
-# options
-
-ADMIN_BUILD=""
-CLEAN=""
-OUTFILE=""
-
-while getopts "bco:" OPT
-do
-  case "$OPT" in
-    b)
-      ADMIN_BUILD=true
-      ;;
-    c)
-      CLEAN=true
-      ;;
-    o)
-      OUTFILE="$OPTARG"
-      ;;
-    \?)
-      usage
-      ;;
-  esac
-done
-
-shift $(($OPTIND - 1))
-
-
-# args
-
-GRAPHFILE=""
-[ "$#" -gt 0 ] && { GRAPHFILE="$1"; shift; }
-[ "$#" -ne 0 ] && usage
-
-
-## main
-
-isabelle_admin_build browser || exit $?
-
-classpath "$ISABELLE_HOME/lib/browser/GraphBrowser.jar"
-
-if [ -n "$GRAPHFILE" ]; then
-  PRIVATE_FILE="${ISABELLE_TMP:-${TMPDIR:-/tmp}}/$$"$(basename "$GRAPHFILE")
-  if [ -n "$CLEAN" ]; then
-    mv -f "$GRAPHFILE" "$PRIVATE_FILE" || fail "Cannot move file: $GRAPHFILE"
-  else
-    cp -f "$GRAPHFILE" "$PRIVATE_FILE" || fail "Cannot copy file: $GRAPHFILE"
-  fi
-
-  PDF=""
-  case "$OUTFILE" in
-    *.pdf)
-      OUTFILE="${OUTFILE%%.pdf}.eps"
-      PDF=true
-      ;;
-  esac
-
-  if [ -z "$OUTFILE" ]; then
-    isabelle java GraphBrowser.GraphBrowser "$(platform_path "$PRIVATE_FILE")"
-  else
-    isabelle java GraphBrowser.Console "$(platform_path "$PRIVATE_FILE")" "$(platform_path "$OUTFILE")"
-  fi
-  RC="$?"
-
-  if [ -n "$PDF" ]; then
-    (
-      cd "$(dirname "$OUTFILE")"
-      "$ISABELLE_EPSTOPDF" "$(basename "$OUTFILE")" || fail "Failed to produce pdf output"
-    )
-  fi
-
-  rm -f "$PRIVATE_FILE"
-elif [ -z "$ADMIN_BUILD" ]; then
-  [ -d "$ISABELLE_BROWSER_INFO" ] && cd "$ISABELLE_BROWSER_INFO"
-  exec isabelle java GraphBrowser.GraphBrowser
-else
-  RC=0
-fi
-
-exit "$RC"
--- a/lib/Tools/components	Wed Jul 07 15:40:00 2021 +0200
+++ b/lib/Tools/components	Tue Aug 17 17:09:20 2021 +0200
@@ -127,7 +127,7 @@
   echo "Missing components:"
   for NAME in "${MISSING_COMPONENTS[@]}"; do echo "  $NAME"; done
 elif [ "${#UPDATE_COMPONENTS[@]}" -ne 0 ]; then
-  isabelle_admin_build jars || exit $?
+  isabelle scala_build || exit $?
   exec isabelle java isabelle.Components "${UPDATE_COMPONENTS[@]}"
 else
   for NAME in "${SELECTED_COMPONENTS[@]}"
--- a/lib/Tools/console	Wed Jul 07 15:40:00 2021 +0200
+++ b/lib/Tools/console	Tue Aug 17 17:09:20 2021 +0200
@@ -4,7 +4,7 @@
 #
 # DESCRIPTION: raw ML process (interactive mode)
 
-isabelle_admin_build jars || exit $?
+isabelle scala_build || exit $?
 
 eval "declare -a JAVA_ARGS=($ISABELLE_TOOL_JAVA_OPTIONS)"
 
--- a/lib/Tools/java	Wed Jul 07 15:40:00 2021 +0200
+++ b/lib/Tools/java	Tue Aug 17 17:09:20 2021 +0200
@@ -6,8 +6,8 @@
 
 eval "declare -a JAVA_ARGS=($ISABELLE_JAVA_SYSTEM_OPTIONS)"
 
-[ -n "$CLASSPATH" ] && classpath "$CLASSPATH"
-unset CLASSPATH
+classpath "$ISABELLE_SETUP_CLASSPATH"; unset ISABELLE_SETUP_CLASSPATH
+classpath "$CLASSPATH"; unset CLASSPATH
 
 isabelle_java java "${JAVA_ARGS[@]}" \
   -classpath "$(platform_path "$ISABELLE_CLASSPATH")" "$@"
--- a/lib/Tools/scala	Wed Jul 07 15:40:00 2021 +0200
+++ b/lib/Tools/scala	Tue Aug 17 17:09:20 2021 +0200
@@ -4,7 +4,7 @@
 #
 # DESCRIPTION: invoke Scala within the Isabelle environment
 
-isabelle_admin_build jars || exit $?
+isabelle scala_build || exit $?
 
 eval "declare -a JAVA_ARGS=($ISABELLE_JAVA_SYSTEM_OPTIONS)"
 declare -a SCALA_ARGS=()
@@ -13,8 +13,8 @@
   SCALA_ARGS["${#SCALA_ARGS[@]}"]="-J$ARG"
 done
 
-[ -n "$CLASSPATH" ] && classpath "$CLASSPATH"
-unset CLASSPATH
+classpath "$ISABELLE_SETUP_CLASSPATH"; unset ISABELLE_SETUP_CLASSPATH
+classpath "$CLASSPATH"; unset CLASSPATH
 
 isabelle_scala scala "${SCALA_ARGS[@]}" \
   -classpath "$(platform_path "$ISABELLE_CLASSPATH")" \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/Tools/scala_build	Tue Aug 17 17:09:20 2021 +0200
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+#
+# Author: Makarius
+#
+# DESCRIPTION: build Isabelle/Scala/Java components
+
+## diagnostics
+
+PRG="$(basename "$0")"
+
+function usage()
+{
+  echo
+  echo "Usage: isabelle $PRG [OPTIONS]"
+  echo
+  echo "  Options are:"
+  echo "    -f           force fresh build"
+  echo "    -q           quiet mode: suppress stdout/stderr"
+  echo
+  echo "  Build Isabelle/Scala/Java modules of all registered components"
+  echo "  (if required)."
+  echo
+  exit 1
+}
+
+
+## process command line
+
+COMMAND="build"
+QUIET=""
+
+while getopts "fq" OPT
+do
+  case "$OPT" in
+    f)
+      COMMAND="build_fresh"
+      ;;
+    q)
+      QUIET="true"
+      ;;
+    \?)
+      usage
+      ;;
+  esac
+done
+
+shift $(($OPTIND - 1))
+
+[ "$#" -ne 0 ] && usage
+
+
+## main
+
+#remove historic material
+rm -rf \
+  "$ISABELLE_HOME/lib/classes/Pure.jar" \
+  "$ISABELLE_HOME/lib/classes/Pure.shasum" \
+  "$ISABELLE_HOME/src/Tools/jEdit/dist"
+
+classpath "$CLASSPATH"; unset CLASSPATH
+
+eval "declare -a JAVA_ARGS=($ISABELLE_TOOL_JAVA_OPTIONS)"
+
+JAVA_ARGS["${#JAVA_ARGS[@]}"]="-classpath"
+JAVA_ARGS["${#JAVA_ARGS[@]}"]="$(platform_path "$ISABELLE_CLASSPATH")"
+JAVA_ARGS["${#JAVA_ARGS[@]}"]="isabelle.setup.Setup"
+JAVA_ARGS["${#JAVA_ARGS[@]}"]="$COMMAND"
+
+if [ -z "$QUIET" ]; then
+  isabelle_java java "${JAVA_ARGS[@]}"
+else
+  isabelle_java java "${JAVA_ARGS[@]}" > /dev/null 2> /dev/null
+fi
--- a/lib/Tools/scalac	Wed Jul 07 15:40:00 2021 +0200
+++ b/lib/Tools/scalac	Tue Aug 17 17:09:20 2021 +0200
@@ -4,7 +4,10 @@
 #
 # DESCRIPTION: invoke Scala compiler within the Isabelle environment
 
-isabelle_admin_build jars || exit $?
+isabelle scala_build || exit $?
+
+classpath "$ISABELLE_SETUP_CLASSPATH"; unset ISABELLE_SETUP_CLASSPATH
+classpath "$CLASSPATH"; unset CLASSPATH
 
 isabelle_scala scalac -Dfile.encoding=UTF-8 \
   -classpath "$(platform_path "$ISABELLE_CLASSPATH")" "$@"
--- a/lib/browser/GraphBrowser/AWTFontMetrics.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/AWTFontMetrics.java
-  Author:     Gerwin Klein, TU Muenchen
-
-  AbstractFontMetrics from the AWT for graphics mode.
-  
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.awt.FontMetrics;
-
-public class AWTFontMetrics implements AbstractFontMetrics {
-  private FontMetrics fontMetrics;
-
-  public AWTFontMetrics(FontMetrics m) {
-    fontMetrics = m;
-  }
-
-  public int stringWidth(String str) {
-    return fontMetrics.stringWidth(str);
-  }
-
-  public int getAscent() {
-    return fontMetrics.getAscent();
-  }
-
-  public int getDescent() {
-    return fontMetrics.getDescent();
-  }
-}
--- a/lib/browser/GraphBrowser/AbstractFontMetrics.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/AWTFontMetrics.java
-  Author:     Gerwin Klein, TU Muenchen
-
-  AbstractFontMetrics avoids dependency on java.awt.FontMetrics in 
-  batch mode.
-  
-***************************************************************************/
-
-package GraphBrowser;
-
-public interface AbstractFontMetrics {
-  public int stringWidth(String str);
-  public int getAscent();
-  public int getDescent();
-}
--- a/lib/browser/GraphBrowser/Box.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/Box.java
-  Author:     Gerwin Klein, TU Muenchen
-
-  A box with width and height. Used instead of java.awt.Dimension for 
-  batch mode.
-
-***************************************************************************/
-
-package GraphBrowser;
-
-public class Box {
-  public int width;
-  public int height;
-
-  public Box(int w, int h) {
-    this.width = w;
-    this.height = h;
-  }
-}
--- a/lib/browser/GraphBrowser/Console.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/Console.java
-  Author:     Gerwin Klein, TU Muenchen
-  Options:    :tabSize=2:
-
-  This is the graph browser's main class when run as a console application.
-  It duplicates some logic from GraphBrowser and GraphView.
-  It does so to remove dependency on AWT.
-
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.io.*;
-import java.util.*;
-
-public class Console {
-	Graph g;
-	String gfname;  
-
-  public Console(String name) {
-    gfname = name;
-  }
-
-	public void PS(String fname, boolean printable) throws IOException {
-    g.layout(null);
-		g.PS(fname,printable);
-	}
-
-
-	public void collapseNodes(Vector collapsedDir) { 
-		Enumeration e1=collapsedDir.elements();
-		Graph gra=(Graph)(g.clone());
-
-		while (e1.hasMoreElements()) {
-			Directory d=(Directory)(e1.nextElement());
-			Vector v=gra.decode(d.getCollapsed());
-			if (!v.isEmpty())
-				gra.collapse(v,"["+d.getName()+"]",d.getCollapsed());
-		}
-    
-    g = gra;
-	}
-
-
-	public void initBrowser(InputStream is) {
-		try {
-			TreeNode tn = new TreeNode("Root", "", -1, true);
-      g = new Graph(is, tn);
-			Vector v = new Vector(10,10);
-			tn.collapsedDirectories(v);      
-      collapseNodes(v);
-		} catch (IOException exn) {
-			System.err.println("\nI/O error while reading graph file.");
-		} catch (ParseError exn) {
-			System.err.println("\nParse error in graph file:");
-			System.err.println(exn.getMessage());
-			System.err.println("\nSyntax:\n<vertexname> <vertexID> <dirname> [ + ] <path> "+
-                         "[ < | > ] [ <vertexID> [ ... [ <vertexID> ] ... ] ] ;");
-		}
-	}
-
-	public static void main(String[] args) {
-		try {
-      if (args.length <= 1) {
-        System.err.println("Graph and output file expected.");
-        return;
-      }
-
-			Console console=new Console(args[0]);
-      InputStream is=new FileInputStream(args[0]);
-      console.initBrowser(is);
-      is.close();      
-    
-      try {
-        if (args[1].endsWith(".ps"))
-          console.PS(args[1], true);
-        else if (args[1].endsWith(".eps"))
-          console.PS(args[1], false);
-        else
-          System.err.println("Unknown file type: " + args[1]);
-      } catch (IOException exn) {
-        System.err.println("Unable to write file " + args[1]);
-      }
-		} catch (IOException exn) {
-			System.err.println("Can't open graph file "+args[0]);
-		}
-	}
-}
--- a/lib/browser/GraphBrowser/DefaultFontMetrics.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/DefaultFontMetrics.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=2:
-
-  Default font metrics which is used when no graphics context
-  is available (batch mode).
-***************************************************************************/
-
-package GraphBrowser;
-
-public class DefaultFontMetrics implements AbstractFontMetrics {
-
-  private static int[] chars =
-	{13, 13, 17, 27, 27, 43, 32, 11, 16, 16, 19, 28, 13, 28, 13, 13, 27,
-	 27, 27, 27, 27, 27, 27, 27, 27, 27, 13, 13, 28, 28, 28, 27, 49, 32,
-	 32, 35, 35, 32, 29, 37, 35, 13, 24, 32, 27, 40, 35, 37, 32, 37, 35,
-	 32, 29, 35, 32, 45, 32, 32, 29, 13, 13, 13, 22, 27, 11, 27, 27, 24,
-	 27, 27, 13, 27, 27, 11, 11, 24, 11, 40, 27, 27, 27, 27, 16, 24, 13,
-	 27, 24, 35, 24, 24, 24, 16, 12, 16, 28};
-
-  private int size;
-
-  public DefaultFontMetrics(int size)
-  { this.size = size; }
-
-  public int getLeading()
-  { return 1; }
-
-  public int getAscent()
-  { return (int)(Math.round(size * 46.0 / 48.0)); }
-  
-  public int getDescent() 
-  { return (int)(Math.round(size * 10.0 / 48.0)); }
-  
-  public int charWidth(char c) {
-    if (c < 32 || c > 126) { return 0; }
-    else {
-	    return (int)(Math.round(chars[c - 32] * size / 48.0));
-    }
-  }
-  
-  public int stringWidth(String s) {
-    int l=0, i;
-    for (i=0; i < s.length(); i++) { l += charWidth(s.charAt(i)); }
-    return l;
-  }
-}
--- a/lib/browser/GraphBrowser/Directory.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-package GraphBrowser;
-
-import java.util.Vector;
-
-class Directory {
-	TreeNode node;
-	String name;
-	Vector collapsed;
-
-	public Directory(TreeNode nd,String n,Vector col) {
-		collapsed=col;
-		name=n;
-		node=nd;
-	}
-
-	public TreeNode getNode() { return node; }
-
-	public String getName() { return name; }
-
-	public Vector getCollapsed() { return collapsed; }
-}
--- a/lib/browser/GraphBrowser/DummyVertex.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/DummyVertex.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This class represents a dummy vertex, which is used to simplify the
-  layout algorithm.
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.awt.*;
-
-class DummyVertex extends Vertex {
-	public boolean isDummy() {return true;}
-
-	public Object clone() {
-		Vertex ve=new DummyVertex();
-		ve.setX(getX());ve.setY(getY());
-		return ve;
-	}
-
-	public int leftX() { return getX(); }
-
-	public int rightX() { return getX(); }
-
-	public void draw(Graphics g) {}
-}
-
--- a/lib/browser/GraphBrowser/Graph.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1062 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/Graph.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This class contains the core of the layout algorithm and methods for
-  drawing and PostScript output.
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.util.*;
-import java.awt.*;
-import java.io.*;
-
-public class Graph {
-	/**** parameters for layout ****/
-
-	public int box_height=0;
-	public int box_height2;
-	public Graphics gfx;
-
-	Vector vertices=new Vector(10,10);
-	Vector splines=new Vector(10,10);
-	Vector numEdges=new Vector(10,10);
-	Vertex []vertices2;
-
-	public int min_x=0,min_y=0,max_x=10,max_y=10;
-
-	/********************************************************************/
-	/*                         clone graph object                       */
-	/********************************************************************/
-
-	public Object clone() {
-		Graph gr=new Graph();
-		Enumeration e1;
-		int i;
-
-		gr.splines=(Vector)(splines.clone());
-
-		e1=vertices.elements();
-		while (e1.hasMoreElements())
-			gr.addVertex((Vertex)(((Vertex)(e1.nextElement())).clone()));
-
-		for (i=0;i<vertices.size();i++) {
-			Vertex vx1=(Vertex)(gr.vertices.elementAt(i));
-			e1=((Vertex)(vertices.elementAt(i))).getChildren();
-			while (e1.hasMoreElements()) {
-				Vertex vx2=(Vertex)(gr.vertices.elementAt(vertices.indexOf(e1.nextElement())));
-				vx1.addChild(vx2);
-			}
-		}
-
-		gr.vertices2 = new Vertex[vertices.size()];
-		gr.vertices.copyInto(gr.vertices2);
-
-		gr.min_x=min_x;gr.max_x=max_x;
-		gr.min_y=min_y;gr.max_y=max_y;
-
-		return gr;
-	}
-
-	Graph() {}
-
-	/********************************************************************/
-	/*                      Read graph from stream                      */
-	/********************************************************************/
-
-	public Graph(InputStream s,TreeNode tn) throws IOException, ParseError {
-		StreamTokenizer tok=new StreamTokenizer(new InputStreamReader(s));
-		String name,dir,vertexID;
-		Vertex ve1,ve2;
-		boolean children,unfoldDir;
-		int index=0;
-
-		tok.nextToken();
-		while (tok.ttype!=StreamTokenizer.TT_EOF) {
-			if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
-				throw new ParseError("expected: vertex name\nfound   : "+tok.toString());
-			name=tok.sval;
-                        tok.nextToken();
-			if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
-				throw new ParseError("expected: vertex identifier\nfound   : "+tok.toString());
-			vertexID=tok.sval;
-			tok.nextToken();
-			if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
-				throw new ParseError("expected: directory name\nfound   : "+tok.toString());
-			dir=tok.sval;
-			tok.nextToken();
-			if (tok.ttype=='+') {
-				unfoldDir=true;
-				tok.nextToken();
-			} else
-				unfoldDir=false;
-			if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
-				throw new ParseError("expected: path name\nfound   : "+tok.toString());
-			ve1=findVertex(vertexID);
-			if (ve1==null) {
-				ve1=new NormalVertex("");
-				ve1.setID(vertexID);
-				ve1.setNumber(index++);
-				addVertex(ve1);
-			}
-			ve1.setPath(tok.sval);
-			ve1.setDir(dir);
-                        ve1.setLabel(name);
-			tn.insertNode(name,dir,tok.sval,ve1.getNumber(),unfoldDir);
-			tok.nextToken();
-			if (tok.ttype=='<') {
-				children=true;
-				tok.nextToken();
-			} else if (tok.ttype=='>') {
-					children=false;
-					tok.nextToken();
-			} else children=true;
-			while (tok.ttype!=';') {
-				if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
-					throw new ParseError("expected: child vertex identifier or ';'\nfound   : "+tok.toString());				
-				ve2=findVertex(tok.sval);
-				if (ve2==null) {
-					ve2=new NormalVertex("");
-					ve2.setID(tok.sval);
-					ve2.setNumber(index++);
-					addVertex(ve2);
-				}
-				if (children)
-					ve1.addChild(ve2);
-				else
-					ve1.addParent(ve2);
-				tok.nextToken();
-			}
-			tok.nextToken();
-		}
-		vertices2 = new Vertex[vertices.size()];
-		vertices.copyInto(vertices2);
-	}
-	
-	/*** Find vertex with identifier vertexID ***/
-
-	public Vertex findVertex(String vertexID) {
-		Enumeration e1=vertices.elements();
-		Vertex v1;
-
-		while (e1.hasMoreElements()) {
-			v1=(Vertex)(e1.nextElement());
-			if ((v1.getID()).equals(vertexID))
-				return v1;
-		}
-		return null;
-	}
-		 
-	public void addVertex(Vertex v) {
-		vertices.addElement(v);
-		v.setGraph(this);
-	}
-
-	public void removeVertex(Vertex v) {
-		vertices.removeElement(v);
-	}
-
-	public Enumeration getVertices() {
-		return vertices.elements();
-	}
-
-	/********************************************************************/
-	/*                          graph layout                            */
-	/********************************************************************/
-
-	public void layout(Graphics g) {
-		splines.removeAllElements();
-		hasseDiagram();
-		Vector layers=min_crossings(insert_dummies((Vector)(sort().elementAt(0))));
-		setParameters(g);
-		init_coordinates(layers);
-		pendulum(layers);
-		rubberband(layers);
-		calcSplines(layers);
-		calcBoundingBox();
-	}
-
-	/********************************************************************/
-	/*                      set layout parameters                       */
-	/********************************************************************/
-
-	public void setParameters(Graphics g) {
-		Enumeration e1=vertices.elements();
-		int h;
-		h=Integer.MIN_VALUE;
-
-		while (e1.hasMoreElements()) {
-		  Box dim=((Vertex)(e1.nextElement())).getLabelSize(g);
-			h=Math.max(h,dim.height);
-		}
-		box_height=h+4;
-		box_height2=box_height/2;
-		gfx=g;
-	}
-
-	/********************************************************************/
-	/*                       topological sorting                        */
-	/********************************************************************/
-
-	public Vector sort() {
-		Vector todo=(Vector)(vertices.clone());
-		Vector layers=new Vector(10,10);
-		Vector todo2;
-		Enumeration e1,e2;
-		Vertex v,v2;
-
-		e1=vertices.elements();
-		while (e1.hasMoreElements())
-			((Vertex)(e1.nextElement())).setDegree(0);
-
-		e1=vertices.elements();
-		while (e1.hasMoreElements()) {
-			v=(Vertex)(e1.nextElement());
-			e2=v.getChildren();
-			while (e2.hasMoreElements()) {
-				v2=(Vertex)(e2.nextElement());
-				todo.removeElement(v2);
-				v2.setDegree(1+v2.getDegree());
-			}
-		}
-		while (!todo.isEmpty()) {
-			layers.addElement(todo);
-			todo2=new Vector(10,10);
-			e1=todo.elements();
-			while (e1.hasMoreElements()) {
-				e2=((Vertex)(e1.nextElement())).getChildren();
-				while (e2.hasMoreElements()) {
-					v=(Vertex)(e2.nextElement());
-					v.setDegree(v.getDegree()-1);
-					if (v.getDegree()==0) {
-						todo2.addElement(v);
-						v.setDegree(layers.size());
-					}
-				}
-			}
-			todo=todo2;
-		}
-		return layers;
-	}
-
-	/********************************************************************/
-	/*                      compute hasse diagram                       */
-	/********************************************************************/
-
-	public void hasseDiagram() {
-		Enumeration e1,e2;
-		Vertex vx1,vx2;
-
-		/** construct adjacence matrix **/
-
-		int vs=vertices.size();
-		boolean adj[][]=new boolean[vs][vs];
-		boolean adj2[][]=new boolean[vs][vs];
-		int i,j,k;
-
-		e1=getVertices();
-		for (i=0;i<vs;i++) {
-			vx1=(Vertex)(e1.nextElement());
-			e2=vx1.getChildren();
-			while (e2.hasMoreElements()) {
-				vx2=(Vertex)(e2.nextElement());
-				j=vertices.indexOf(vx2);
-				adj[i][j]=true;
-				adj2[i][j]=true;
-			}
-		}
-
-		/** compute transitive closure R+ **/
-
-		for (k=0;k<vs;k++)
-			for (i=0;i<vs;i++)
-				if (adj[i][k])
-					for (j=0;j<vs;j++)
-						adj[i][j] = adj[i][j] || adj[k][j];
-
-		/** compute R \ (R+)^2 **/
-
-		for (i=0;i<vs;i++)
-			for (j=0;j<vs;j++)
-				if (adj2[i][j]) {
-					vx1=(Vertex)(vertices.elementAt(i));
-					vx2=(Vertex)(vertices.elementAt(j));
-					for (k=0;k<vs;k++)
-						if (adj[i][k] && adj[k][j]) {
-							vx1.removeChild(vx2);
-							break;
-						}
-				}
-	}
-				
-	/********************************************************************/
-	/*                      insert dummy vertices                       */
-	/********************************************************************/
-
-	public Vector insert_dummies(Vector v) {
-		Vector layers2=new Vector(10,10);
-		int n_edges;
-
-		do {
-			Enumeration e1=v.elements(),e2;
-			Vector next=new Vector(10,10);
-
-			layers2.addElement(v);
-			n_edges=0;
-			while (e1.hasMoreElements()) {
-				Vertex v1=(Vertex)(e1.nextElement());
-				e2=v1.getChildren();
-				while (e2.hasMoreElements()) {
-					n_edges++;
-					Vertex v2=(Vertex)(e2.nextElement());
-					if (v2.getDegree()!=v1.getDegree()+1) {
-						Vertex v3=new DummyVertex();
-						v3.addChild(v2);
-						v3.setDegree(v1.getDegree()+1);
-						v1.removeChild(v2);
-						v1.addChild(v3);
-						next.addElement(v3);
-						addVertex(v3);
-					} else if (next.indexOf(v2)<0) next.addElement(v2);
-				}
-			}
-			v=next;
-			numEdges.addElement(new Integer(n_edges));
-		} while (!v.isEmpty());
-		return layers2;
-	}
-
-	/********************************************************************/
-	/*                     calculation of crossings                     */
-	/********************************************************************/
-
-	public int count_crossings(Vector layers,int oldcr) {
-		int i,j,y1,y2,cr=0,l;
-		for (l=0;l<layers.size()-1;l++) {
-			Vector v1=(Vector)(layers.elementAt(l));
-			for (i=0;i<v1.size();i++) {
-				Enumeration e2=((Vertex)(v1.elementAt(i))).getChildren();
-				while (e2.hasMoreElements()) {
-					y1=((Vector)(layers.elementAt(l+1))).indexOf(e2.nextElement());
-					for (j=0;j<i;j++) {
-						Enumeration e3=((Vertex)(v1.elementAt(j))).getChildren();
-						while (e3.hasMoreElements()) {
-							y2=((Vector)(layers.elementAt(l+1))).indexOf(e3.nextElement());
-							if (y1<y2) {
-								cr++;
-								if (cr>=oldcr) return cr;
-							}
-						}
-					}
-				}
-			}
-		}
-		return cr;
-	}
-
-	/********************************************************************/
-	/* calculation of crossings where vertices vx1 and vx2 are involved */
-	/* vx1 and vx2 must be in same layer and vx1 is left from vx2       */
-	/********************************************************************/
-
-	public int count_crossings_2(Vector layers,Vertex vx1,Vertex vx2,int oldcr) {
-		int i,cr=0,l=vx1.getDegree();
-		Vertex va,vb;
-		Vector layer;
-		Enumeration e1,e2;
-
-		if (l>0) {
-			layer=(Vector)(layers.elementAt(l-1));
-			e1=vx1.getParents();
-			while (e1.hasMoreElements()) {
-				va=(Vertex)(e1.nextElement());
-				i=layer.indexOf(va);
-				e2=vx2.getParents();
-				while (e2.hasMoreElements()) {
-					vb=(Vertex)(e2.nextElement());
-					if (layer.indexOf(vb)<i) {
-						cr++;
-						if (cr>=oldcr) return cr;
-					}
-				}
-			}
-		}
-		if (l<layers.size()-1) {
-			layer=(Vector)(layers.elementAt(l+1));
-			e1=vx1.getChildren();
-			while (e1.hasMoreElements()) {
-				va=(Vertex)(e1.nextElement());
-				i=layer.indexOf(va);
-				e2=vx2.getChildren();
-				while (e2.hasMoreElements()) {
-					vb=(Vertex)(e2.nextElement());
-					if (layer.indexOf(vb)<i) {
-						cr++;
-						if (cr>=oldcr) return cr;
-					}
-				}
-			}
-		}
-		return cr;
-	}
-
-	/********************************************************************/
-	/*       reduction of crossings by exchanging adjacent vertices     */
-	/********************************************************************/
-
-	public void exchangeVertices(Vector layers,int oldcr) {
-		int i,l,c1,c2;
-		Vertex vx1,vx2;
-		Vector v1;
-
-		for (l=0;l<layers.size();l++) {
-			v1=(Vector)(layers.elementAt(l));
-			for (i=0;i<v1.size()-1;i++) {
-				vx1=(Vertex)(v1.elementAt(i));
-				vx2=(Vertex)(v1.elementAt(i+1));
-				c1=count_crossings_2(layers,vx1,vx2,oldcr);
-				c2=count_crossings_2(layers,vx2,vx1,c1);
-				if (c2<c1) {
-					v1.setElementAt(vx2,i);
-					v1.setElementAt(vx1,i+1);
-				}
-			}
-		}
-	}
-
-	/********************************************************************/
-	/*                    minimization of crossings                     */
-	/********************************************************************/
-
-	public Vector min_crossings(Vector layers) {
-		int n,i,l,k,z=0,cr2,cr=count_crossings(layers,Integer.MAX_VALUE);
-		boolean topdown=true,first=true;
-		Enumeration e1,e2;
-		Vector v1,v2,layers2=null,best=layers;
-		Vertex vx1,vx2;
-		n=0;
-		while (n<3 && cr>0) {
-			if (topdown) {
-				/** top-down-traversal **/
-
-				layers2=new Vector(10,10);
-				for (l=0;l<layers.size();l++) {
-					v1=(Vector)(layers.elementAt(l));
-					if (l==0) layers2.addElement(v1.clone());
-					else {
-						v2=new Vector(10,10);
-						layers2.addElement(v2);
-						e1=v1.elements();
-						while (e1.hasMoreElements()) {
-							vx1=(Vertex)(e1.nextElement());
-							k=0;z=0;
-							e2=vx1.getParents();
-							while (e2.hasMoreElements()) {
-								k+=((Vector)(layers2.elementAt(l-1))).indexOf(e2.nextElement());
-								z++;
-							}
-							if (z>0)
-								vx1.setWeight(((double)(k))/z);
-							else if (first)
-								vx1.setWeight(Double.MAX_VALUE);
-							for (i=0;i<v2.size();i++)
-								if (vx1.getWeight()<((Vertex)(v2.elementAt(i))).getWeight()) break;
-							if (i==v2.size()) v2.addElement(vx1);
-							else v2.insertElementAt(vx1,i);
-						}
-					}
-				}
-			} else {
-				/** bottom-up-traversal **/
-
-				layers2=new Vector(10,10);
-				for (l=layers.size()-1;l>=0;l--) {
-					v1=(Vector)(layers.elementAt(l));
-					if (l==layers.size()-1) layers2.addElement(v1.clone());
-					else {
-						v2=new Vector(10,10);
-						layers2.insertElementAt(v2,0);
-						e1=v1.elements();
-						while (e1.hasMoreElements()) {
-							vx1=(Vertex)(e1.nextElement());
-							k=0;z=0;
-							e2=vx1.getChildren();
-							while (e2.hasMoreElements()) {
-								k+=((Vector)(layers2.elementAt(1))).indexOf(e2.nextElement());
-								z++;
-							}
-							if (z>0)
-								vx1.setWeight(((double)(k))/z);
-							else if (first)
-								vx1.setWeight(Double.MAX_VALUE);
-							for (i=0;i<v2.size();i++)
-								if (vx1.getWeight()<((Vertex)(v2.elementAt(i))).getWeight()) break;
-							if (i==v2.size()) v2.addElement(vx1);
-							else v2.insertElementAt(vx1,i);
-						}
-					}
-				}
-			}
-			//exchangeVertices(layers2,cr);
-			topdown=!topdown;
-			first=false;
-			layers=layers2;
-
-			cr2=count_crossings(layers2,cr);
-			if (cr2<cr) {
-				best=layers2;
-				cr=cr2;					
-			} else n++;
-		}
-
-		while (true) {
-			exchangeVertices(best,cr);
-			cr2=count_crossings(best,cr);
-			if (cr2<cr)
-				cr=cr2;
-			else
-				break;
-		}
-
-		return best;
-	}
-
-	/********************************************************************/
-	/*                   set initial coordinates                        */
-	/********************************************************************/
-
-	public void init_coordinates(Vector layers) {
-		int y=0;
-		Enumeration e1=layers.elements();
-		Enumeration e3=numEdges.elements();
-		while (e1.hasMoreElements()) {
-			Vector v1=(Vector)(e1.nextElement());
-			Enumeration e2=v1.elements();
-			int x=0;
-			while (e2.hasMoreElements()) {
-				Vertex ve=(Vertex)(e2.nextElement());
-				ve.setX(x+ve.box_width2());
-				ve.setY(y);
-				x+=ve.box_width()+20;
-			}
-			y+=box_height+Math.max(35,7*(((Integer)(e3.nextElement())).intValue()));
-		}
-	}
-
-	/********************************************************************/
-	/*                       pendulum method                            */
-	/********************************************************************/
-
-	public void pendulum(Vector layers) {
-		Vector layers2=new Vector(10,10);
-		Enumeration e1=layers.elements(),e2;
-		int i,j,d1,d2,k,offset,dsum;
-		Region r1,r2;
-		boolean change;
-
-		while (e1.hasMoreElements()) {
-			e2=((Vector)(e1.nextElement())).elements();
-			Vector layer=new Vector(10,10);
-			layers2.addElement(layer);
-			while (e2.hasMoreElements()) {
-				Region r=new Region(this);
-				r.addVertex((Vertex)(e2.nextElement()));
-				layer.addElement(r);
-			}
-		}
-		for (k=0;k<10;k++) {
-			dsum=0;
-			for (j=1;j<layers2.size();j++) {
-				Vector l=(Vector)(layers2.elementAt(j));
-				if (l.size()>=2) {
-					do {
-						change=false;
-						d1=((Region)(l.firstElement())).pred_deflection();
-						for (i=0;i<l.size()-1;i++) {
-							r1=(Region)(l.elementAt(i));
-							r2=(Region)(l.elementAt(i+1));
-							d2=r2.pred_deflection();
-							if (r1.touching(r2) && (d1 <= 0 && d2 < d1 ||
-								d2 > 0 && d1 > d2 || d1 > 0 && d2 < 0)) {
-								r1.combine(r2);
-								l.removeElement(r2);
-								change=true;
-								d2=r1.pred_deflection();
-							}
-							d1=d2;
-						}
-					} while (change);
-				}
-				for (i=0;i<l.size();i++) {
-					r1=(Region)(l.elementAt(i));
-					d1=r1.pred_deflection();
-					offset=d1;
-					if (d1<0 && i>0) offset=-Math.min(
-						((Region)(l.elementAt(i-1))).spaceBetween(r1),-d1);
-					if (d1>=0 && i<l.size()-1) offset=Math.min(
-						r1.spaceBetween((Region)(l.elementAt(i+1))),d1);
-					r1.move(offset);
-					dsum+=Math.abs(d1);
-				}		
-			}
-			if (dsum==0) break;
-		}
-	}		
-
-	/********************************************************************/
-	/*                      rubberband method                           */
-	/********************************************************************/
-
-	public void rubberband(Vector layers) {
-		Enumeration e1,e2;
-		int i,n,k,d,d2;
-		Vector v;
-		Vertex vx;
-
-		for (k=0;k<10;k++) {
-			e1=layers.elements();
-			while (e1.hasMoreElements()) {
-				v=(Vector)(e1.nextElement());
-				for (i=0;i<v.size();i++) {
-					n=0;d=0;
-					vx=(Vertex)(v.elementAt(i));
-					e2=vx.getChildren();
-					while (e2.hasMoreElements()) {
-						d+=((Vertex)(e2.nextElement())).getX()-vx.getX();
-						n++;
-					}
-					e2=vx.getParents();
-					while (e2.hasMoreElements()) {
-						d+=((Vertex)(e2.nextElement())).getX()-vx.getX();
-						n++;
-					}
-					d2=(n!=0?d/n:0);
-
-					if (d<0 && (i==0 || ((Vertex)(v.elementAt(i-1))).rightX()+20 < vx.leftX()+d2) ||
-						d>0 && (i==v.size()-1 || ((Vertex)(v.elementAt(i+1))).leftX()-20 > vx.rightX()+d2))
-						vx.setX(vx.getX()+d2);
-				}
-			}
-		}
-	}
-
-	/**** Intersection point of two lines (auxiliary function for calcSplines)   ****/
-	/**** Calculate intersection point of line which is parallel to line (p1,p2) ****/
-	/**** and leads through p5, with line (p3,p4)                                ****/
-
-	Point intersect(Point p1,Point p2,Point p3,Point p4,Point p5) {
-		float x=0,y=0,s1=0,s2=0;
-
-		if (p1.x!=p2.x)
-			s1=((float)(p2.y-p1.y))/(p2.x-p1.x);
-		if (p3.x!=p4.x)
-			s2=((float)(p4.y-p3.y))/(p4.x-p3.x);
-		if (p1.x==p2.x) {
-			x=p5.x;
-			y=s2*(p5.x-p3.x)+p3.y;
-		} else if (p3.x==p4.x) {
-			x=p3.x;
-			y=s1*(p3.x-p5.x)+p5.y;
-		} else {
-			x=(p5.x*s1-p3.x*s2+p3.y-p5.y)/(s1-s2);
-			y=s2*(x-p3.x)+p3.y;
-		}
-		return new Point(Math.round(x),Math.round(y));
-	}
-
-	/**** Calculate control points (auxiliary function for calcSplines) ****/
-
-	Points calcPoint(Point p1,Point p2,Point p3,int lboxx,int rboxx,int boxy) {
-
-		/*** Points p1 , p2 , p3 define a triangle which encloses the spline.  ***/
-		/*** Check if adjacent boxes (specified by lboxx,rboxx and boxy)       ***/
-		/*** collide with the spline. In this case p1 and p3 are shifted by an ***/
-		/*** appropriate offset before they are returned                       ***/
-
-		int xh1,xh2,bx=0,by=0;
-		boolean pt1 = boxy >= p1.y && boxy <= p3.y || boxy >= p3.y && boxy <= p1.y;
-		boolean pt2 = boxy+box_height >= p1.y && boxy+box_height <= p3.y ||
-                              boxy+box_height >= p3.y && boxy+box_height <= p1.y;
-		boolean move = false;
-		Point b;
-
-		xh1 = p1.x+(boxy-p1.y)*(p3.x-p1.x)/(p3.y-p1.y);
-		xh2 = p1.x+(boxy+box_height-p1.y)*(p3.x-p1.x)/(p3.y-p1.y);
-
-		if (xh1 <= lboxx && pt1 && xh2 <= lboxx && pt2) {
-			move = true;
-			bx = lboxx;
-			by = boxy + (xh1 < xh2 ? 0 : box_height ) ;
-		} else if (xh1 >= rboxx && pt1 && xh2 >= rboxx && pt2) {
-			move = true;
-			bx = rboxx;
-			by = boxy + (xh1 > xh2 ? 0 : box_height ) ;
-		} else if ( (xh1 <= lboxx || xh1 >= rboxx) && pt1) {
-			move = true;
-			bx = (xh1 <= lboxx ? lboxx : rboxx ) ;
-			by = boxy;
-		} else if ( (xh2 <= lboxx || xh2 >= rboxx) && pt2) {
-			move = true;
-			bx = (xh2 <= lboxx ? lboxx : rboxx ) ;
-			by = boxy+box_height;
-		}
-		b=new Point(bx,by);
-		if (move) return new Points(intersect(p1,p3,p1,p2,b),intersect(p1,p3,p2,p3,b));
-		else return new Points(p1,p3);
-	}
-
-	/********************************************************************/
-	/*                        calculate splines                         */
-	/********************************************************************/
-
-	public void calcSplines(Vector layers) {
-		Enumeration e2,e1=vertices.elements();
-		Vertex vx1,vx2,vx3;
-		Vector pos,layer;
-		int x1,y1,x2,y2,x3,y3,xh,k,leftx,rightx,spc;
-
-		while (e1.hasMoreElements()) {
-			vx1=(Vertex)(e1.nextElement());
-			if (!vx1.isDummy()) {
-				e2=vx1.getChildren();
-				while (e2.hasMoreElements()) {
-					vx2=(Vertex)(e2.nextElement());
-					if (vx2.isDummy()) {
-						vx3=vx2;
-						/**** convert edge to spline ****/
-						pos=new Vector(10,10);
-						x1=vx1.getX();
-						y1=vx1.getY()+box_height;
-
-						do {
-							/*** calculate position of control points ***/
-							x2=vx2.getX();
-							y2=vx2.getY();
-							layer=(Vector)(layers.elementAt(vx2.getDegree()));
-							k=layer.indexOf(vx2);
-							vx2=(Vertex)((vx2.getChildren()).nextElement());
-							x3=vx2.getX();
-							y3=vx2.getY();
-							spc=0;
-							leftx = k==0 /* || ((Vertex)(layer.elementAt(k-1))).isDummy() */ ?
-								Integer.MIN_VALUE:
-								((Vertex)(layer.elementAt(k-1))).rightX()+spc;
-							rightx = k==layer.size()-1 /* || ((Vertex)(layer.elementAt(k+1))).isDummy() */ ?
-								Integer.MAX_VALUE:
-								((Vertex)(layer.elementAt(k+1))).leftX()-spc;
-							xh=x2+box_height*(x3-x2)/(y3-y2);
-							if (!(x2<=x3 && xh>=rightx || x2>x3 && xh<=leftx)) {
-								/* top control point */
-								pos.addElement(new Integer(1));
-								y1=y2;
-							} else {
-								xh=x1+(y2-y1)*(x2-x1)/(y2+box_height-y1);
-								if (!(x2<=x1 && xh>=rightx || x2>x1 && xh<=leftx))
-									/* bottom control point */
-									pos.addElement(new Integer(2));
-								else
-									/* two control points needed */
-									pos.addElement(new Integer(3));
-								y1=y2+box_height;
-							}
-							x1=x2;
-						} while (vx2.isDummy());
-						pos.addElement(new Integer(1));
-
-						/**** calculate triangles ****/
-						vx2=vx3;
-
-						int pos1,pos2,i=0;
-						Vector pts=new Vector(10,10);
-						int lboxx,rboxx,boxy;
-
-						x1=vx1.getX();
-						y1=vx1.getY()+box_height;
-						pts.addElement(new Point(x1,y1)); /** edge starting point **/
-						do {
-							x2=vx2.getX();
-							y2=vx2.getY();
-							pos1=((Integer)(pos.elementAt(i))).intValue();
-							pos2=((Integer)(pos.elementAt(i+1))).intValue();
-							i++;
-							layer=(Vector)(layers.elementAt(vx2.getDegree()));
-							k=layer.indexOf(vx2);
-							boxy=vx2.getY();
-							vx2=(Vertex)((vx2.getChildren()).nextElement());
-							x3=vx2.getX();
-							y3=vx2.getY();
-							if (pos1==2) y2+=box_height;
-							if (pos2==2) y3+=box_height;
-
-							lboxx = (k==0 /* || ((Vertex)(layer.elementAt(k-1))).isDummy() */ ) ?
-								Integer.MIN_VALUE :
-								((Vertex)(layer.elementAt(k-1))).rightX();
-
-							rboxx = (k==layer.size()-1 /* || ((Vertex)(layer.elementAt(k+1))).isDummy() */ ) ?
-								Integer.MAX_VALUE :
-								((Vertex)(layer.elementAt(k+1))).leftX();
-
-							Point p1,p2,p3;
-							Points ps;
-
-							p1 = new Point((x1+x2)/2,(y1+y2)/2);
-
-							if (pos1<=2) {
-								/** one control point **/
-								p2 = new Point(x2,y2);
-								ps = calcPoint(p1,p2,new Point((x2+x3)/2,(y2+y3)/2),lboxx,rboxx,boxy);
-								pts.addElement(ps.p);
-								pts.addElement(p2);
-								pts.addElement(ps.q);
-							} else {
-								/** two control points **/
-								p2 = new Point(x2,y2-box_height);
-								p3 = new Point(x2,y2+box_height2);
-								ps = calcPoint(p1,p2,p3,lboxx,rboxx,boxy);
-								pts.addElement(ps.p);
-								pts.addElement(p2);
-								pts.addElement(ps.q);
-								p2 = new Point(x2,y2+box_height*2);
-								ps = calcPoint(p3,p2,new Point((p2.x+x3)/2,(p2.y+y3)/2),
-								               lboxx,rboxx,boxy);
-								pts.addElement(ps.p);
-								pts.addElement(p2);
-								pts.addElement(ps.q);
-							}
-							x1=p2.x;
-							y1=p2.y;
-						} while (vx2.isDummy());
-
-						pts.addElement(new Point(vx2.getX(),vx2.getY())); /** edge end point **/
-						splines.addElement(new Spline(pts));
-					}
-				}
-			}
-		}
-	}
-
-	/********************************************************************/
-	/*                      calculate bounding box                      */
-	/********************************************************************/
-
-	public void calcBoundingBox() {
-		min_y=min_x=Integer.MAX_VALUE;
-		max_y=max_x=Integer.MIN_VALUE;
-
-		Enumeration e1=vertices.elements();
-		Vertex v;
-
-		while (e1.hasMoreElements()) {
-			v=(Vertex)(e1.nextElement());
-			min_x=Math.min(min_x,v.leftX());
-			max_x=Math.max(max_x,v.rightX());
-			min_y=Math.min(min_y,v.getY());
-			max_y=Math.max(max_y,v.getY()+box_height);
-		}
-		min_x-=20;
-		min_y-=20;
-		max_x+=20;
-		max_y+=20;
-	}
-
-	/********************************************************************/
-	/*                           draw graph                             */
-	/********************************************************************/
-					 
-	public void draw(Graphics g) {
-		if (box_height==0) layout(g);
-
-		g.translate(-min_x,-min_y);
-
-		Enumeration e1=vertices.elements();
-		while (e1.hasMoreElements())
-			((Vertex)(e1.nextElement())).draw(g);
-
-		e1=splines.elements();
-		while (e1.hasMoreElements())
-			((Spline)(e1.nextElement())).draw(g);
-	}
-
-	/********************************************************************/
-	/*               return vertex at position (x,y)                    */
-	/********************************************************************/
-
-	public Vertex vertexAt(int x,int y) {
-		Enumeration e1=vertices.elements();
-		while (e1.hasMoreElements()) {
-			Vertex v=(Vertex)(e1.nextElement());
-			if (v.contains(x,y)) return v;
-		}
-		return null;
-	}
-
-	/********************************************************************/
-	/*       encode list of vertices (as array of vertice numbers)      */
-	/********************************************************************/
-
-	public Vector encode(Vector v) {
-		Vector code=new Vector(10,10);
-		Enumeration e1=v.elements();
-
-		while (e1.hasMoreElements()) {
-			Vertex vx=(Vertex)(e1.nextElement());
-			if (vx.getNumber()>=0)
-				code.addElement(new Integer(vx.getNumber()));
-		}
-		return code;
-	}
-
-	/********************************************************************/
-	/*                      get vertex with number n                    */
-	/********************************************************************/
-
-	public Vertex getVertexByNum(int x) {
-		Enumeration e1=vertices.elements();
-
-		while (e1.hasMoreElements()) {
-			Vertex vx=(Vertex)(e1.nextElement());
-			if (vx.getNumber()==x) return vx;
-		}
-		return null;
-	}
-
-	/********************************************************************/
-	/*                      decode list of vertices                     */
-	/********************************************************************/
-
-	public Vector decode(Vector code) {
-		Enumeration e1=code.elements();
-		Vector vec=new Vector(10,10);
-
-		while (e1.hasMoreElements()) {
-			int i=((Integer)(e1.nextElement())).intValue();
-			//Vertex vx=getVertexByNum(i);
-			//if (vx!=null) vec.addElement(vx);
-			vec.addElement(vertices2[i]);
-		}
-		return vec;
-	}
-
-	/********************************************************************/
-	/*                       collapse vertices                          */
-	/********************************************************************/
-
-	public void collapse(Vector vs,String name,Vector inflate) {
-		Enumeration e1,e2,e3;
-		boolean nonempty=false;
-		Vertex vx3,vx2,vx1;
-		
-		e1=vertices.elements();
-
-		vx1=new NormalVertex(name);
-		vx1.setInflate(inflate);
-
-		while (e1.hasMoreElements()) {
-			vx2=(Vertex)(e1.nextElement());
-
-			if (vs.indexOf(vx2)<0) {
-				e2=vx2.getParents();
-				while (e2.hasMoreElements()) {
-					vx3=(Vertex)(e2.nextElement());
-					if (vs.indexOf(vx3)>=0) {
-						if (!vx1.isChild(vx2))
-							vx1.addChild(vx2);
-						vx3.removeChild(vx2);
-					}
-				}
-
-				e2=vx2.getChildren();
-				while (e2.hasMoreElements()) {
-					vx3=(Vertex)(e2.nextElement());
-					if (vs.indexOf(vx3)>=0) {
-						if (!vx2.isChild(vx1))
-							vx2.addChild(vx1);
-						vx2.removeChild(vx3);
-					}
-				}
-			} else { nonempty=true; }
-		}
-
-		e1=vs.elements();
-		while (e1.hasMoreElements())
-			try {
-				removeVertex((Vertex)(e1.nextElement()));
-			} catch (NoSuchElementException exn) {}
-
-		if (nonempty) addVertex(vx1);
-	}
-
-	/********************************************************************/
-	/*                      PostScript output                           */
-	/********************************************************************/
-
-	public void PS(String fname,boolean printable) throws IOException {
-		FileOutputStream f = new FileOutputStream(fname);
-		PrintWriter p = new PrintWriter(f, true);
-
-		if (printable)
-			p.println("%!PS-Adobe-2.0\n\n%%BeginProlog");
-		else {
-			p.println("%!PS-Adobe-2.0 EPSF-2.0\n%%Orientation: Portrait");
-			p.println("%%BoundingBox: "+min_x+" "+min_y+" "+max_x+" "+max_y);
-			p.println("%%EndComments\n\n%%BeginProlog");
-		}
-		p.println("/m { moveto } def /l { lineto } def /n { newpath } def");
-		p.println("/s { stroke } def /c { curveto } def");
-		p.println("/b { n 0 0 m dup true charpath pathbbox 1 index 4 index sub");
-		p.println("7 index exch sub 2 div 9 index add 1 index 4 index sub 7 index exch sub");
-		p.println("2 div 9 index add 2 index add m pop pop pop pop");
-		p.println("1 -1 scale show 1 -1 scale n 3 index 3 index m 1 index 0 rlineto");
-		p.println("0 exch rlineto neg 0 rlineto closepath s pop pop } def");
-		p.println("%%EndProlog\n");
-		if (printable) {
-			int hsize=max_x-min_x;
-			int vsize=max_y-min_y;
-			if (hsize>vsize) {
-				// Landscape output
-				double scale=Math.min(1,Math.min(750.0/hsize,500.0/vsize));
-				double trans_x=50+max_y*scale+(500-scale*vsize)/2.0;
-				double trans_y=50+max_x*scale+(750-scale*hsize)/2.0;
-				p.println(trans_x+" "+trans_y+" translate");
-				p.println("-90 rotate");
-				p.println(scale+" "+(-scale)+" scale");
-			} else {
-				// Portrait output
-				double scale=Math.min(1,Math.min(500.0/hsize,750.0/vsize));
-				double trans_x=50-min_x*scale+(500-scale*hsize)/2.0;
-				double trans_y=50+max_y*scale+(750-scale*vsize)/2.0;
-				p.println(trans_x+" "+trans_y+" translate");
-				p.println(scale+" "+(-scale)+" scale");
-			}
-		} else
-			p.println("0 "+(max_y+min_y)+" translate\n1 -1 scale");
-
-		p.println("/Helvetica findfont 12 scalefont setfont");
-		p.println("0.5 setlinewidth");
-
-		Enumeration e1=vertices.elements();
-		while (e1.hasMoreElements())
-			((Vertex)(e1.nextElement())).PS(p);
-
-		e1=splines.elements();
-		while (e1.hasMoreElements())
-			((Spline)(e1.nextElement())).PS(p);
-
-		if (printable) p.println("showpage");
-
-		f.close();
-	}
-}
-
-/**** Return value of function calcPoint ****/
-
-class Points {
-	public Point p,q;
-
-	public Points(Point p1,Point p2) {
-		p=p1;q=p2;
-	}
-}
-
--- a/lib/browser/GraphBrowser/GraphBrowser.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/GraphBrowser.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This is the graph browser's main class. It contains the "main(...)"
-  method, which is used for the stand-alone version, as well as
-  "init(...)", "start(...)" and "stop(...)" methods which are used for
-  the applet version.
-  Note: GraphBrowser is designed for the 1.1.x version of the JDK.
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.awt.*;
-import java.applet.*;
-import java.io.*;
-import java.util.*;
-import java.net.*;
-import awtUtilities.*;
-
-public class GraphBrowser extends Applet {
-	GraphView gv;
-	TreeBrowser tb=null;
-	String gfname;
-
-	static boolean isApplet;
-	static Frame f;
-
-	public GraphBrowser(String name) {
-		gfname=name;
-	}
-
-	public GraphBrowser() {}
-
-	public void showWaitMessage() {
-		if (isApplet)
-			getAppletContext().showStatus("calculating layout, please wait ...");
-		else {
-			f.setCursor(new Cursor(Cursor.WAIT_CURSOR));
-		}
-	}
-
-	public void showReadyMessage() {
-		if (isApplet)
-			getAppletContext().showStatus("ready !");
-		else {
-			f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
-		}
-	}
-
-	public void viewFile(String fname) {
-		try {
-			if (isApplet)
-				getAppletContext().showDocument(new URL(getDocumentBase(), fname), "_blank");
-			else {
-				String path = gfname.substring(0, gfname.lastIndexOf('/') + 1);
-				Reader rd;
-				BufferedReader br;
-				String line, text = "";
-
-				try {
-					rd = new BufferedReader(new InputStreamReader((new URL(fname)).openConnection().getInputStream()));
-				} catch (Exception exn) {
-					rd = new FileReader(path + fname);
-				}
-				br = new BufferedReader(rd);
-
-				while ((line = br.readLine()) != null)
-					text += line + "\n";
-
-				if (fname.endsWith(".html")) {
-					/**** convert HTML to text (just a quick hack) ****/
-
-					String buf="";
-					char[] text2,text3;
-					int i,j=0;
-					boolean special=false, html=false;
-					char ctrl;
-
-					text2 = text.toCharArray();
-					text3 = new char[text.length()];
-					for (i = 0; i < text.length(); i++) {
-						char c = text2[i];
-						if (c == '&') {
-							special = true;
-							buf = "";
-						} else if (special) {
-							if (c == ';') {
-								special = false;
-								if (buf.equals("lt"))
-									text3[j++] = '<';
-								else if (buf.equals("gt"))
-									text3[j++] = '>';
-								else if (buf.equals("amp"))
-									text3[j++] = '&';
-							} else
-								buf += c;
-						} else if (c == '<') {
-							html = true;
-							ctrl = text2[i+1];
-						} else if (c == '>')
-							html = false;
-						else if (!html)
-							text3[j++] = c;
-					}
-					text = String.valueOf(text3);
-				}
-							
-				Frame f=new TextFrame(fname.substring(fname.lastIndexOf('/')+1),text);
-				f.setSize(500,600);
-				f.show();
-			}
-		} catch (Exception exn) {
-			System.err.println("Can't read file "+fname);
-		}
-	}
-				
-	public void PS(String fname,boolean printable) throws IOException {
-		gv.PS(fname,printable);
-	}
-
-	public boolean isEmpty() {
-		return tb==null;
-	}
-
-	public void initBrowser(InputStream is, boolean noAWT) {
-		try {
-			Font font = noAWT ? null : new Font("Helvetica", Font.PLAIN, 12);
-			TreeNode tn = new TreeNode("Root", "", -1, true);
-			gv = new GraphView(new Graph(is, tn), this, font);
-			tb = new TreeBrowser(tn, gv, font);
-			gv.setTreeBrowser(tb);
-			Vector v = new Vector(10,10);
-			tn.collapsedDirectories(v);
-			gv.collapseDir(v);
-
-			ScrollPane scrollp1 = new ScrollPane();
-			ScrollPane scrollp2 = new ScrollPane();
-			scrollp1.add(gv);
-			scrollp2.add(tb);
-			scrollp1.getHAdjustable().setUnitIncrement(20);
-			scrollp1.getVAdjustable().setUnitIncrement(20);
-			scrollp2.getHAdjustable().setUnitIncrement(20);
-			scrollp2.getVAdjustable().setUnitIncrement(20);
-			Component gv2 = new Border(scrollp1, 3);
-			Component tb2 = new Border(scrollp2, 3);
-			GridBagLayout gridbag = new GridBagLayout();
-			GridBagConstraints cnstr = new GridBagConstraints();
-			setLayout(gridbag);
-			cnstr.fill = GridBagConstraints.BOTH;
-			cnstr.insets = new Insets(5,5,5,5);
-			cnstr.weightx = 1;
-			cnstr.weighty = 1;
-			cnstr.gridwidth = 1;
-			gridbag.setConstraints(tb2,cnstr);
-			add(tb2);
-			cnstr.weightx = 2.5;
-			cnstr.gridwidth = GridBagConstraints.REMAINDER;
-			gridbag.setConstraints(gv2,cnstr);
-			add(gv2);
-		} catch (IOException exn) {
-			System.err.println("\nI/O error while reading graph file.");
-		} catch (ParseError exn) {
-			System.err.println("\nParse error in graph file:");
-			System.err.println(exn.getMessage());
-			System.err.println("\nSyntax:\n<vertexname> <vertexID> <dirname> [ + ] <path> [ < | > ] [ <vertexID> [ ... [ <vertexID> ] ... ] ] ;");
-		}
-	}		
-
-	public void init() {
-		isApplet=true;
-		gfname=getParameter("graphfile");
-		try {
-			InputStream is=(new URL(getDocumentBase(), gfname)).openConnection().getInputStream();
-			initBrowser(is, false);
-			is.close();
-		} catch (MalformedURLException exn) {
-			System.err.println("Invalid URL: "+gfname);
-		} catch (IOException exn) {
-			System.err.println("I/O error while reading "+gfname+".");
-		}
-	}
-
-	public static void main(String[] args) {
-		isApplet=false;
-		try {
-			GraphBrowser gb=new GraphBrowser(args.length > 0 ? args[0] : "");
-			if (args.length > 0) {
-				InputStream is=new FileInputStream(args[0]);
-				gb.initBrowser(is, args.length > 1);
-				is.close();
-			}
-			if (args.length > 1) {
-                            try {
-			      if (args[1].endsWith(".ps"))
-                                gb.gv.PS(args[1], true);
-                              else if (args[1].endsWith(".eps"))
-                                gb.gv.PS(args[1], false);
-                              else
-                                System.err.println("Unknown file type: " + args[1]);
-                            } catch (IOException exn) {
-                              System.err.println("Unable to write file " + args[1]);
-                            }
-                        } else {
-			    f=new GraphBrowserFrame(gb);
-			    f.setSize(700,500);
-			    f.show();
-                        }
-		} catch (IOException exn) {
-			System.err.println("Can't open graph file "+args[0]);
-		}
-	}
-}
-
--- a/lib/browser/GraphBrowser/GraphBrowserFrame.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/GraphBrowserFrame.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=2:
-
-  This class is the frame for the stand-alone application. It contains
-  methods for handling menubar events.
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import awtUtilities.*;
-
-public class GraphBrowserFrame extends Frame implements ActionListener {
-	GraphBrowser gb;
-	MenuItem i1, i2;
-	String graphDir, psDir;
-
-	public void checkMenuItems() {
-		if (gb.isEmpty()) {
-			i1.setEnabled(false);
-			i2.setEnabled(false);
-		} else {
-			i1.setEnabled(true);
-			i2.setEnabled(true);
-		}
-	}
-
-	public void actionPerformed(ActionEvent evt) {
-		String label = evt.getActionCommand();
-		if (label.equals("Quit"))
-			System.exit(0);
-		else if (label.equals("Export to PostScript")) {
-			PS(true, label);
-			return;
-		} else if (label.equals("Export to EPS")) {
-			PS(false, label);
-			return;
-		} else if (label.equals("Open ...")) {
-			FileDialog fd = new FileDialog(this, "Open graph file", FileDialog.LOAD);
-			if (graphDir != null)
-				fd.setDirectory(graphDir);
-			fd.setVisible(true);
-			if (fd.getFile() == null) return;
-			graphDir = fd.getDirectory();
-			String fname = graphDir + fd.getFile();
-			GraphBrowser gb2 = new GraphBrowser(fname);
-			try {
-				InputStream is = new FileInputStream(fname);
-				gb2.initBrowser(is, false);
-				is.close();
-			} catch (IOException exn) {
-				String button[] = {"OK"};
-				MessageDialog md = new MessageDialog(this, "Error",
-					"Can't open file " + fname + ".", button);
-				md.setSize(350, 200);
-				md.setVisible(true);
-				return;
-			}
-			remove(gb);
-			add("Center", gb2);
-			gb = gb2;
-			checkMenuItems();
-			validate();
-		}
-	}
-
-	public void PS(boolean printable,String label) {
-		FileDialog fd=new FileDialog(this,label,FileDialog.SAVE);
-		if (psDir!=null)
-			fd.setDirectory(psDir);
-		fd.setVisible(true);
-		if (fd.getFile()==null) return;
-		psDir=fd.getDirectory();
-		String fname=psDir+fd.getFile();
-
-		if ((new File(fname)).exists()) {
-			String buttons[]={"Overwrite","Cancel"};
-			MessageDialog md=new MessageDialog(this,"Warning",
-			      "Warning: File "+fname+" already exists. Overwrite?",
-			      buttons);
-			md.setSize(350,200);
-			md.setVisible(true);
-			if (md.getText().equals("Cancel")) return;
-		}
-
-		try {
-			gb.PS(fname,printable);
-		} catch (IOException exn) {
-			String button[]={"OK"};
-			MessageDialog md=new MessageDialog(this,"Error",
-			      "Unable to write file "+fname+".",button);
-			md.setSize(350,200);
-			md.setVisible(true);
-		}
-	}
-
-	public GraphBrowserFrame(GraphBrowser br) {
-		super("GraphBrowser");
-		MenuItem i3, i4;
-		gb = br;
-		MenuBar mb = new MenuBar();
-		Menu m1 = new Menu("File");
-		m1.add(i3 = new MenuItem("Open ..."));
-		m1.add(i1 = new MenuItem("Export to PostScript"));
-		m1.add(i2 = new MenuItem("Export to EPS"));
-		m1.add(i4 = new MenuItem("Quit"));
-		i1.addActionListener(this);
-		i2.addActionListener(this);
-		i3.addActionListener(this);
-		i4.addActionListener(this);
-		checkMenuItems();
-		mb.add(m1);
-		setMenuBar(mb);
-		add("Center", br);
-    addWindowListener( new WindowAdapter() {
-      public void windowClosing(WindowEvent e) {
-        System.exit(0);
-      }
-    });
-	}
-}
--- a/lib/browser/GraphBrowser/GraphView.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/GraphView.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This class defines the window in which the graph is displayed. It
-  contains methods for handling events such as collapsing / uncollapsing
-  nodes of the graph.
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import java.util.*;
-
-public class GraphView extends Canvas implements MouseListener, MouseMotionListener {
-	Graph gra, gra2;
-	GraphBrowser browser;
-	Vertex v = null;
-	Vector collapsed = new Vector(10,10);
-	Vector collapsedDirs = new Vector(10,10);
-	TreeBrowser tb;
-	long timestamp;
-	Vertex highlighted = null;
-	Dimension size;
-	boolean parent_needs_layout;
-	Font font;
-
-	public void setTreeBrowser(TreeBrowser br) {
-		tb=br;
-	}
-
-	public GraphBrowser getBrowser() { return browser; }
-
-	public Graph getGraph() { return gra; }
-
-	public Graph getOriginalGraph() { return gra2; }
-
-	public GraphView(Graph gr, GraphBrowser br, Font f) {
-		gra2=gr;
-		browser=br;
-		gra=(Graph)(gra2.clone());
-		parent_needs_layout = true;
-		size = new Dimension(0, 0);
-		font = f;
-		addMouseListener(this);
-		addMouseMotionListener(this);
-	}
-
-	public void PS(String fname,boolean printable) throws IOException {
-	    Graph gra3 = (Graph)gra.clone();
-	    gra3.layout(null);
-	    gra3.PS(fname,printable);
-	}
-
-	public void paint(Graphics g) {
-		g.setFont(font);
-		gra.draw(g);
-		if (highlighted!=null) highlighted.drawBox(g,Color.white);
-		size = new Dimension(gra.max_x-gra.min_x, gra.max_y-gra.min_y);
-		if (parent_needs_layout) {
-			parent_needs_layout = false;
-			getParent().doLayout();
-		}
-	}
-
-	public Dimension getPreferredSize() {
-		return size;
-	}
-
-	public void mouseMoved(MouseEvent evt) {
-		int x = evt.getX() + gra.min_x;
-		int y = evt.getY() + gra.min_y;
-
-		Vertex v2=gra.vertexAt(x,y);
-		Graphics g=getGraphics();
-		g.setFont(font);
-		g.translate(-gra.min_x,-gra.min_y);
-		if (highlighted!=null) {
-			highlighted.drawBox(g,Color.lightGray);
-			highlighted=null;
-		}
-		if (v2!=v) {
-			if (v!=null) v.removeButtons(g);
-			if (v2!=null) v2.drawButtons(g);
-			v=v2;
-		}
-	}
-
-	public void mouseDragged(MouseEvent evt) {}
-
-	/*****************************************************************/
-	/* This method is called if successor / predecessor nodes (whose */
-	/* numbers are stored in Vector c) of a certain node should be   */
-        /* displayed again                                               */
-	/*****************************************************************/
-
-	void uncollapse(Vector c) {
-		collapsed.removeElement(c);
-		collapseNodes();
-	}
-
-	/*****************************************************************/
-	/* This method is called by class TreeBrowser when directories   */
-	/* are collapsed / uncollapsed by the user                       */
-	/*****************************************************************/
-
-	public void collapseDir(Vector v) {
-		collapsedDirs=v;
-
-		collapseNodes();
-	}
-
-	/*****************************************************************/
-	/*                      Inflate node again                       */
-	/*****************************************************************/
-
-	public void inflateNode(Vector c) {
-		Enumeration e1;
-
-		e1=collapsedDirs.elements();
-		while (e1.hasMoreElements()) {
-			Directory d=(Directory)(e1.nextElement());
-			if (d.collapsed==c) {
-				tb.selectNode(d.getNode());
-				return;
-			}
-		}
-
-		collapsed.removeElement(c);
-		e1=gra2.getVertices();
-		while (e1.hasMoreElements()) {
-			Vertex vx=(Vertex)(e1.nextElement());
-			if (vx.getUp()==c) vx.setUp(null);
-			if (vx.getDown()==c) vx.setDown(null);
-		}
-
-		collapseNodes();
-		relayout();
-	}
-
-	public void relayout() {
-		Graphics g = getGraphics();
-		g.setFont(font);
-		browser.showWaitMessage();
-		highlighted=null;
-		gra.layout(g);
-		v=null;
-		parent_needs_layout = true;
-		update(g);
-		browser.showReadyMessage();
-	}
-
-	public void focusToVertex(int n) {
-		Vertex vx=gra.getVertexByNum(n);
-		if (vx!=null) {
-			ScrollPane scrollp = (ScrollPane)(getParent());
-			Dimension vpsize = scrollp.getViewportSize();
-
-                        int x = vx.getX()-gra.min_x;
-                        int y = vx.getY()-gra.min_y;
-			int offset_x = Math.min(scrollp.getHAdjustable().getMaximum(),
-				Math.max(0,x-vpsize.width/2));
-			int offset_y = Math.min(scrollp.getVAdjustable().getMaximum(),
-				Math.max(0,y-vpsize.height/2));
-
-			Graphics g=getGraphics();
-			g.setFont(font);
-			g.translate(-gra.min_x,-gra.min_y);
-			if (highlighted!=null) highlighted.drawBox(g,Color.lightGray);
-			vx.drawBox(g,Color.white);
-			highlighted=vx;
-			scrollp.setScrollPosition(offset_x, offset_y);
-		}
-	}
-
-	/*****************************************************************/
-	/*             Create new graph with collapsed nodes             */
-	/*****************************************************************/
-
-	public void collapseNodes() {
-		Enumeration e1=collapsed.elements();
-		gra=(Graph)(gra2.clone());
-
-		while (e1.hasMoreElements()) {
-			Vector v1=(Vector)(e1.nextElement());
-			Vector v2=gra.decode(v1);
-			if (!v2.isEmpty()) gra.collapse(v2,"[. . . .]",v1);
-		}
-
-		e1=collapsedDirs.elements();
-
-		while (e1.hasMoreElements()) {
-			Directory d=(Directory)(e1.nextElement());
-			Vector v=gra.decode(d.getCollapsed());
-			if (!v.isEmpty())
-				gra.collapse(v,"["+d.getName()+"]",d.getCollapsed());
-		}
-	}
-
-	public void mouseClicked(MouseEvent evt) {
-		Vector code = null;
-		Vertex v2;
-		int x = evt.getX() + gra.min_x;
-		int y = evt.getY() + gra.min_y;
-
-		if (v!=null) {
-			int num=v.getNumber();
-			v2=gra2.getVertexByNum(num);
-			if (v.leftButton(x,y)) {
-				if (v.getUp()!=null) {
-					code=v.getUp();
-					v2.setUp(null);
-					v=null;
-					uncollapse(code);
-					relayout();
-					focusToVertex(num);
-				} else {
-					Vector vs=v2.getPreds();
-					code=gra2.encode(vs);
-					v.setUp(code);v2.setUp(code);
-					v=null;
-					collapsed.insertElementAt(code,0);
-					collapseNodes();
-					relayout();
-					focusToVertex(num);
-				}
-			} else if (v.rightButton(x,y)) {
-				if (v.getDown()!=null) {
-					code=v.getDown();
-					v2.setDown(null);
-					v=null;
-					uncollapse(code);
-					relayout();
-					focusToVertex(num);
-				} else {
-					Vector vs=v2.getSuccs();
-					code=gra2.encode(vs);
-					v.setDown(code);v2.setDown(code);
-					v=null;
-					collapsed.insertElementAt(code,0);
-					collapseNodes();
-					relayout();
-					focusToVertex(num);
-				}
-			} else if (v.getInflate()!=null) {
-				inflateNode(v.getInflate());
-				v=null;
-			} else {
-				if (evt.getWhen()-timestamp < 400 && !(v.getPath().equals("")))
-					browser.viewFile(v.getPath());
-				timestamp=evt.getWhen();
-			}
-		}
-	}
-
-	public void mouseExited(MouseEvent evt) {
-		Graphics g=getGraphics();
-		g.setFont(font);
-		g.translate(-gra.min_x,-gra.min_y);
-		if (highlighted!=null) {
-			highlighted.drawBox(g,Color.lightGray);
-			highlighted=null;
-		}
-		if (v!=null) v.removeButtons(g);
-		v=null;
-	}
-
-	public void mouseEntered(MouseEvent evt) {}
-
-	public void mousePressed(MouseEvent evt) {}
-
-	public void mouseReleased(MouseEvent evt) {}
-}
--- a/lib/browser/GraphBrowser/NormalVertex.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/NormalVertex.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This class represents an ordinary vertex. It contains methods for
-  drawing and PostScript output.
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.util.*;
-import java.awt.*;
-import java.io.*;
-
-class NormalVertex extends Vertex {
-	String label="",path="",dir="",ID="";
-	Vector up,down,inflate=null;
-
-	public Object clone() {
-		Vertex ve=new NormalVertex(label);
-                ve.setID(ID);
-		ve.setNumber(getNumber());
-		ve.setUp(getUp());ve.setDown(getDown());
-		ve.setX(getX());ve.setY(getY());
-		ve.setPath(getPath());
-		return ve;
-	}
-
-	/*** Constructor ***/
-
-	public NormalVertex(String s) { label=s; }
-
-	public void setInflate(Vector v) { inflate=v; }
-
-	public Vector getInflate() { return inflate; }
-
-	public Vector getUp() { return up; }
-
-	public void setUp(Vector v) { up=v; }
-
-	public Vector getDown() { return down; }
-
-	public void setDown(Vector v) { down=v; }
-
-	public String getLabel() {return label;}
-
-	public void setLabel(String s) {label=s;}
-
-	public void setID(String s) { ID=s; }
-
-        public String getID() { return ID; }
-
-	public String getPath() { return path;}
-
-	public void setPath(String p) { path=p; }
-
-	public String getDir() { return dir; }
-
-	public void setDir(String d) { dir=d; }
-
-	public int leftX() { return getX()-box_width2(); }
-
-	public int rightX() { return getX()+box_width2(); }
-
-	public void drawBox(Graphics g,Color boxColor) {
-		FontMetrics fm = g.getFontMetrics(g.getFont());
-		int h=fm.getAscent()+fm.getDescent();
-
-		g.setColor(boxColor);
-		g.fillRect(getX()-box_width2(),getY(),box_width(),gra.box_height);
-		g.setColor(Color.black);
-		g.drawRect(getX()-box_width2(),getY(),box_width(),gra.box_height);
-		if (getNumber()<0)
-			g.setColor(Color.red);
-
-		g.drawString(label,
-		             (int)Math.round((box_width()-fm.stringWidth(label))/2.0)+getX()-box_width2(),
-				fm.getAscent()+(int)Math.round((gra.box_height-h)/2.0)+getY());
-	}
-
-	public void removeButtons(Graphics g) {
-		drawBox(g,Color.lightGray);
-	}
-
-	public void draw(Graphics g) {
-		drawBox(g,Color.lightGray);
-		g.setColor(Color.black);
-		Enumeration e1=getChildren();
-		while (e1.hasMoreElements()) {
-			Vertex v=(Vertex)(e1.nextElement());
-			if (!v.isDummy())
-				g.drawLine(getX(),getY()+gra.box_height,v.getX(),v.getY());
-		}
-	}
-
-	public boolean contains(int x,int y) {
-		return (x>=leftX() && x<=rightX() && y>=getY() &&
-                        y<=getY()+gra.box_height);
-	}
-
-	public boolean leftButton(int x,int y) {
-		return contains(x,y) && x<=leftX()+gra.box_height && getParents().hasMoreElements() && getNumber()>=0;
-	}
-
-	public boolean rightButton(int x,int y) {
-		return contains(x,y) && x>=rightX()-gra.box_height && getChildren().hasMoreElements() && getNumber()>=0;
-	}
-
-	public void drawButtons(Graphics g) {
-		if (getNumber()<0) return;
-
-		int l=gra.box_height*2/3,d=gra.box_height/6;
-		int up_x[] = { leftX()+d , leftX()+d+l/2 , leftX()+d+l };
-		int up_y[] = { getY()+d+l , getY()+d , getY()+d+l };
-		int down_x[] = { rightX()-d-l , rightX()-d-l/2 , rightX()-d };
-		int down_y[] = { getY()+d , getY()+d+l , getY()+d };
-
-		if (getParents().hasMoreElements()) {
-			g.setColor(Color.gray);
-			g.fillRect(leftX()+1,getY()+1,gra.box_height-1,gra.box_height-1);
-			g.setColor(getUp()!=null ? Color.red : Color.green);
-			g.fillPolygon(up_x,up_y,3);
-		}
-		if (getChildren().hasMoreElements()) {
-			g.setColor(Color.gray);
-			g.fillRect(rightX()+1-gra.box_height,getY()+1,gra.box_height,gra.box_height-1);
-			g.setColor(getDown()!=null ? Color.red : Color.green);
-			g.fillPolygon(down_x,down_y,3);
-		}
-		g.setColor(Color.black);
-	}
-
-	public void PS(PrintWriter p) {
-		p.print(leftX()+" "+getY()+" "+box_width()+" "+
-		        gra.box_height+" (");
-		for (int i=0;i<label.length();i++)
-		{
-			if (("()\\").indexOf(label.charAt(i))>=0)
-				p.print("\\");
-			p.print(label.charAt(i));
-		}
-		p.println(") b");
-
-		Enumeration e1=getChildren();
-		while (e1.hasMoreElements()) {
-			Vertex v=(Vertex)(e1.nextElement());
-			if (!v.isDummy())
-				p.println("n "+getX()+" "+(getY()+gra.box_height)+
-				" m "+v.getX()+" "+v.getY()+" l s");
-		}
-	}	
-}
-		
--- a/lib/browser/GraphBrowser/ParseError.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-package GraphBrowser;
-
-class ParseError extends Exception {
-	public ParseError(String s) { super(s); }
-}
--- a/lib/browser/GraphBrowser/Region.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/Region.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This is an auxiliary class which is used by the layout algorithm when
-  calculating coordinates with the "pendulum method". A "region" is a
-  group of nodes which "stick together".
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.util.*;
-
-class Region {
-	Vector vertices=new Vector(10,10);
-	Graph gra;
-
-	public Region(Graph g) { gra=g; }
-
-	public void addVertex(Vertex v) {
-		vertices.addElement(v);
-	}
-
-	public Enumeration getVertices() {
-		return vertices.elements();
-	}
-
-	public int pred_deflection() {
-		float d1=0;
-		int n=0;
-		Enumeration e1=vertices.elements();
-		while (e1.hasMoreElements()) {
-			float d2=0;
-			int p=0;
-			n++;
-			Vertex v=(Vertex)(e1.nextElement());
-			Enumeration e2=v.getParents();
-			while (e2.hasMoreElements()) {
-				p++;
-				d2+=((Vertex)(e2.nextElement())).getX()-v.getX();
-			}
-			if (p>0) d1+=d2/p;
-		}
-		return (int)(Math.round(d1/n));
-	}
-
-	public int succ_deflection() {
-		float d1=0;
-		int n=0;
-		Enumeration e1=vertices.elements();
-		while (e1.hasMoreElements()) {
-			float d2=0;
-			int p=0;
-			n++;
-			Vertex v=(Vertex)(e1.nextElement());
-			Enumeration e2=v.getChildren();
-			while (e2.hasMoreElements()) {
-				p++;
-				d2+=((Vertex)(e2.nextElement())).getX()-v.getX();
-			}
-			if (p>0) d1+=d2/p;
-		}
-		return (int)(Math.round(d1/n));
-	}
-
-	public void move(int x) {
-		Enumeration e1=vertices.elements();
-		while (e1.hasMoreElements()) {
-			Vertex v=(Vertex)(e1.nextElement());
-			v.setX(v.getX()+x);
-		}
-	}
-
-	public void combine(Region r2) {
-		Enumeration e1=r2.getVertices();
-		while (e1.hasMoreElements()) addVertex((Vertex)(e1.nextElement()));
-	}
-
-	public int spaceBetween(Region r2) {
-		return ((Vertex)(r2.getVertices().nextElement())).leftX()-
-			((Vertex)(vertices.lastElement())).rightX()-
-			20;
-	}
-
-	public boolean touching(Region r2) {
-		return spaceBetween(r2)==0;
-	}
-}
--- a/lib/browser/GraphBrowser/Spline.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/Spline.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This class is used for drawing spline curves (which are not yet
-  supported by the Java AWT).
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.awt.*;
-import java.util.*;
-import java.io.*;
-
-class SplineSection {
-
-	/*** Section of a spline function ***/
-
-	double x_b,x_c,x_d;
-	double y_b,y_c,y_d;
-	int dx,dy;
-
-	public SplineSection(double xb,double xc,double xd,
-		double yb,double yc,double yd,int dx2,int dy2) {
-		x_b=xb;x_c=xc;x_d=xd;
-		y_b=yb;y_c=yc;y_d=yd;
-		dx=dx2;dy=dy2;
-	}
-
-	public Point draw(Graphics g,Point s) {
-		double m;
-		int s_x,s_y,e_x=0,e_y=0;
-		int x,y;
-
-		s_x=s.x;s_y=s.y;
-		if (dx>=dy) {
-			if (dx==0) return s;
-			m=1/((double)dx);
-			for (x=0;x<dx;x++) {
-				e_x=(int)(Math.round((x_b*x*m+x_c)*x*m+x_d));
-				e_y=(int)(Math.round((y_b*x*m+y_c)*x*m+y_d));
-				g.drawLine(s_x,s_y,e_x,e_y);
-				s_x=e_x;s_y=e_y;
-			}
-		} else {
-			m=1/((double)dy);
-			for (y=0;y<dy;y++) {
-				e_x=(int)(Math.round((x_b*y*m+x_c)*y*m+x_d));
-				e_y=(int)(Math.round((y_b*y*m+y_c)*y*m+y_d));
-				g.drawLine(s_x,s_y,e_x,e_y);
-				s_x=e_x;s_y=e_y;
-			}
-		}
-		return new Point(e_x,e_y);
-	}
-}
-
-public class Spline {
-
-	Vector sections;
-	Vector points;
-	Point start,end;
-
-	public Spline(Vector pts) {
-		int i;
-		double d0,d1,d2,d3;
-		Point p0,p1,p2;
-		SplineSection s;
-		
-		start=(Point)(pts.firstElement());
-		end=(Point)(pts.lastElement());
-
-		sections=new Vector(10,10);
-		for (i=1;i<=pts.size()-4;i+=3) {
-			p0=(Point)(pts.elementAt(i));
-			p1=(Point)(pts.elementAt(i+1));
-			p2=(Point)(pts.elementAt(i+2));
-			s=new SplineSection(
-				(double)(p2.x-2*p1.x+p0.x),
-				2.0*(p1.x-p0.x),
-				(double)(p0.x),
-
-				(double)(p2.y-2*p1.y+p0.y),
-				2.0*(p1.y-p0.y),
-				(double)(p0.y),
-
-				Math.abs(p2.x-p0.x),
-				Math.abs(p2.y-p0.y)
-			);
-
-			sections.addElement(s);
-		}
-		points=pts;
-	}
-
-	public void draw(Graphics g) {
-		Enumeration e1=sections.elements();
-		Point p=start;
-
-		while (e1.hasMoreElements())
-			p=((SplineSection)(e1.nextElement())).draw(g,p);
-		g.drawLine(p.x,p.y,end.x,end.y);
-	}
-
-	public void PS(PrintWriter p) {
-		Point p0,p1,p2;
-		int i;
-
-		p.println("n "+start.x+" "+start.y+" m");
-		for (i=1;i<=points.size()-4;i+=3) {
-			p0=(Point)(points.elementAt(i));
-			p1=(Point)(points.elementAt(i+1));
-			p2=(Point)(points.elementAt(i+2));
-			p.println(p0.x+" "+p0.y+" l");
-			p.println(p0.x+" "+p0.y+" "+p1.x+" "+p1.y+" "+p2.x+" "+p2.y+" c");
-		}
-		p.println(end.x+" "+end.y+" l s");
-	}
-}
--- a/lib/browser/GraphBrowser/TreeBrowser.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/TreeBrowser.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This class defines the browser window which is used to display directory
-  trees. It contains methods for handling events.
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.util.*;
-
-
-public class TreeBrowser extends Canvas implements MouseListener
-{
-	TreeNode t;
-	TreeNode selected;
-	GraphView gv;
-	long timestamp;
-	Dimension size;
-	boolean parent_needs_layout;
-	Font font;
-
-	public TreeBrowser(TreeNode tn, GraphView gr, Font f) {
-		t = tn; gv = gr; font = f;
-		size = new Dimension(0, 0);
-		parent_needs_layout = true;
-		addMouseListener(this);
-	}
-
-	public Dimension getPreferredSize() {
-		return size;
-	}
-
-	public void mouseEntered(MouseEvent evt) {}
-
-	public void mouseExited(MouseEvent evt) {}
-
-	public void mouseReleased(MouseEvent evt) {}
-
-	public void mousePressed(MouseEvent evt) {}
-
-	public void mouseClicked(MouseEvent e)
-	{
-		TreeNode l=t.lookup(e.getY());
-
-		if (l!=null)
-		{
-			if (l.select()) {
-				Vector v=new Vector(10,10);
-				t.collapsedDirectories(v);
-				gv.collapseDir(v);
-				gv.relayout();
-			} else {
-				Vertex vx=gv.getGraph().getVertexByNum(l.getNumber());
-				gv.focusToVertex(l.getNumber());
-				vx=gv.getOriginalGraph().getVertexByNum(l.getNumber());
-				if (e.getWhen()-timestamp < 400 && !(vx.getPath().equals("")))
-					gv.getBrowser().viewFile(vx.getPath());
-				timestamp=e.getWhen();
-
-			}
-			selected=l;
-			parent_needs_layout = true;
-			repaint();
-		}
-	}
-
-	public void selectNode(TreeNode nd) {
-		Vector v=new Vector(10,10);
-		nd.select();
-		t.collapsedDirectories(v);
-		gv.collapseDir(v);
-		gv.relayout();
-		selected=nd;
-		parent_needs_layout = true;
-		repaint();
-	}
-
-	public void paint(Graphics g)
-	{
-		g.setFont(font);
-		Dimension d = t.draw(g,5,5,selected);
-		if (parent_needs_layout) {
-			size = new Dimension(5+d.width, 5+d.height);
-			parent_needs_layout = false;
-			getParent().doLayout();
-		}
-	}
-}
-
--- a/lib/browser/GraphBrowser/TreeNode.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/TreeNode.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This class contains methods for storing and manipulating directory
-  trees (e.g. collapsing / uncollapsing directory branches).
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.awt.*;
-import java.util.*;
-
-
-public class TreeNode
-{
-	int starty,endy,number;
-	String name,path;
-
-	Vector leaves=new Vector(10,10);
-	boolean unfold=false;
-
-	public void insertNode(String n,String d,String p,int num,boolean u) {
-		if (d.length()==0) {
-			leaves.addElement(new TreeNode(n,p,num));
-			unfold=unfold||u;
-		} else {
-			unfold=unfold||u;
-			String str1,str2;
-			if (d.indexOf('/')<0) {
-				str1=d;str2="";
-			} else {
-				str1=d.substring(0,d.indexOf('/'));
-				str2=d.substring(d.indexOf('/')+1);
-			}
-
-			Enumeration e1=leaves.elements();
-			TreeNode nd=null;
-
-			while (e1.hasMoreElements()) {
-				TreeNode nd2=(TreeNode)(e1.nextElement());
-				if (nd2.name.equals(str1)) {
-					nd=nd2;break;
-				}
-			}
-			if (nd==null) {
-				nd=new TreeNode(str1,"",-1);
-				leaves.addElement(nd);
-			}
-			nd.insertNode(n,str2,p,num,u);
-		}
-	}
-
-	public TreeNode(String n,String p,int num) {
-		name=n;
-		path=p;
-		number=num;
-	}
-
-	public TreeNode(String n,String p,int num,boolean u) {
-		this(n,p,num);
-		unfold=u;
-	}	
-
-	public int getNumber() { return number; }
-
-	public TreeNode lookup(int y)
-	{
-		if (y>=starty && y<endy) return this;
-		else
-		if (unfold)
-			for (int i=0;i<leaves.size();i++)
-			{
-				TreeNode t=((TreeNode)leaves.elementAt(i)).lookup(y);
-				if (t!=null) return t;
-			}
-		return null;
-	}
-
-	public boolean select()
-	{
-		if (!leaves.isEmpty()) {
-			if (unfold) collapse();
-			else unfold=true;
-			return true;
-		}
-		return false; 
-	}
-
-	public void collapse()
-	{
-		unfold=false;
-		/*
-		for(int i=0;i<leaves.size();i++)
-			((Tree)leaves.elementAt(i)).collapse();
-		*/
-	}
-
-	void collapsedNodes(Vector v) {
-		if (number>=0) v.addElement(new Integer(number));
-		Enumeration e1=leaves.elements();
-		while (e1.hasMoreElements())
-			((TreeNode)(e1.nextElement())).collapsedNodes(v);
-	}
-
-	public void collapsedDirectories(Vector v) {
-		if (!unfold) {
-			Vector v2=new Vector(10,10);
-			v.addElement(new Directory(this,name,v2));
-			collapsedNodes(v2);
-		} else {
-			Enumeration e1=leaves.elements();
-			while (e1.hasMoreElements()) {
-				TreeNode tn=(TreeNode)(e1.nextElement());
-				if (!tn.leaves.isEmpty())
-					tn.collapsedDirectories(v);
-			}
-		}
-	}
-
-	public Dimension draw(Graphics g,int x,int y,TreeNode t)
-	{
-		FontMetrics fm=g.getFontMetrics(g.getFont());
-		int h=fm.getHeight();
-		int e=(int) (h / 10) + 1;
-		int down_x[]={x + e, x + h - e, x + (int)(h / 2)};
-		int down_y[]={y + e, y + e, y + (int)(3 * h / 4) - e};
-		int right_x[]={x + e, x + (int)(3 * h / 4) - e, x + e};
-		int right_y[]={y + e, y + (int)(h / 2), y + h - e};
-		int dx=0;
-
-		if (unfold)
-		{
-			g.setColor(Color.green);
-			g.fillPolygon(down_x,down_y,3);
-			g.setColor(Color.black);
-			g.drawString(name,x+h+4,y+fm.getAscent());
-			starty=y;endy=y+h;
-			dx=Math.max(dx,x+h+4+fm.stringWidth(name));
-			y+=h+5;
-			for(int i=0;i<leaves.size();i++)
-			{
-				Dimension d=((TreeNode)leaves.elementAt(i)).draw(g,x+h+4,y,t);
-				y=d.height;
-				dx=Math.max(dx,d.width);
-			}
-		}
-		else
-		{
-			g.setColor(leaves.isEmpty() ? Color.blue : Color.red);
-			g.fillPolygon(right_x,right_y,3);
-			if (this==t && leaves.isEmpty())
-			{
-				g.setColor(Color.white);
-				g.fillRect(x+h+4,y,fm.stringWidth(name),h);
-			}
-			g.setColor(Color.black);
-			g.drawString(name,x+h+4,y+fm.getAscent());
-			starty=y;endy=y+h;
-			dx=Math.max(dx,x+h+4+fm.stringWidth(name));
-			y+=h+5;
-		}
-		return new Dimension(dx,y);
-	}
-}
-
-
--- a/lib/browser/GraphBrowser/Vertex.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/***************************************************************************
-  Title:      GraphBrowser/Vertex.java
-  Author:     Stefan Berghofer, TU Muenchen
-  Options:    :tabSize=4:
-
-  This class contains attributes and methods common to all kinds of
-  vertices (e.g. coordinates, successors, predecessors).
-***************************************************************************/
-
-package GraphBrowser;
-
-import java.util.*;
-import java.awt.*;
-import java.io.*;
-
-abstract class Vertex {
-	Vector children=new Vector(10,10);
-	Vector parents=new Vector(10,10);
-	int degree=0;
-	int number=-1;
-	double weight=0;
-	int x,y;
-	Graph gra;
-
-	public abstract Object clone();
-
-	public void setGraph(Graph g) { gra=g; }
-
-	public int countChildren() { return children.size(); }
-
-	/** getInflate returns a vector of vertices which get **/
-	/** inflated again if the user clicks on this vertex  **/
-
-	public void setInflate(Vector v) {}
-
-	public Vector getInflate() { return null; }
-
-	/** getUp returns a vector of vertices which get inflated   **/
-	/** again, if the user clicks on this vertex's upward arrow **/
-
-	public Vector getUp() { return null; }
-
-	public void setUp(Vector v) {}
-
-	/** getUp returns a vector of vertices which get inflated     **/
-	/** again, if the user clicks on this vertex's downward arrow **/
-
-	public Vector getDown() { return null; }
-
-	public void setDown(Vector v) {}
-
-	/** internal number, for decoding / encoding etc. **/
-
-	public int getNumber() { return number; }
-
-	public void setNumber(int n) { number=n; }
-
-	public String getLabel() {return "";}
-
-	public void setLabel(String s) {}
-
-	/** unique identifier **/
-
-	public String getID() {return "";}
-
-	public void setID(String s) {}
-
-	public Box getLabelSize(Graphics g) {
-		AbstractFontMetrics fm = g == null ? 
-      (AbstractFontMetrics) new DefaultFontMetrics(12) : 
-      (AbstractFontMetrics) new AWTFontMetrics(g.getFontMetrics(g.getFont()));
-		
-		return new Box(Math.max(fm.stringWidth("[. . . .]"),
-                            fm.stringWidth(getLabel())),
-                   fm.getAscent()+fm.getDescent());
-	}
-		
-	public String getPath() { return "";}
-
-	public void setPath(String p) {}
-
-	public String getDir() { return ""; }
-
-	public void setDir(String d) {}
-
-	public void setWeight(double w) {weight=w;}
-
-	public double getWeight() {return weight;}
-
-	public void setDegree(int d) { degree=d; }
-
-	public int getDegree() { return degree; }
-
-	public boolean isDummy() { return false; }
-
-	public Enumeration getChildren() {
-		return ((Vector)(children.clone())).elements();
-	}
-
-	public void addChild(Vertex v) {
-		children.addElement(v);
-		v.parents.addElement(this);
-	}
-
-	public void removeChild(Vertex v) {
-		children.removeElement(v);
-		v.parents.removeElement(this);
-	}
-
-	public boolean isChild(Vertex v) {
-		return children.indexOf(v)>=0;
-	}
-
-	public boolean isParent(Vertex v) {
-		return parents.indexOf(v)>=0;
-	}
-
-	public Enumeration getParents() {
-		return ((Vector)(parents.clone())).elements();
-	}
-
-	public void addParent(Vertex v) {
-		parents.addElement(v);
-		v.children.addElement(this);
-	}
-
-	public void removeParent(Vertex v) {
-		parents.removeElement(v);
-		v.children.removeElement(this);
-	}
-
-	/********************************************************************/
-	/*                   get all predecessor vertices                   */
-	/********************************************************************/
-
-	public Vector getPreds() {
-	    Vector preds=new Vector(10,10);
-	    Vector todo=(Vector)(parents.clone());
-	    Vertex vx1,vx2;
-	    Enumeration e;
-
-	    while (!todo.isEmpty()) {
-		vx1=(Vertex)(todo.lastElement());
-		todo.removeElementAt(todo.size()-1);
-		preds.addElement(vx1);
-		e=vx1.parents.elements();
-		while (e.hasMoreElements()) {
-		    vx2=(Vertex)(e.nextElement());
-		    if (preds.indexOf(vx2)<0 && todo.indexOf(vx2)<0)
-			todo.addElement(vx2);
-		}
-	    }
-
-	    return preds;
-	}
-
-	/********************************************************************/
-	/*                     get all successor vertices                   */
-	/********************************************************************/
-
-	public Vector getSuccs() {
-	    Vector succs=new Vector(10,10);
-	    Vector todo=(Vector)(children.clone());
-	    Vertex vx1,vx2;
-	    Enumeration e;
-
-	    while (!todo.isEmpty()) {
-		vx1=(Vertex)(todo.lastElement());
-		todo.removeElementAt(todo.size()-1);
-		succs.addElement(vx1);
-		e=vx1.children.elements();
-		while (e.hasMoreElements()) {
-		    vx2=(Vertex)(e.nextElement());
-		    if (succs.indexOf(vx2)<0 && todo.indexOf(vx2)<0)
-			todo.addElement(vx2);
-		}
-	    }
-
-	    return succs;
-	}
-
-	public int box_width() { return getLabelSize(gra.gfx).width+8; }
-
-	public int box_width2() { return box_width()/2; }
-
-	public void setX(int x) {this.x=x;}
-
-	public void setY(int y) {this.y=y;}
-
-	public int getX() {return x;}
-
-	public int getY() {return y;}
-
-	public abstract int leftX();
-
-	public abstract int rightX();
-
-	public abstract void draw(Graphics g);
-
-	public void drawButtons(Graphics g) {}
-
-	public void drawBox(Graphics g,Color boxColor) {}
-
-	public void removeButtons(Graphics g) {}
-
-	public boolean contains(int x,int y) { return false; }
-
-	public boolean leftButton(int x,int y) { return false; }
-
-	public boolean rightButton(int x,int y) { return false; }
-
-	public void PS(PrintWriter p) {}
-}
--- a/lib/browser/awtUtilities/Border.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/***************************************************************************
-  Title:      awtUtilities/Border.java
-  Author:     Stefan Berghofer, TU Muenchen
-
-  This class defines a nice 3D border.
-***************************************************************************/
-
-package awtUtilities;
-
-import java.awt.*;
-
-public class Border extends Panel {
-	int bs;
-
-	public Insets getInsets() {
-		return new Insets(bs*3/2,bs*3/2,bs*3/2,bs*3/2);
-	}
-
-	public Border(Component comp,int s) {
-		setLayout(new GridLayout(1,1));
-		add(comp);
-		bs=s;
-	}
-
-	public void paint(Graphics g) {
-		int w = getSize().width;
-		int h = getSize().height;
-		int x1[]={0,bs,w-bs,w}, y1[]={0,bs,bs,0};
-		int x2[]={w,w-bs,w-bs,w}, y2[]={0,bs,h-bs,h};
-		int y3[]={h,h-bs,h-bs,h};
-
-		g.setColor(new Color(224,224,224));
-		g.fillPolygon(y1,y2,4);
-		g.fillPolygon(x1,y1,4);
-		g.setColor(Color.gray);
-		g.fillPolygon(x2,y2,4);
-		g.fillPolygon(x1,y3,4);
-	}
-}
--- a/lib/browser/awtUtilities/MessageDialog.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/***************************************************************************
-  Title:      awtUtilities/MessageDialog.java
-  Author:     Stefan Berghofer, TU Muenchen
-
-  This class defines a dialog window for displaying messages and buttons.
-***************************************************************************/
-
-package awtUtilities;
-
-import java.awt.*;
-import java.awt.event.*;
-
-public class MessageDialog extends Dialog implements ActionListener {
-	String txt;
-
-	public String getText() { return txt; }
-
-	public void actionPerformed(ActionEvent evt) {
-		txt = evt.getActionCommand();
-		setVisible(false);
-	}
-
-	public MessageDialog(Frame parent,String title,String text,String []buttons) {
-		super(parent,title,true);
-		int i;
-		Panel p1=new Panel(),p2=new Panel();
-		p1.setLayout(new FlowLayout(FlowLayout.CENTER,0,0));
-		p2.setLayout(new FlowLayout());
-		setFont(new Font("Helvetica", Font.PLAIN, 14));
-		setLayout(new GridLayout(2,1));
-
-		while (true) {
-			int pos=text.indexOf(' ');
-			if (pos<0) {
-				p1.add(new Label(text));
-				break;
-			} else {
-				p1.add(new Label(text.substring(0,pos)));
-				if (pos+1==text.length())
-					break;
-				else
-					text=text.substring(pos+1);
-			}
-		}
-
-		add(p1);add(p2);
-		for (i=0;i<buttons.length;i++) {
-			Button bt = new Button(buttons[i]);
-			p2.add(bt);
-			bt.addActionListener(this);
-		}
-	}
-}
--- a/lib/browser/awtUtilities/TextFrame.java	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/***************************************************************************
-  Title:      Graph/TextFrame.java
-  Author:     Stefan Berghofer, TU Muenchen
-
-  This class defines a simple text viewer.
-***************************************************************************/
-
-package awtUtilities;
-
-import java.awt.*;
-import java.awt.event.*;
-
-public class TextFrame extends Frame implements ActionListener {
-	public void actionPerformed(ActionEvent evt) {
-		setVisible(false);
-	}
-
-	public TextFrame(String title,String text) {
-		super(title);
-		TextArea ta = new TextArea(text,200,80);
-		Button bt = new Button("Dismiss");
-		bt.addActionListener(this);
-		ta.setEditable(false);
-		add("Center", ta);
-		add("South", bt);
-	}
-}
--- a/lib/browser/build	Wed Jul 07 15:40:00 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-#!/usr/bin/env bash
-#
-# Author: Makarius
-#
-# mk - build graph browser
-#
-# Requires proper Isabelle settings environment.
-
-
-## diagnostics
-
-function fail()
-{
-  echo "$1" >&2
-  exit 2
-}
-
-[ -n "$ISABELLE_HOME" ] || fail "Missing Isabelle settings environment"
-
-
-## dependencies
-
-declare -a SOURCES=(
-  GraphBrowser/AWTFontMetrics.java
-  GraphBrowser/AbstractFontMetrics.java
-  GraphBrowser/Box.java
-  GraphBrowser/Console.java
-  GraphBrowser/DefaultFontMetrics.java
-  GraphBrowser/Directory.java
-  GraphBrowser/DummyVertex.java
-  GraphBrowser/Graph.java
-  GraphBrowser/GraphBrowser.java
-  GraphBrowser/GraphBrowserFrame.java
-  GraphBrowser/GraphView.java
-  GraphBrowser/NormalVertex.java
-  GraphBrowser/ParseError.java
-  GraphBrowser/Region.java
-  GraphBrowser/Spline.java
-  GraphBrowser/TreeBrowser.java
-  GraphBrowser/TreeNode.java
-  GraphBrowser/Vertex.java
-  awtUtilities/Border.java
-  awtUtilities/MessageDialog.java
-  awtUtilities/TextFrame.java
-)
-
-TARGET="$ISABELLE_HOME/lib/browser/GraphBrowser.jar"
-
-
-## main
-
-OUTDATED=false
-
-for SOURCE in "${SOURCES[@]}"
-do
-  [ ! -e "$SOURCE" ] && fail "Missing source file: $SOURCE"
-  [ ! -e "$TARGET" -o "$SOURCE" -nt "$TARGET" ] && OUTDATED=true
-done
-
-if [ "$OUTDATED" = true ]
-then
-  echo >&2 "### Building graph browser ..."
-
-  rm -rf classes && mkdir classes
-
-  isabelle_jdk javac -d classes -source 7 "${SOURCES[@]}" || \
-    fail "Failed to compile sources"
-  isabelle_jdk jar cf "$(platform_path "$TARGET")" -C classes . ||
-    fail "Failed to produce $TARGET"
-
-  rm -rf classes
-fi
--- a/lib/scripts/getfunctions	Wed Jul 07 15:40:00 2021 +0200
+++ b/lib/scripts/getfunctions	Tue Aug 17 17:09:20 2021 +0200
@@ -106,7 +106,7 @@
   do
     if [ -z "$ISABELLE_CLASSPATH" ]; then
       ISABELLE_CLASSPATH="$X"
-    else
+    elif [ -n "$X" ]; then
       ISABELLE_CLASSPATH="$ISABELLE_CLASSPATH:$X"
     fi
   done
@@ -211,17 +211,6 @@
 }
 export -f isabelle_directory
 
-#administrative build
-if [ -e "$ISABELLE_HOME/Admin/build" ]; then
-  function isabelle_admin_build ()
-  {
-    "$ISABELLE_HOME/Admin/build" "$@"
-  }
-else
-  function isabelle_admin_build () { return 0; }
-fi
-export -f isabelle_admin_build
-
 #arrays
 function splitarray ()
 {
--- a/lib/scripts/getsettings	Wed Jul 07 15:40:00 2021 +0200
+++ b/lib/scripts/getsettings	Tue Aug 17 17:09:20 2021 +0200
@@ -129,6 +129,10 @@
   export JAVA_HOME="$ISABELLE_JDK_HOME"
 fi
 
+if [ -e "$ISABELLE_SETUP_JAR" ]; then
+  ISABELLE_SETUP_CLASSPATH="$(isabelle_java java -jar "$(platform_path "$ISABELLE_SETUP_JAR")" classpath)"
+fi
+
 set +o allexport
 
 fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/services/java.nio.charset.spi.CharsetProvider	Tue Aug 17 17:09:20 2021 +0200
@@ -0,0 +1,1 @@
+isabelle.Isabelle_Charset_Provider
--- a/src/Doc/Isar_Ref/Document_Preparation.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/Doc/Isar_Ref/Document_Preparation.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -95,6 +95,7 @@
     @{antiquotation_def type} & : & \<open>antiquotation\<close> \\
     @{antiquotation_def class} & : & \<open>antiquotation\<close> \\
     @{antiquotation_def locale} & : & \<open>antiquotation\<close> \\
+    @{antiquotation_def bundle} & : & \<open>antiquotation\<close> \\
     @{antiquotation_def "text"} & : & \<open>antiquotation\<close> \\
     @{antiquotation_def goals} & : & \<open>antiquotation\<close> \\
     @{antiquotation_def subgoals} & : & \<open>antiquotation\<close> \\
@@ -195,6 +196,7 @@
       @@{antiquotation type} options @{syntax embedded} |
       @@{antiquotation class} options @{syntax embedded} |
       @@{antiquotation locale} options @{syntax embedded} |
+      @@{antiquotation bundle} options @{syntax embedded} |
       (@@{antiquotation command} | @@{antiquotation method} | @@{antiquotation attribute})
         options @{syntax name}
     ;
@@ -272,6 +274,8 @@
 
   \<^descr> \<open>@{locale c}\<close> prints a locale \<open>c\<close>.
 
+  \<^descr> \<open>@{bundle c}\<close> prints a bundle \<open>c\<close>.
+
   \<^descr> \<open>@{command name}\<close>, \<open>@{method name}\<close>, \<open>@{attribute name}\<close> print checked
   entities of the Isar language.
 
--- a/src/Doc/JEdit/JEdit.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/Doc/JEdit/JEdit.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -206,7 +206,7 @@
   is no longer affected by change of default properties.
 
   Users may modify their keymap later, but this can lead to conflicts with
-  \<^verbatim>\<open>shortcut\<close> properties in \<^file>\<open>$JEDIT_HOME/dist/properties/jEdit.props\<close>.
+  \<^verbatim>\<open>shortcut\<close> properties in \<^file>\<open>$JEDIT_HOME/properties/jEdit.props\<close>.
 
   The action @{action_def "isabelle.keymap-merge"} helps to resolve pending
   Isabelle keymap changes wrt. the current jEdit keymap; non-conflicting
@@ -282,10 +282,9 @@
   directly to the underlying \<^verbatim>\<open>java\<close> process.
 
   The \<^verbatim>\<open>-b\<close> and \<^verbatim>\<open>-f\<close> options control the self-build mechanism of
-  Isabelle/jEdit. This is only relevant for building from sources, which also
-  requires an auxiliary \<^verbatim>\<open>jedit_build\<close> component from
-  \<^url>\<open>https://isabelle.in.tum.de/components\<close>. The official Isabelle release
-  already includes a pre-built version of Isabelle/jEdit.
+  Isabelle/Scala/PIDE/jEdit. This is only relevant for building from sources,
+  the official Isabelle release already includes a pre-built version of
+  Isabelle/jEdit.
 
   \<^bigskip>
   It is also possible to connect to an already running Isabelle/jEdit process
--- a/src/Doc/Sledgehammer/document/root.tex	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/Doc/Sledgehammer/document/root.tex	Tue Aug 17 17:09:20 2021 +0200
@@ -109,8 +109,8 @@
 Vampire \cite{riazanov-voronkov-2002}, Waldmeister \cite{waldmeister}, and
 Zipperposition \cite{cruanes-2014}. The ATPs are run either locally or remotely
 via the System\-On\-TPTP web service \cite{sutcliffe-2000}. The supported SMT
-solvers are CVC3 \cite{cvc3}, CVC4 \cite{cvc4}, veriT \cite{bouton-et-al-2009},
-and Z3 \cite{de-moura-2008}. These are always run locally.
+solvers are CVC4 \cite{cvc4}, veriT \cite{bouton-et-al-2009}, and Z3
+\cite{de-moura-2008}. These are always run locally.
 
 The problem passed to the external provers (or solvers) consists of your current
 goal together with a heuristic selection of hundreds of facts (theorems) from the
@@ -147,12 +147,11 @@
 Sledgehammer is part of Isabelle, so you do not need to install it. However, it
 relies on third-party automatic provers (ATPs and SMT solvers).
 
-Among the ATPs, agsyHOL, Alt-Ergo, E, LEO-II, Leo-III, Satallax, SPASS,
-Vampire, and Zipperposition can be run locally; in addition, agsyHOL,
-Alt-Ergo, E, iProver, LEO-II, Leo-III, Satallax, Vampire, Waldmeister,
-and Zipperposition are available remotely via System\-On\-TPTP
-\cite{sutcliffe-2000}. The SMT solvers CVC3, CVC4, veriT, and Z3 can be run
-locally.
+Among the ATPs, agsyHOL, Alt-Ergo, E, LEO-II, Leo-III, Satallax, SPASS, Vampire,
+and Zipperposition can be run locally; in addition, agsyHOL, Alt-Ergo, E,
+iProver, LEO-II, Leo-III, Satallax, Vampire, Waldmeister, and Zipperposition are
+available remotely via System\-On\-TPTP \cite{sutcliffe-2000}. The SMT solvers
+CVC4, veriT, and Z3 can be run locally.
 
 There are three main ways to install automatic provers on your machine:
 
@@ -164,9 +163,9 @@
 noncommercial user, as indicated by the message that is displayed when
 Sledgehammer is invoked the first time.
 
-\item[\labelitemi] Alternatively, you can download the Isabelle-aware CVC3,
-CVC4, E, SPASS, Vampire, veriT, and Z3 binary packages from \download. Extract
-the archives, then add a line to your \texttt{\$ISABELLE\_HOME\_USER\slash
+\item[\labelitemi] Alternatively, you can download the Isabelle-aware CVC4, E,
+SPASS, Vampire, veriT, and Z3 binary packages from \download. Extract the
+archives, then add a line to your \texttt{\$ISABELLE\_HOME\_USER\slash
 etc\slash components}%
 \footnote{The variable \texttt{\$ISABELLE\_HOME\_USER} is set by Isabelle at
 startup. Its value can be retrieved by executing \texttt{isabelle}
@@ -189,24 +188,17 @@
 \texttt{eprover} (and/or \texttt{eproof} or \texttt{eproof\_ram}),
 \texttt{leo}, \texttt{leo3}, or \texttt{satallax} executable;
 for Alt-Ergo, set the environment variable \texttt{WHY3\_HOME} to the
-directory that contains the \texttt{why3} executable. Sledgehammer has been
-tested with agsyHOL 1.0, Alt-Ergo 0.95.2, E 1.6 to 2.0, LEO-II 1.3.4, Leo-III
-1.1, and Satallax 2.7. Since the ATPs' output formats are neither documented
-nor stable, other versions might not work well with Sledgehammer. Ideally, you
+directory that contains the \texttt{why3} executable. Ideally, you
 should also set \texttt{E\_VERSION}, \texttt{LEO2\_VERSION},
 \texttt{LEO3\_VERSION}, or \texttt{SATALLAX\_VERSION} to the prover's version
-number (e.g., ``2.7''); this might help Sledgehammer invoke the prover
-optimally.
+number (e.g., ``3.6'').
 
-Similarly, if you want to install CVC3, CVC4, veriT, or Z3, set the environment
-variable \texttt{CVC3\_\allowbreak SOLVER}, \texttt{CVC4\_\allowbreak SOLVER},
-\texttt{VERIT\_\allowbreak SOLVER}, or \texttt{Z3\_SOLVER} to the complete path
-of the executable, \emph{including the file name}. Sledgehammer has been tested
-with CVC3 2.2 and 2.4.1, CVC4 1.5-prerelease, veriT 2020.10-rmx, and Z3 4.3.2.
-Since Z3's output format is somewhat unstable, other versions of the solver
-might not work well with Sledgehammer. Ideally, also set
-\texttt{CVC3\_VERSION}, \texttt{CVC4\_VERSION}, \texttt{VERIT\_VERSION}, or
-\texttt{Z3\_VERSION} to the solver's version number (e.g., ``4.4.0'').
+Similarly, if you want to install CVC4, veriT, or Z3, set the environment
+variable \texttt{CVC4\_\allowbreak SOLVER}, \texttt{VERIT\_\allowbreak SOLVER},
+or \texttt{Z3\_SOLVER} to the complete path of the executable, \emph{including
+the file name}. Ideally, also set \texttt{CVC4\_VERSION},
+\texttt{VERIT\_VERSION}, or \texttt{Z3\_VERSION} to the solver's version number
+(e.g., ``4.4.0'').
 \end{enum}
 \end{sloppy}
 
@@ -457,8 +449,8 @@
 \textit{full\_types} option to \textit{metis} directly.
 
 
-\point{And what are the \textit{lifting} and \textit{hide\_lams} \\ arguments
-to Metis?}
+\point{And what are the \textit{lifting} and \textit{opaque\_lifting} \\
+arguments to Metis?}
 
 Orthogonally to the encoding of types, it is important to choose an appropriate
 translation of $\lambda$-abstractions. Metis supports three translation
@@ -614,7 +606,7 @@
 with the same semantics as Sledgehammer's \textit{type\_enc} option
 (\S\ref{problem-encoding}).
 %
-The supported $\lambda$ translation schemes are \textit{hide\_lams},
+The supported $\lambda$ translation schemes are \textit{opaque\_lifting},
 \textit{lifting}, and \textit{combs} (the default).
 %
 All the untyped type encodings listed in \S\ref{problem-encoding} are supported.
@@ -689,8 +681,7 @@
 \item[\labelitemi] \textbf{\textit{agsyhol}:} agsyHOL is an automatic
 higher-order prover developed by Fredrik Lindblad \cite{agsyHOL}. To use
 agsyHOL, set the environment variable \texttt{AGSYHOL\_HOME} to the directory
-that contains the \texttt{agsyHOL} executable. Sledgehammer has been tested
-with version 1.0.
+that contains the \texttt{agsyHOL} executable.
 
 \item[\labelitemi] \textbf{\textit{alt\_ergo}:} Alt-Ergo is a polymorphic
 ATP developed by Bobot et al.\ \cite{alt-ergo}.
@@ -699,83 +690,73 @@
 to the directory that contains the \texttt{why3} executable. Sledgehammer
 requires Alt-Ergo 0.95.2 and Why3 0.83.
 
-\item[\labelitemi] \textbf{\textit{cvc3}:} CVC3 is an SMT solver developed by
-Clark Barrett, Cesare Tinelli, and their colleagues \cite{cvc3}. To use CVC3,
-set the environment variable \texttt{CVC3\_SOLVER} to the complete path of the
-executable, including the file name, or install the prebuilt CVC3 package from
-\download. Sledgehammer has been tested with versions 2.2 and 2.4.1.
-
-\item[\labelitemi] \textbf{\textit{cvc4}:} CVC4 \cite{cvc4} is the successor to
-CVC3. To use CVC4, set the environment variable \texttt{CVC4\_SOLVER} to the
-complete path of the executable, including the file name, or install the
-prebuilt CVC4 package from \download. Sledgehammer has been tested with version
-1.5-prerelease.
+\item[\labelitemi] \textbf{\textit{cvc4}:} CVC4 is an SMT solver developed by
+Clark Barrett, Cesare Tinelli, and their colleagues \cite{cvc4}. To use CVC4,
+set the environment variable \texttt{CVC4\_SOLVER} to the complete path of the
+executable, including the file name, or install the prebuilt CVC4 package from
+\download.
 
 \item[\labelitemi] \textbf{\textit{e}:} E is a first-order resolution prover
 developed by Stephan Schulz \cite{schulz-2019}. To use E, set the environment
 variable \texttt{E\_HOME} to the directory that contains the \texttt{eproof}
 executable and \texttt{E\_VERSION} to the version number (e.g., ``1.8''), or
-install the prebuilt E package from \download. Sledgehammer has been tested with
-versions 1.6 to 1.8.
+install the prebuilt E package from \download.
 
 \item[\labelitemi] \textbf{\textit{iprover}:} iProver is a pure
-instantiation-based prover developed by Konstantin Korovin
-\cite{korovin-2009}. To use iProver, set the environment variable
-\texttt{IPROVER\_HOME} to the directory that contains the \texttt{iproveropt}
-executable. Sledgehammer has been tested with version 2.8. iProver depends on
-E to clausify problems, so make sure that E is installed as well.
+instantiation-based prover developed by Konstantin Korovin \cite{korovin-2009}.
+To use iProver, set the environment variable \texttt{IPROVER\_HOME} to the
+directory that contains the \texttt{iproveropt} executable. iProver depends on
+Vampire to clausify problems, so make sure that Vampire is installed as well.
 
 \item[\labelitemi] \textbf{\textit{leo2}:} LEO-II is an automatic
 higher-order prover developed by Christoph Benzm\"uller et al.\ \cite{leo2},
 with support for the TPTP typed higher-order syntax (TH0). To use LEO-II, set
 the environment variable \texttt{LEO2\_HOME} to the directory that contains the
-\texttt{leo} executable. Sledgehammer has been tested with version 1.3.4.
+\texttt{leo} executable.
 
 \item[\labelitemi] \textbf{\textit{leo3}:} Leo-III is an automatic
 higher-order prover developed by Alexander Steen, Max Wisniewski, Christoph
 Benzm\"uller et al.\ \cite{leo3},
 with support for the TPTP typed higher-order syntax (TH0). To use Leo-III, set
 the environment variable \texttt{LEO3\_HOME} to the directory that contains the
-\texttt{leo3} executable. Sledgehammer has been tested with version 1.1.
+\texttt{leo3} executable.
 
 \item[\labelitemi] \textbf{\textit{satallax}:} Satallax is an automatic
 higher-order prover developed by Chad Brown et al.\ \cite{satallax}, with
 support for the TPTP typed higher-order syntax (TH0). To use Satallax, set the
 environment variable \texttt{SATALLAX\_HOME} to the directory that contains the
-\texttt{satallax} executable. Sledgehammer has been tested with version 2.2.
+\texttt{satallax} executable.
 
 \item[\labelitemi] \textbf{\textit{spass}:} SPASS is a first-order resolution
 prover developed by Christoph Weidenbach et al.\ \cite{weidenbach-et-al-2009}.
 To use SPASS, set the environment variable \texttt{SPASS\_HOME} to the directory
 that contains the \texttt{SPASS} executable and \texttt{SPASS\_VERSION} to the
 version number (e.g., ``3.8ds''), or install the prebuilt SPASS package from
-\download. Sledgehammer has been tested with version 3.8ds.
+\download.
 
 \item[\labelitemi] \textbf{\textit{vampire}:} Vampire is a first-order
 resolution prover developed by Andrei Voronkov and his colleagues
 \cite{riazanov-voronkov-2002}. To use Vampire, set the environment variable
 \texttt{VAMPIRE\_HOME} to the directory that contains the \texttt{vampire}
 executable and \texttt{VAMPIRE\_VERSION} to the version number (e.g.,
-``4.2.2''). Sledgehammer has been tested with versions 1.8 to 4.2.2 (in the
-post-2010 numbering scheme).
+``4.2.2'').
 
 \item[\labelitemi] \textbf{\textit{verit}:} veriT \cite{bouton-et-al-2009} is an
 SMT solver developed by David D\'eharbe, Pascal Fontaine, and their colleagues.
 It is designed to produce detailed proofs for reconstruction in proof
 assistants. To use veriT, set the environment variable \texttt{VERIT\_SOLVER}
-to the complete path of the executable, including the file name. Sledgehammer
-has been tested with version 2020.10-rmx.
+to the complete path of the executable, including the file name.
 
 \item[\labelitemi] \textbf{\textit{z3}:} Z3 is an SMT solver developed at
 Microsoft Research \cite{de-moura-2008}. To use Z3, set the environment variable
 \texttt{Z3\_SOLVER} to the complete path of the executable, including the
-file name. Sledgehammer has been tested with a pre-release version of 4.4.0.
+file name.
 
 \item[\labelitemi] \textbf{\textit{z3\_tptp}:} This version of Z3 pretends to
 be an ATP, exploiting Z3's support for the TPTP typed first-order format (TF0).
-It is included for experimental purposes. Sledgehammer has been tested with
-version 4.3.1. To use it, set the environment variable \texttt{Z3\_TPTP\_HOME}
-to the directory that contains the \texttt{z3\_tptp} executable.
+It is included for experimental purposes. To use it, set the environment
+variable \texttt{Z3\_TPTP\_HOME} to the directory that contains the
+\texttt{z3\_tptp} executable.
 
 \item[\labelitemi] \textbf{\textit{zipperposition}:} Zipperposition
 \cite{cruanes-2014} is a higher-order superposition prover developed by Simon
@@ -783,7 +764,6 @@
 environment variable \texttt{ZIPPERPOSITION\_HOME} to the directory that
 contains the \texttt{zipperposition} executable and
 \texttt{ZIPPERPOSITION\_VERSION} to the version number (e.g., ``2.0.1'').
-Sledgehammer has been tested with version 2.0.1.
 \end{enum}
 
 \end{sloppy}
@@ -810,9 +790,6 @@
 \item[\labelitemi] \textbf{\textit{remote\_leo3}:} The remote version of Leo-III
 runs on Geoff Sutcliffe's Miami servers \cite{sutcliffe-2000}.
 
-\item[\labelitemi] \textbf{\textit{remote\_vampire}:} The remote version of
-Vampire runs on Geoff Sutcliffe's Miami servers.
-
 \item[\labelitemi] \textbf{\textit{remote\_waldmeister}:} Waldmeister is a unit
 equality prover developed by Hillenbrand et al.\ \cite{waldmeister}. It can be
 used to prove universally quantified equations using unconditional equations,
@@ -961,6 +938,25 @@
 
 \nopagebreak
 {\small See also \textit{type\_enc} (\S\ref{problem-encoding}).}
+
+\opdefault{induction\_rules}{string}{smart}
+Specifies whether induction rules should be considered as relevant facts.
+The following behaviors are available:
+\begin{enum}
+\item[\labelitemi] \textbf{\textit{include}:}
+Induction rules are considered by the relevance filter.
+
+\item[\labelitemi] \textbf{\textit{exclude}:}
+Induction rules are ignored by the relevance filter.
+
+\item[\labelitemi] \textbf{\textit{instantiated}:}
+Induction rules are instantiated based on the conjecture and then
+considered by the relevance filter.
+
+\item[\labelitemi] \textbf{\textit{smart}:}
+Same as \textit{include} if the prover supports higher-order logic;
+same as \textit{exclude} otherwise.
+\end{enum}
 \end{enum}
 
 
@@ -975,14 +971,15 @@
 translation schemes are listed below:
 
 \begin{enum}
-\item[\labelitemi] \textbf{\textit{hide\_lams}:} Hide the $\lambda$-abstractions
-by replacing them by unspecified fresh constants, effectively disabling all
-reasoning under $\lambda$-abstractions.
-
 \item[\labelitemi] \textbf{\textit{lifting}:} Introduce a new
 supercombinator \const{c} for each cluster of $n$~$\lambda$-abstractions,
 defined using an equation $\const{c}~x_1~\ldots~x_n = t$ ($\lambda$-lifting).
 
+\item[\labelitemi] \textbf{\textit{opaque\_lifting}:} Same as
+\textit{lifting}, except that the supercombinators are kept opaque,
+i.e. they are unspecified fresh constants. This effectively disables
+all reasoning under $\lambda$-abstractions.
+
 \item[\labelitemi] \textbf{\textit{combs}:} Rewrite lambdas to the Curry
 combinators (\comb{I}, \comb{K}, \comb{S}, \comb{B}, \comb{C}). Combinators
 enable the ATPs to synthesize $\lambda$-terms but tend to yield bulkier formulas
@@ -990,6 +987,10 @@
 equational definitions of the combinators are very prolific in the context of
 resolution.
 
+\item[\labelitemi] \textbf{\textit{opaque\_combs}:} Same as
+\textit{combs}, except that the combinators are kept opaque, i.e. without
+equational definitions.
+
 \item[\labelitemi] \textbf{\textit{combs\_and\_lifting}:} Introduce a new
 supercombinator \const{c} for each cluster of $\lambda$-abstractions and characterize it both using a
 lifted equation $\const{c}~x_1~\ldots~x_n = t$ and via Curry combinators.
@@ -1246,9 +1247,9 @@
     -A ACTION    add to list of actions
     -O DIR       output directory for log files (default: "mirabelle")
     -T THEORY    theory restriction: NAME or NAME[FIRST_LINE:LAST_LINE]
-    -m INT       max. no. of calls to each Mirabelle action (default 0)
-    -s INT       run actions on every nth goal (default 1)
-    -t SECONDS   timeout for each action (default 30.000)
+    -m INT       max. no. of calls to each action (0: unbounded) (default 0)
+    -s INT       run actions on every nth goal (0: uniform distribution) (default 1)
+    -t SECONDS   timeout in seconds for each action (default 30)
     ...
 
   Apply the given ACTIONs at all theories and proof steps of the
@@ -1329,16 +1330,16 @@
 
 \begin{verbatim}
 isabelle mirabelle -d $AFP -O output \
-  -A "sledgehammer[prover=e, prover_timeout=5, keep=/tptp]" \
+  -A "sledgehammer[prover=e, prover_timeout=5, keep=true]" \
   VeriComp
 \end{verbatim}
 
 This command generates TPTP files using Sledgehammer. Since the file
 is generated at the very beginning of every Sledgehammer invocation,
 a timeout of five seconds making the prover fail faster speeds up
-processing the subgoals. The results are written in the specified directory
-(\texttt{/tptp}), which must exist beforehand. A TPTP file is generated
-for each subgoal.
+processing the subgoals. The results are written in an action-specific
+subdirectory of the specified output directory (\texttt{output}). A TPTP
+file is generated for each subgoal.
 
 \let\em=\sl
 \bibliography{manual}{}
--- a/src/Doc/System/Environment.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/Doc/System/Environment.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -459,7 +459,7 @@
 text \<open>
   The subsequent example creates a raw Java process on the command-line and
   invokes the main Isabelle application entry point:
-  @{verbatim [display] \<open>isabelle_java isabelle.Main\<close>}
+  @{verbatim [display] \<open>isabelle_java -Djava.awt.headless=false isabelle.jedit.Main\<close>}
 \<close>
 
 
--- a/src/Doc/System/Scala.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/Doc/System/Scala.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -31,30 +31,22 @@
     operates on the running Java application, using the Scala
     read-eval-print-loop (REPL).
 
-  The main Isabelle/Scala functionality is provided by \<^verbatim>\<open>Pure.jar\<close>, but
-  further add-ons are bundled with Isabelle, e.g.\ to access SQLite or
-  PostgreSQL using JDBC (Java Database Connectivity).
-
-  Other components may augment the system environment by providing a suitable
-  \<^path>\<open>etc/settings\<close> shell script in the component directory. Some shell
-  functions are available to help with that:
-
-    \<^item> Function \<^bash_function>\<open>classpath\<close> adds \<^verbatim>\<open>jar\<close> files in Isabelle path
-    notation (POSIX). On Windows, this is converted to native path names
-    before invoking @{tool java} or @{tool scala} (\secref{sec:scala-tools}).
+  The main Isabelle/Scala/jEdit functionality is provided by
+  \<^file>\<open>$ISABELLE_HOME/lib/classes/isabelle.jar\<close>. Further underlying Scala and
+  Java libraries are bundled with Isabelle, e.g.\ to access SQLite or
+  PostgreSQL via JDBC.
 
-    \<^item> Function \<^bash_function>\<open>isabelle_scala_service\<close> registers global
-    service providers as subclasses of
-    \<^scala_type>\<open>isabelle.Isabelle_System.Service\<close>, using the raw Java name
-    according to @{scala_method (in java.lang.Object) getClass} (it should be
-    enclosed in single quotes to avoid special characters like \<^verbatim>\<open>$\<close> to be
-    interpreted by the shell).
+  Add-on Isabelle components may augment the system environment by providing
+  suitable configuration in \<^path>\<open>etc/settings\<close> (GNU bash script). The
+  shell function \<^bash_function>\<open>classpath\<close> helps to write
+  \<^path>\<open>etc/settings\<close> in a portable manner: it refers to library \<^verbatim>\<open>jar\<close>
+  files in standard POSIX path notation. On Windows, this is converted to
+  native platform format, before invoking Java (\secref{sec:scala-tools}).
 
-    Particular Isabelle/Scala services require particular subclasses:
-    instances are filtered according to their dynamic type. For example, class
-    \<^scala_type>\<open>isabelle.Isabelle_Scala_Tools\<close> collects Scala command-line
-    tools, and class \<^scala_type>\<open>isabelle.Scala.Functions\<close>
-    collects Scala functions (\secref{sec:scala-functions}).
+  \<^medskip>
+  There is also an implicit build process for Isabelle/Scala/Java modules,
+  based on \<^path>\<open>etc/build.props\<close> within the component directory (see also
+  \secref{sec:scala-build}).
 \<close>
 
 
@@ -103,25 +95,6 @@
 \<close>
 
 
-subsection \<open>Scala compiler \label{sec:tool-scalac}\<close>
-
-text \<open>
-  The @{tool_def scalac} tool is a direct wrapper for the Scala compiler; see
-  also @{tool scala} above. The command line arguments are that of the
-  bundled Scala distribution.
-
-  This allows to compile further Scala modules, depending on existing
-  Isabelle/Scala functionality. The resulting \<^verbatim>\<open>class\<close> or \<^verbatim>\<open>jar\<close> files can be
-  added to the Java classpath using the shell function
-  \<^bash_function>\<open>classpath\<close>. Thus add-on components can register themselves
-  in a modular manner, see also \secref{sec:components}.
-
-  Note that Isabelle/jEdit @{cite "isabelle-jedit"} has its own mechanisms for
-  adding plugin components. This needs special attention, since it overrides
-  the standard Java class loader.
-\<close>
-
-
 subsection \<open>Scala script wrapper\<close>
 
 text \<open>
@@ -143,16 +116,167 @@
 \<close>
 
 
-subsection \<open>Project setup for common Scala IDEs\<close>
+subsection \<open>Scala compiler \label{sec:tool-scalac}\<close>
+
+text \<open>
+  The @{tool_def scalac} tool is a direct wrapper for the Scala compiler; see
+  also @{tool scala} above. The command line arguments are that of the
+  bundled Scala distribution.
+
+  This provides a low-level mechanism to compile further Scala modules,
+  depending on existing Isabelle/Scala functionality; the resulting \<^verbatim>\<open>class\<close>
+  or \<^verbatim>\<open>jar\<close> files can be added to the Java classpath using the shell function
+  \<^bash_function>\<open>classpath\<close>.
+
+  A more convenient high-level approach works via \<^path>\<open>etc/build.props\<close>
+  (see \secref{sec:scala-build}).
+\<close>
+
+
+section \<open>Isabelle/Scala/Java modules \label{sec:scala-build}\<close>
+
+subsection \<open>Component configuration via \<^path>\<open>etc/build.props\<close>\<close>
 
 text \<open>
-  The @{tool_def scala_project} tool creates a project configuration for
-  Isabelle/Scala/jEdit:
+  Isabelle components may augment the Isabelle/Scala/Java environment
+  declaratively via properties given in \<^path>\<open>etc/build.props\<close> (within the
+  component directory). This specifies an output \<^verbatim>\<open>jar\<close> \<^emph>\<open>module\<close>, based on
+  Scala or Java \<^emph>\<open>sources\<close>, and arbitrary \<^emph>\<open>resources\<close>. Moreover, a module can
+  specify \<^emph>\<open>services\<close> that are subclasses of
+  \<^scala_type>\<open>isabelle.Isabelle_System.Service\<close>; these have a particular
+  meaning to Isabelle/Scala tools.
+
+  Before running a Scala or Java process, the Isabelle system implicitly
+  ensures that all provided modules are compiled and packaged (as jars). It is
+  also possible to invoke @{tool scala_build} explicitly, with extra options.
+
+  \<^medskip>
+  The syntax of in \<^path>\<open>etc/build.props\<close> follows a regular Java properties
+  file\<^footnote>\<open>\<^url>\<open>https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/Properties.html#load(java.io.Reader)\<close>\<close>,
+  but the encoding is \<^verbatim>\<open>UTF-8\<close>, instead of historic \<^verbatim>\<open>ISO 8859-1\<close> from the API
+  documentation.
+
+  The subsequent properties are relevant for the Scala/Java build process.
+  Most properties are optional: the default is an empty string (or list). File
+  names are relative to the main component directory and may refer to Isabelle
+  settings variables (e.g. \<^verbatim>\<open>$ISABELLE_HOME\<close>).
+
+    \<^item> \<^verbatim>\<open>title\<close> (required) is a human-readable description of the module, used
+    in printed messages.
+
+    \<^item> \<^verbatim>\<open>module\<close> specifies a \<^verbatim>\<open>jar\<close> file name for the output module, as result
+    of the specified sources (and resources). If this is absent (or
+    \<^verbatim>\<open>no_build\<close> is set, as described below), there is no implicit build
+    process. The contributing sources might be given nonetheless, notably for
+    @{tool scala_project} (\secref{sec:tool-scala-project}), which includes
+    Scala/Java sources of components, while suppressing \<^verbatim>\<open>jar\<close> modules (to
+    avoid duplication of program content).
+
+    \<^item> \<^verbatim>\<open>no_build\<close> is a Boolean property, with default \<^verbatim>\<open>false\<close>. If set to
+    \<^verbatim>\<open>true\<close>, the implicit build process for the given \<^verbatim>\<open>module\<close> is \<^emph>\<open>omitted\<close>
+    --- it is assumed to be provided by other means.
+
+    \<^item> \<^verbatim>\<open>scalac_options\<close> and \<^verbatim>\<open>javac_options\<close> augment the default settings
+    @{setting_ref ISABELLE_SCALAC_OPTIONS} and @{setting_ref
+    ISABELLE_JAVAC_OPTIONS} for this component; option syntax follows the
+    regular command-line tools \<^verbatim>\<open>scalac\<close> and \<^verbatim>\<open>javac\<close>, respectively.
+
+    \<^item> \<^verbatim>\<open>main\<close> specifies the main entry point for the \<^verbatim>\<open>jar\<close> module. This is
+    only relevant for direct invocation like ``\<^verbatim>\<open>java -jar test.jar\<close>''.
+
+    \<^item> \<^verbatim>\<open>requirements\<close> is a list of \<^verbatim>\<open>jar\<close> modules that are needed in the
+    compilation process, but not provided by the regular classpath (notably
+    @{setting ISABELLE_CLASSPATH}).
+
+    A \<^emph>\<open>normal entry\<close> refers to a single \<^verbatim>\<open>jar\<close> file name, possibly with
+    settings variables as usual. E.g. \<^file>\<open>$ISABELLE_SCALA_JAR\<close> for the main
+    \<^file>\<open>$ISABELLE_HOME/lib/classes/isabelle.jar\<close> (especially relevant for
+    add-on modules).
+
+    A \<^emph>\<open>special entry\<close> is of of the form \<^verbatim>\<open>env:\<close>\<open>variable\<close> and refers to a
+    settings variable from the Isabelle environment: its value may consist of
+    multiple \<^verbatim>\<open>jar\<close> entries (separated by colons). Environment variables are
+    not expanded recursively.
+
+    \<^item> \<^verbatim>\<open>resources\<close> is a list of files that should be included in the resulting
+    \<^verbatim>\<open>jar\<close> file. Each item consists of a pair separated by colon:
+    \<open>source\<close>\<^verbatim>\<open>:\<close>\<open>target\<close> means to copy an existing source file (relative to
+    the component directory) to the given target file or directory (relative
+    to the \<^verbatim>\<open>jar\<close> name space). A \<open>file\<close> specification without colon
+    abbreviates \<open>file\<close>\<^verbatim>\<open>:\<close>\<open>file\<close>, i.e. the file is copied while retaining its
+    relative path name.
+
+    \<^item> \<^verbatim>\<open>sources\<close> is a list of \<^verbatim>\<open>.scala\<close> or \<^verbatim>\<open>.java\<close> files that contribute to
+    the specified module. It is possible to use both languages simultaneously:
+    the Scala and Java compiler will be invoked consecutively to make this
+    work.
+
+    \<^item> \<^verbatim>\<open>services\<close> is a list of class names to be registered as Isabelle
+    service providers (subclasses of
+    \<^scala_type>\<open>isabelle.Isabelle_System.Service\<close>). Internal class names of
+    the underlying JVM need to be given: e.g. see method @{scala_method (in
+    java.lang.Object) getClass}.
+
+    Particular services require particular subclasses: instances are filtered
+    according to their dynamic type. For example, class
+    \<^scala_type>\<open>isabelle.Isabelle_Scala_Tools\<close> collects Scala command-line
+    tools, and class \<^scala_type>\<open>isabelle.Scala.Functions\<close> collects Scala
+    functions (\secref{sec:scala-functions}).
+\<close>
+
+
+subsection \<open>Explicit Isabelle/Scala/Java build \label{sec:tool-scala-build}\<close>
+
+text \<open>
+  The @{tool_def scala_build} tool explicitly invokes the build process for
+  all registered components.
   @{verbatim [display]
-\<open>Usage: isabelle scala_project [OPTIONS] PROJECT_DIR
+\<open>Usage: isabelle scala_build [OPTIONS]
 
   Options are:
-    -L           make symlinks to original scala files
+    -f           force fresh build
+    -q           quiet mode: suppress stdout/stderr
+
+  Build Isabelle/Scala/Java modules of all registered components
+  (if required).
+\<close>}
+
+  For each registered Isabelle component that provides
+  \<^path>\<open>etc/build.props\<close>, the specified output \<^verbatim>\<open>module\<close> is checked against
+  the corresponding input \<^verbatim>\<open>requirements\<close>, \<^verbatim>\<open>resources\<close>, \<^verbatim>\<open>sources\<close>. If
+  required, there is an automatic build using \<^verbatim>\<open>scalac\<close> or \<^verbatim>\<open>javac\<close> (or both).
+  The identity of input files is recorded within the output \<^verbatim>\<open>jar\<close>, using SHA1
+  digests in \<^verbatim>\<open>META-INF/isabelle/shasum\<close>.
+
+  \<^medskip>
+  Option \<^verbatim>\<open>-f\<close> forces a fresh build, regardless of the up-to-date status of
+  input files vs. the output module.
+
+  \<^medskip>
+  Option \<^verbatim>\<open>-q\<close> suppresses all output on stdout/stderr produced by the Scala or
+  Java compiler.
+
+  \<^medskip> Explicit invocation of \<^verbatim>\<open>isabelle scala_build\<close> mainly serves testing or
+  applications with special options: the Isabelle system normally does an
+  automatic the build on demand.
+\<close>
+
+
+subsection \<open>Project setup for common Scala IDEs \label{sec:tool-scala-project}\<close>
+
+text \<open>
+  The @{tool_def scala_project} tool creates a project configuration for all
+  Isabelle/Scala/Java modules specified in components via
+  \<^path>\<open>etc/build.props\<close>, together with additional source files given on
+  the command-line:
+
+  @{verbatim [display]
+\<open>Usage: isabelle scala_project [OPTIONS] [MORE_SOURCES ...]
+
+  Options are:
+    -D DIR       project directory (default: "$ISABELLE_HOME_USER/scala_project")
+    -L           make symlinks to original source files
+    -f           force update of existing directory
 
   Setup Gradle project for Isabelle/Scala/jEdit --- to support Scala IDEs
   such as IntelliJ IDEA.\<close>}
@@ -162,19 +286,36 @@
   IDEA\<^footnote>\<open>\<^url>\<open>https://www.jetbrains.com/idea\<close>\<close>. This allows to explore the
   sources with static analysis and other hints in real-time.
 
-  The specified project directory needs to be fresh. The generated files refer
-  to physical file-system locations, using the path notation of the underlying
-  OS platform. Thus the project needs to be recreated whenever the Isabelle
-  installation is changed or moved.
+  The generated files refer to physical file-system locations, using the path
+  notation of the underlying OS platform. Thus the project needs to be
+  recreated whenever the Isabelle installation is changed or moved.
+
+  \<^medskip>
+  Option \<^verbatim>\<open>-L\<close> produces \<^emph>\<open>symlinks\<close> to the original files: this allows to
+  develop Isabelle/Scala/jEdit modules within an external IDE. Note that the
+  result cannot be built within the IDE: it requires implicit or explicit
+  \<^verbatim>\<open>isabelle scala_build\<close> (\secref{sec:tool-scala-build}) instead.
+
+  The default is to \<^emph>\<open>copy\<close> source files, so editing them within the IDE has
+  no permanent effect on the originals.
 
   \<^medskip>
-  By default, Scala sources are \<^emph>\<open>copied\<close> from the Isabelle distribution and
-  editing them within the IDE has no permanent effect.
+  Option \<^verbatim>\<open>-D\<close> specifies an explicit project directory, instead of the default
+  \<^path>\<open>$ISABELLE_HOME_USER/scala_project\<close>. Option \<^verbatim>\<open>-f\<close> forces an existing
+  project directory to be \<^emph>\<open>purged\<close> --- after some sanity checks that it has
+  been generated by @{tool "scala_project"} before.
+\<close>
+
 
-  Option \<^verbatim>\<open>-L\<close> produces \<^emph>\<open>symlinks\<close> to the original files: this allows to
-  develop Isabelle/Scala/jEdit within an external Scala IDE. Note that
-  building the result always requires \<^verbatim>\<open>isabelle jedit -b\<close> on the
-  command-line.
+subsubsection \<open>Examples\<close>
+
+text \<open>
+  Create a project directory and for editing the original sources:
+
+  @{verbatim [display] \<open>isabelle scala_project -f -L\<close>}
+
+  On Windows, this usually requires Administrator rights, in order to create
+  native symlinks.
 \<close>
 
 
@@ -185,13 +326,10 @@
 text \<open>
   A Scala functions of type \<^scala_type>\<open>String => String\<close> may be wrapped as
   \<^scala_type>\<open>isabelle.Scala.Fun\<close> and collected via an instance of the
-  class \<^scala_type>\<open>isabelle.Scala.Functions\<close>. A system component
-  can then register that class via \<^bash_function>\<open>isabelle_scala_service\<close>
-  in \<^path>\<open>etc/settings\<close> (\secref{sec:components}). An example is the
-  predefined collection of \<^scala_type>\<open>isabelle.Scala.Functions\<close> in
-  Isabelle/\<^verbatim>\<open>Pure.jar\<close> with the following line in
-  \<^file>\<open>$ISABELLE_HOME/etc/settings\<close>:
-  @{verbatim [display, indent = 2] \<open>isabelle_scala_service 'isabelle.Functions'\<close>}
+  class \<^scala_type>\<open>isabelle.Scala.Functions\<close>. A system component can then
+  register that class via \<^verbatim>\<open>services\<close> in \<^path>\<open>etc/build.props\<close>
+  (\secref{sec:scala-build}). An example is the predefined collection of
+  \<^scala_type>\<open>isabelle.Scala.Functions\<close> in \<^file>\<open>$ISABELLE_HOME/etc/build.props\<close>.
 
   The overall list of registered functions is accessible in Isabelle/Scala as
   \<^scala_object>\<open>isabelle.Scala.functions\<close>.
--- a/src/HOL/Algebra/Coset.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Algebra/Coset.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1387,7 +1387,7 @@
     moreover
     have "y = f x \<otimes>\<^bsub>H\<^esub> (inv\<^bsub>H\<^esub> f x \<otimes>\<^bsub>H\<^esub> y)"
       using x y
-      by (metis (no_types, hide_lams) assms(5) f group.inv_solve_left group.subgroup_self hom_carrier image_subset_iff subgroup_def that)
+      by (metis (no_types, opaque_lifting) assms(5) f group.inv_solve_left group.subgroup_self hom_carrier image_subset_iff subgroup_def that)
     ultimately
     show ?thesis
       using x y by force
--- a/src/HOL/Algebra/Free_Abelian_Groups.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Algebra/Free_Abelian_Groups.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -242,7 +242,7 @@
 lemma sum_closed_free_Abelian_group:
     "(\<And>i. i \<in> I \<Longrightarrow> x i \<in> carrier (free_Abelian_group S)) \<Longrightarrow> sum x I \<in> carrier (free_Abelian_group S)"
   apply (induction I rule: infinite_finite_induct, auto)
-  by (metis (no_types, hide_lams) UnE subsetCE keys_add)
+  by (metis (no_types, opaque_lifting) UnE subsetCE keys_add)
 
 
 lemma (in comm_group) free_Abelian_group_universal:
--- a/src/HOL/Algebra/Generated_Groups.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Algebra/Generated_Groups.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -572,11 +572,11 @@
 lemma (in group) subgroup_generated2 [simp]: "subgroup_generated (subgroup_generated G S) S = subgroup_generated G S"
 proof -
   have *: "\<And>A. carrier G \<inter> A \<subseteq> carrier (subgroup_generated (subgroup_generated G A) A)"
-    by (metis (no_types, hide_lams) Int_assoc carrier_subgroup_generated generate.incl inf.order_iff subset_iff)
+    by (metis (no_types, opaque_lifting) Int_assoc carrier_subgroup_generated generate.incl inf.order_iff subset_iff)
   show ?thesis
   apply (auto intro!: monoid.equality)
     using group.carrier_subgroup_generated_subset group_subgroup_generated apply blast
-     apply (metis (no_types, hide_lams) "*" group.subgroup_subgroup_generated group_subgroup_generated subgroup_generated_minimal
+     apply (metis (no_types, opaque_lifting) "*" group.subgroup_subgroup_generated group_subgroup_generated subgroup_generated_minimal
         subgroup_generated_restrict subgroup_subgroup_generated_iff subset_eq)
     apply (simp add: subgroup_generated_def)
     done
--- a/src/HOL/Algebra/Group.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Algebra/Group.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1120,7 +1120,7 @@
     have "(\<phi> \<one>) \<otimes>\<^bsub>H\<^esub> \<one>\<^bsub>H\<^esub> = (\<phi> \<one>) \<otimes>\<^bsub>H\<^esub> (\<phi> \<one>)"
       by (metis assms(2) image_eqI monoid.r_one one_closed phi_hom r_one surj(1))
     thus ?thesis
-      by (metis (no_types, hide_lams) Units_eq Units_one_closed assms(2) f_inv_into_f imageI
+      by (metis (no_types, opaque_lifting) Units_eq Units_one_closed assms(2) f_inv_into_f imageI
           monoid.l_one monoid.one_closed phi_hom psi_def r_one surj)
   qed
 
--- a/src/HOL/Algebra/Polynomial_Divisibility.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Algebra/Polynomial_Divisibility.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1176,7 +1176,7 @@
   from \<open>degree p = 1\<close> have "length p = Suc (Suc 0)"
     by simp
   then obtain a b where p: "p = [ a, b ]"
-    by (metis (no_types, hide_lams) Suc_length_conv length_0_conv)
+    by (metis (no_types, opaque_lifting) Suc_length_conv length_0_conv)
   hence "a \<in> K - { \<zero> }" "b \<in> K"  and in_carrier: "a \<in> carrier R" "b \<in> carrier R"
     using assms(2) subfieldE(3)[OF assms(1)] unfolding sym[OF univ_poly_carrier] polynomial_def by auto
   hence inv_a: "inv a \<in> carrier R" "a \<otimes> inv a = \<one>" and "inv a \<in> K"
--- a/src/HOL/Algebra/Product_Groups.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Algebra/Product_Groups.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -468,7 +468,7 @@
             using G H group.subgroup_self hom_one homf injf inv_into_f_eq subgroup.one_closed by fastforce
           with x show "?g \<in> {x \<in> \<Pi>\<^sub>E i\<in>I. carrier (G i). finite {i \<in> I. x i \<noteq> \<one>\<^bsub>G i\<^esub>}}"
             apply (auto simp: PiE_iff inv_into_into conj_commute cong: conj_cong)
-            by (metis (no_types, hide_lams) iso_iff f inv_into_into)
+            by (metis (no_types, opaque_lifting) iso_iff f inv_into_into)
         qed
       qed
     qed
--- a/src/HOL/Algebra/Subrings.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Algebra/Subrings.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -357,7 +357,7 @@
     using k' A(3) subring_props(6) by auto
   thus "a \<in> K"
     using m_assoc[of "inv k" k a] A(2) inv_k subring_props(1)
-    by (metis (no_types, hide_lams) A(1) Diff_iff l_one subsetCE)
+    by (metis (no_types, opaque_lifting) A(1) Diff_iff l_one subsetCE)
 qed
 
 lemma (in ring) subfield_iff:
--- a/src/HOL/Analysis/Abstract_Topology.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Abstract_Topology.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -2117,7 +2117,7 @@
 proof (intro conjI ballI allI impI)
   show "\<And>x'. x' \<in> topspace X' \<Longrightarrow> g x' \<in> topspace X''"
     using assms unfolding quotient_map_def
-    by (metis (no_types, hide_lams) continuous_map_image_subset_topspace image_comp image_subset_iff)
+    by (metis (no_types, opaque_lifting) continuous_map_image_subset_topspace image_comp image_subset_iff)
 next
   fix U'' :: "'c set"
   assume U'': "openin X'' U''"
@@ -3802,7 +3802,7 @@
 
 lemma section_imp_injective_map:
    "\<lbrakk>section_map X Y f; x \<in> topspace X; y \<in> topspace X\<rbrakk> \<Longrightarrow> f x = f y \<longleftrightarrow> x = y"
-  by (metis (mono_tags, hide_lams) retraction_maps_def section_map_def)
+  by (metis (mono_tags, opaque_lifting) retraction_maps_def section_map_def)
 
 lemma retraction_maps_to_retract_maps:
    "retraction_maps X Y r s
--- a/src/HOL/Analysis/Abstract_Topology_2.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Abstract_Topology_2.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1334,7 +1334,7 @@
 lemma homeomorphic_path_connected_space_imp:
      "\<lbrakk>path_connected_space X; X homeomorphic_space Y\<rbrakk> \<Longrightarrow> path_connected_space Y"
   unfolding homeomorphic_space_def homeomorphic_maps_def
-  by (metis (no_types, hide_lams) continuous_map_closedin continuous_map_image_subset_topspace imageI order_class.order.antisym path_connectedin_continuous_map_image path_connectedin_topspace subsetI)
+  by (metis (no_types, opaque_lifting) continuous_map_closedin continuous_map_image_subset_topspace imageI order_class.order.antisym path_connectedin_continuous_map_image path_connectedin_topspace subsetI)
 
 lemma homeomorphic_path_connected_space:
    "X homeomorphic_space Y \<Longrightarrow> path_connected_space X \<longleftrightarrow> path_connected_space Y"
@@ -1351,7 +1351,7 @@
   assume "U \<subseteq> topspace X"
   show "subtopology Y (f ` U) homeomorphic_space subtopology X U"
     using assms unfolding homeomorphic_eq_everything_map
-    by (metis (no_types, hide_lams) assms homeomorphic_map_subtopologies homeomorphic_space homeomorphic_space_sym image_mono inf.absorb_iff2)
+    by (metis (no_types, opaque_lifting) assms homeomorphic_map_subtopologies homeomorphic_space homeomorphic_space_sym image_mono inf.absorb_iff2)
 qed
 
 lemma homeomorphic_map_path_connectedness_eq:
@@ -1525,7 +1525,7 @@
 next
   case False
   then show ?thesis
-    by (metis (no_types, hide_lams) Union_connected_components_of ccpo_Sup_singleton
+    by (metis (no_types, opaque_lifting) Union_connected_components_of ccpo_Sup_singleton
         connected_components_of_eq_empty connected_space_iff_components_eq insertI1 singletonD
         subsetI subset_singleton_iff)
 qed
--- a/src/HOL/Analysis/Arcwise_Connected.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Arcwise_Connected.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1792,7 +1792,7 @@
           by (metis dist_norm dist_triangle_half_r order_less_irrefl)
       qed (auto simp: open_segment_commute)
       show ?thesis
-        unfolding \<phi>_def by (metis (no_types, hide_lams) INT_I Inf_lower2 rangeI that(3) F01 subsetCE pqF)
+        unfolding \<phi>_def by (metis (no_types, opaque_lifting) INT_I Inf_lower2 rangeI that(3) F01 subsetCE pqF)
     qed
     show "closed {0..1::real}" by auto
   qed (meson \<phi>_def)
@@ -1950,7 +1950,7 @@
   then have "arc g"
     by (metis arc_def path_def inj_on_def)
   obtain u v where "u \<in> {0..1}" "a = g u" "v \<in> {0..1}" "b = g v"
-    by (metis (mono_tags, hide_lams) \<open>\<phi> T\<close> \<phi>_def a b fhim gfeq h_eq_p imageI path_image_def pathfinish_def pathfinish_in_path_image pathstart_def pathstart_in_path_image)
+    by (metis (mono_tags, opaque_lifting) \<open>\<phi> T\<close> \<phi>_def a b fhim gfeq h_eq_p imageI path_image_def pathfinish_def pathfinish_in_path_image pathstart_def pathstart_in_path_image)
   then have "a \<in> path_image g" "b \<in> path_image g"
     using path_image_def by blast+
   have ph: "path_image h \<subseteq> path_image p"
@@ -2003,7 +2003,7 @@
   assumes "arc g" "arc h" "pathfinish g = pathstart h" "pathstart g \<noteq> pathfinish h"
   obtains i where "arc i" "path_image i \<subseteq> path_image g \<union> path_image h"
                   "pathstart i = pathstart g" "pathfinish i = pathfinish h"
-  by (metis (no_types, hide_lams) arc_imp_path assms path_contains_arc path_image_join path_join pathfinish_join pathstart_join)
+  by (metis (no_types, opaque_lifting) arc_imp_path assms path_contains_arc path_image_join path_join pathfinish_join pathstart_join)
 
 
 
--- a/src/HOL/Analysis/Bochner_Integration.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Bochner_Integration.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -513,7 +513,7 @@
     by (auto intro!: simple_bochner_integral_eq_nn_integral)
   also have "\<dots> \<le> (\<integral>\<^sup>+x. ennreal (norm (f x - s x)) + ennreal (norm (f x - t x)) \<partial>M)"
     by (auto intro!: nn_integral_mono simp flip: ennreal_plus)
-       (metis (erased, hide_lams) add_diff_cancel_left add_diff_eq diff_add_eq order_trans
+       (metis (erased, opaque_lifting) add_diff_cancel_left add_diff_eq diff_add_eq order_trans
               norm_minus_commute norm_triangle_ineq4 order_refl)
   also have "\<dots> = ?S + ?T"
    by (rule nn_integral_add) auto
--- a/src/HOL/Analysis/Brouwer_Fixpoint.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Brouwer_Fixpoint.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -2054,7 +2054,7 @@
     show "\<And>x. x \<in> frontier (cball a B) \<Longrightarrow> h x = x"
       apply (auto simp: h_def algebra_simps)
       apply (simp add: vector_add_divide_simps  notga)
-      by (metis (no_types, hide_lams) B add.commute dist_commute  dist_norm g_def mem_ball not_less_iff_gr_or_eq  subset_eq)
+      by (metis (no_types, opaque_lifting) B add.commute dist_commute  dist_norm g_def mem_ball not_less_iff_gr_or_eq  subset_eq)
   qed
   ultimately show False by simp
 qed
--- a/src/HOL/Analysis/Cartesian_Space.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Cartesian_Space.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1158,7 +1158,7 @@
   "orthogonal_transformation f \<longleftrightarrow> f(0::'a::real_inner) = (0::'a) \<and> (\<forall>x y. dist(f x) (f y) = dist x y)"
   unfolding orthogonal_transformation
   apply (auto simp: linear_0 isometry_linear)
-   apply (metis (no_types, hide_lams) dist_norm linear_diff)
+   apply (metis (no_types, opaque_lifting) dist_norm linear_diff)
   by (metis dist_0_norm)
 
 
--- a/src/HOL/Analysis/Change_Of_Vars.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Change_Of_Vars.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -198,7 +198,7 @@
               by simp
             have "\<bar>z *\<^sub>R \<bar>prod m UNIV\<bar> - \<bar>prod m UNIV\<bar> * measure lebesgue S\<bar>
                  = \<bar>prod m UNIV\<bar> * \<bar>z - measure lebesgue S\<bar>"
-              by (metis (no_types, hide_lams) abs_abs abs_scaleR mult.commute real_scaleR_def right_diff_distrib')
+              by (metis (no_types, opaque_lifting) abs_abs abs_scaleR mult.commute real_scaleR_def right_diff_distrib')
             also have "\<dots> < e"
               using zless True by (simp add: field_simps)
             finally show "\<bar>z *\<^sub>R \<bar>prod m UNIV\<bar> - \<bar>prod m UNIV\<bar> * measure lebesgue S\<bar> < e" .
@@ -563,7 +563,7 @@
                 by (simp add: bounded_plus [OF bo])
               moreover have "?rfs \<subseteq> ?B"
                 apply (auto simp: dist_norm image_iff dest!: ex_lessK)
-                by (metis (no_types, hide_lams) add.commute diff_add_cancel dist_0_norm dist_commute dist_norm mem_ball)
+                by (metis (no_types, opaque_lifting) add.commute diff_add_cancel dist_0_norm dist_commute dist_norm mem_ball)
               ultimately show "bounded (?rfs)"
                 by (rule bounded_subset)
             qed
@@ -764,7 +764,7 @@
             fix x
             assume "e > 0"  "m < n"  "n * e \<le> \<bar>det (matrix (f' x))\<bar>"  "\<bar>det (matrix (f' x))\<bar> < (1 + real m) * e"
             then have "n < 1 + real m"
-              by (metis (no_types, hide_lams) less_le_trans mult.commute not_le mult_le_cancel_iff2)
+              by (metis (no_types, opaque_lifting) less_le_trans mult.commute not_le mult_le_cancel_iff2)
             then show "False"
               using less.hyps by linarith
           qed
@@ -1402,7 +1402,7 @@
               have *: "\<bar>T (b *\<^sub>R axis k 1) \<bullet> (y - x)\<bar> = b * \<bar>inv T y $ k - ?x' $ k\<bar>" for y
               proof -
                 have "\<bar>T (b *\<^sub>R axis k 1) \<bullet> (y - x)\<bar> = \<bar>(b *\<^sub>R axis k 1) \<bullet> inv T (y - x)\<bar>"
-                  by (metis (no_types, hide_lams) b_def eqb invT orthogonal_transformation_def v)
+                  by (metis (no_types, opaque_lifting) b_def eqb invT orthogonal_transformation_def v)
                 also have "\<dots> = b * \<bar>(axis k 1) \<bullet> inv T (y - x)\<bar>"
                   using \<open>b > 0\<close> by (simp add: abs_mult)
                 also have "\<dots> = b * \<bar>inv T y $ k - ?x' $ k\<bar>"
@@ -1480,7 +1480,7 @@
                                     (\<forall>y\<in>S. norm (y - x) < d \<longrightarrow> norm (f y - f x - A *v (y - x)) \<le> e * norm (y - x))"
                      (is "\<forall>e>0. \<exists>d>0. \<exists>A. ?\<Phi> e d A")
           then have "\<forall>k. \<exists>d>0. \<exists>A. ?\<Phi> (1 / Suc k) d A"
-            by (metis (no_types, hide_lams) less_Suc_eq_0_disj of_nat_0_less_iff zero_less_divide_1_iff)
+            by (metis (no_types, opaque_lifting) less_Suc_eq_0_disj of_nat_0_less_iff zero_less_divide_1_iff)
           then obtain \<delta> A where \<delta>: "\<And>k. \<delta> k > 0"
                            and Ab: "\<And>k. A k $ m $ n < b"
                            and A: "\<And>k y. \<lbrakk>y \<in> S; norm (y - x) < \<delta> k\<rbrakk> \<Longrightarrow>
@@ -1997,7 +1997,7 @@
       proof
         have "T (inv T x - inv T t) = x - t"
           using T linear_diff orthogonal_transformation_def
-          by (metis (no_types, hide_lams) Tinv)
+          by (metis (no_types, opaque_lifting) Tinv)
         then have "norm (inv T x - inv T t) = norm (x - t)"
           by (metis T orthogonal_transformation_norm)
         then show "norm (inv T x - inv T t) \<le> e"
@@ -2180,7 +2180,7 @@
               using r12 by auto
             ultimately have "norm (v - u) \<le> 1"
               using norm_triangle_half_r [of x u 1 v]
-              by (metis (no_types, hide_lams) dist_commute dist_norm less_eq_real_def less_le_trans mem_ball)
+              by (metis (no_types, opaque_lifting) dist_commute dist_norm less_eq_real_def less_le_trans mem_ball)
             then have "norm (v - u) ^ ?n \<le> norm (v - u) ^ ?m"
               by (simp add: power_decreasing [OF mlen])
             also have "\<dots> \<le> ?\<mu> K * real (?m ^ ?m)"
--- a/src/HOL/Analysis/Complex_Transcendental.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Complex_Transcendental.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1146,7 +1146,7 @@
 proof (cases w rule: complex_split_polar)
   case (1 r a) with sin_cos_le1 [of a \<phi>] show ?thesis
     apply (simp add: norm_mult cmod_unit_one)
-    by (metis (no_types, hide_lams) abs_le_D1 distrib_left mult.commute mult.left_commute mult_left_le)
+    by (metis (no_types, opaque_lifting) abs_le_D1 distrib_left mult.commute mult.left_commute mult_left_le)
 qed
 
 subsection\<^marker>\<open>tag unimportant\<close>\<open>Analytic properties of tangent function\<close>
@@ -1333,7 +1333,7 @@
     then have "\<And>y. y \<in> V \<Longrightarrow> g' y = inv ((*) y)"
       by (metis exp_Ln g' g_eq_Ln)
     then have g': "g' z = (\<lambda>x. x/z)"
-      by (metis (no_types, hide_lams) bij \<open>z \<in> V\<close> bij_inv_eq_iff exp_Ln g_eq_Ln nonzero_mult_div_cancel_left znz)
+      by (metis (no_types, opaque_lifting) bij \<open>z \<in> V\<close> bij_inv_eq_iff exp_Ln g_eq_Ln nonzero_mult_div_cancel_left znz)
     show "(g has_derivative (*) (inverse z)) (at z)"
       using g [OF \<open>z \<in> V\<close>] g'
       by (simp add: \<open>z \<in> V\<close> field_class.field_divide_inverse has_derivative_imp_has_field_derivative has_field_derivative_imp_has_derivative)
@@ -4040,7 +4040,7 @@
     also have "... \<longleftrightarrow> (\<exists>z::int. of_nat j = of_nat k + of_nat n * (of_int z :: complex))"
       by simp
     also have "... \<longleftrightarrow> (\<exists>z::int. of_nat j = of_nat k + of_nat n * z)"
-      by (metis (mono_tags, hide_lams) of_int_add of_int_eq_iff of_int_mult of_int_of_nat_eq)
+      by (metis (mono_tags, opaque_lifting) of_int_add of_int_eq_iff of_int_mult of_int_of_nat_eq)
     also have "... \<longleftrightarrow> int j mod int n = int k mod int n"
       by (auto simp: mod_eq_dvd_iff dvd_def algebra_simps)
     also have "... \<longleftrightarrow> j mod n = k mod n"
--- a/src/HOL/Analysis/Connected.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Connected.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -240,7 +240,7 @@
     \<Longrightarrow> connected_component_set S x = connected_component_set S y"
 apply (simp add: ex_in_conv [symmetric])
 apply (rule connected_component_eq)
-by (metis (no_types, hide_lams) connected_component_eq_eq connected_component_in connected_component_maximal subsetD mem_Collect_eq)
+by (metis (no_types, opaque_lifting) connected_component_eq_eq connected_component_in connected_component_maximal subsetD mem_Collect_eq)
 
 
 lemma Union_connected_component: "\<Union>(connected_component_set S ` S) = S"
@@ -335,7 +335,7 @@
   by simp
 
 lemma connected_eq_connected_components_eq: "connected s \<longleftrightarrow> (\<forall>c \<in> components s. \<forall>c' \<in> components s. c = c')"
-  by (metis (no_types, hide_lams) components_iff connected_component_eq_eq connected_iff_connected_component)
+  by (metis (no_types, opaque_lifting) components_iff connected_component_eq_eq connected_iff_connected_component)
 
 lemma components_eq_sing_iff: "components s = {s} \<longleftrightarrow> connected s \<and> s \<noteq> {}"
   apply (rule iffI)
--- a/src/HOL/Analysis/Cross3.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Cross3.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -141,7 +141,7 @@
     using norm_cross [of x y] by (auto simp: power_mult_distrib)
   also have "... \<longleftrightarrow> \<bar>x \<bullet> y\<bar> = norm x * norm y"
     using power2_eq_iff
-    by (metis (mono_tags, hide_lams) abs_minus abs_norm_cancel abs_power2 norm_mult power_abs real_norm_def) 
+    by (metis (mono_tags, opaque_lifting) abs_minus abs_norm_cancel abs_power2 norm_mult power_abs real_norm_def) 
   also have "... \<longleftrightarrow> collinear {0, x, y}"
     by (rule norm_cauchy_schwarz_equal)
   finally show ?thesis .
--- a/src/HOL/Analysis/Derivative.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Derivative.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -3269,7 +3269,7 @@
       apply (rule Limits.continuous_on_scaleR, assumption)
       by (metis (mono_tags, lifting) continuous_at_imp_continuous_on continuous_on_compose continuous_on_cong differentiable_imp_continuous_within o_def)
     show "\<And>x. x \<in> S \<Longrightarrow> vector_derivative f (at x) *\<^sub>R vector_derivative g (at (f x)) = vector_derivative (g \<circ> f) (at x)"
-      by (metis (mono_tags, hide_lams) C1_differentiable_on_eq fg imageI vector_derivative_chain_at)
+      by (metis (mono_tags, opaque_lifting) C1_differentiable_on_eq fg imageI vector_derivative_chain_at)
   qed
   ultimately show ?thesis
     by (simp add: C1_differentiable_on_eq)
--- a/src/HOL/Analysis/Determinants.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Determinants.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -238,7 +238,7 @@
   proof (unfold inj_on_def, auto)
     fix x y assume x: "x permutes ?U" and even_x: "evenperm x"
       and y: "y permutes ?U" and even_y: "evenperm y" and eq: "?t_jk \<circ> x = ?t_jk \<circ> y"
-    show "x = y" by (metis (hide_lams, no_types) comp_assoc eq id_comp swap_id_idempotent)
+    show "x = y" by (metis (opaque_lifting, no_types) comp_assoc eq id_comp swap_id_idempotent)
   qed
   have tjk_permutes: "?t_jk permutes ?U"
     by (auto simp add: permutes_def dest: transpose_eq_imp_eq) (meson transpose_involutory)
@@ -820,7 +820,7 @@
       by simp
     show "f \<circ> (*v) B = id"
       using 1 assms comp_apply eq_id_iff vec.linear_id matrix_id_mat_1 matrix_vector_mul_assoc matrix_works
-      by (metis (no_types, hide_lams))
+      by (metis (no_types, opaque_lifting))
   qed
 next
   fix g
--- a/src/HOL/Analysis/Elementary_Metric_Spaces.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Elementary_Metric_Spaces.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1558,11 +1558,11 @@
 
 lemma bounded_fst: "bounded s \<Longrightarrow> bounded (fst ` s)"
   unfolding bounded_def
-  by (metis (erased, hide_lams) dist_fst_le image_iff order_trans)
+  by (metis (erased, opaque_lifting) dist_fst_le image_iff order_trans)
 
 lemma bounded_snd: "bounded s \<Longrightarrow> bounded (snd ` s)"
   unfolding bounded_def
-  by (metis (no_types, hide_lams) dist_snd_le image_iff order.trans)
+  by (metis (no_types, opaque_lifting) dist_snd_le image_iff order.trans)
 
 instance\<^marker>\<open>tag important\<close> prod :: (heine_borel, heine_borel) heine_borel
 proof
--- a/src/HOL/Analysis/Equivalence_Lebesgue_Henstock_Integration.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Equivalence_Lebesgue_Henstock_Integration.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1298,7 +1298,7 @@
     using assms by (metis euclidean_all_zero_iff inner_zero_right)
   moreover have "c = 1" if "a \<bullet> (x + c *\<^sub>R w) = b" "a \<bullet> (x + w) = b" for c w
     using that
-    by (metis (no_types, hide_lams) add_diff_eq diff_0 diff_minus_eq_add inner_diff_right inner_scaleR_right mult_cancel_right2 right_minus_eq x)
+    by (metis (no_types, opaque_lifting) add_diff_eq diff_0 diff_minus_eq_add inner_diff_right inner_scaleR_right mult_cancel_right2 right_minus_eq x)
   ultimately
   show ?thesis
     using starlike_negligible [OF closed_hyperplane, of x] by simp
@@ -3597,7 +3597,7 @@
       fix t
       assume "\<bar>t\<bar> < B" then show "a $ 1 \<le> t \<and> t \<le> b $ 1"
         using subsetD [OF B]
-        by (metis (mono_tags, hide_lams) mem_ball_0 mem_box_cart(2) norm_real vec_component)
+        by (metis (mono_tags, opaque_lifting) mem_ball_0 mem_box_cart(2) norm_real vec_component)
     qed
     have eq: "(\<lambda>x. if vec x \<in> S then f (vec x) else 0) = (\<lambda>x. if x \<in> S then f x else 0) \<circ> vec"
       by force
@@ -4217,7 +4217,7 @@
           finally show ?thesis .
         qed
         ultimately show ?thesis
-          by (metis (no_types, hide_lams) m_def order_trans power2_eq_square power_even_eq)
+          by (metis (no_types, opaque_lifting) m_def order_trans power2_eq_square power_even_eq)
       next
         case False
         with n N1 have "f x \<le> 2^n"
--- a/src/HOL/Analysis/Equivalence_Measurable_On_Borel.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Equivalence_Measurable_On_Borel.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -349,7 +349,7 @@
             proof (rule pairwise_mono)
               show "negligible (BOX (\<eta> x) x \<inter> BOX (\<eta> y) y)"
                 if "negligible (BOX2 (\<eta> x) x \<inter> BOX2 (\<eta> y) y)" for x y
-                by (metis (no_types, hide_lams) that Int_mono negligible_subset BOX_sub)
+                by (metis (no_types, opaque_lifting) that Int_mono negligible_subset BOX_sub)
             qed auto
 
             have eq: "\<And>box. (\<lambda>D. box (\<eta> (tag D)) (tag D)) ` \<G> = (\<lambda>t. box (\<eta> t) t) ` tag ` \<G>"
--- a/src/HOL/Analysis/Extended_Real_Limits.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Extended_Real_Limits.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -363,7 +363,7 @@
   fixes a::ereal
   shows "(\<Sum>i\<in>I. a) = a * card I"
 apply (cases "finite I", induct set: finite, simp_all)
-apply (cases a, auto, metis (no_types, hide_lams) add.commute mult.commute semiring_normalization_rules(3))
+apply (cases a, auto, metis (no_types, opaque_lifting) add.commute mult.commute semiring_normalization_rules(3))
 done
 
 lemma real_lim_then_eventually_real:
@@ -677,7 +677,7 @@
       then have "1/z \<ge> 0" by auto
       moreover have "1/z < e" using \<open>e>0\<close> \<open>z>1/e\<close>
         apply (cases z) apply auto
-        by (metis (mono_tags, hide_lams) less_ereal.simps(2) less_ereal.simps(4) divide_less_eq ereal_divide_less_pos ereal_less(4)
+        by (metis (mono_tags, opaque_lifting) less_ereal.simps(2) less_ereal.simps(4) divide_less_eq ereal_divide_less_pos ereal_less(4)
             ereal_less_eq(4) less_le_trans mult_eq_0_iff not_le not_one_less_zero times_ereal.simps(1))
       ultimately have "1/z \<ge> 0" "1/z < e" by auto
     }
--- a/src/HOL/Analysis/Fashoda_Theorem.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Fashoda_Theorem.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -118,7 +118,7 @@
     show "(\<lambda>x::real^2. x $ i) ` cbox (- 1) 1 \<subseteq> {-1..1}" for i
       by (auto simp: mem_box_cart)
     show "{-1..1} \<subseteq> (\<lambda>x::real^2. x $ i) ` cbox (- 1) 1" for i
-      by (clarsimp simp: image_iff mem_box_cart Bex_def) (metis (no_types, hide_lams) vec_component)
+      by (clarsimp simp: image_iff mem_box_cart Bex_def) (metis (no_types, opaque_lifting) vec_component)
   qed
   {
     fix x
--- a/src/HOL/Analysis/Finite_Cartesian_Product.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Finite_Cartesian_Product.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -334,13 +334,7 @@
   fix K :: "('a ^ 'b) set set"
   assume "\<forall>S\<in>K. open S" thus "open (\<Union>K)"
     unfolding open_vec_def
-    apply clarify
-    apply (drule (1) bspec)
-    apply (drule (1) bspec)
-    apply clarify
-    apply (rule_tac x=A in exI)
-    apply fast
-    done
+    by (metis Union_iff)
 qed
 
 end
@@ -612,9 +606,7 @@
   by (rule L2_set_mono) (auto simp: assms)
 
 lemma component_le_norm_cart: "\<bar>x$i\<bar> \<le> norm x"
-  apply (simp add: norm_vec_def)
-  apply (rule member_le_L2_set, simp_all)
-  done
+  by (metis norm_nth_le real_norm_def)
 
 lemma norm_bound_component_le_cart: "norm x \<le> e ==> \<bar>x$i\<bar> \<le> e"
   by (metis component_le_norm_cart order_trans)
@@ -626,11 +618,10 @@
   by (simp add: norm_vec_def L2_set_le_sum)
 
 lemma bounded_linear_vec_nth[intro]: "bounded_linear (\<lambda>x. x $ i)"
-apply standard
-apply (rule vector_add_component)
-apply (rule vector_scaleR_component)
-apply (rule_tac x="1" in exI, simp add: norm_nth_le)
-done
+proof
+  show "\<exists>K. \<forall>x. norm (x $ i) \<le> norm x * K"
+    by (metis mult.commute mult.left_neutral norm_nth_le)
+qed auto
 
 instance vec :: (banach, finite) banach ..
 
@@ -681,13 +672,7 @@
 
 lemma inner_axis_axis:
   "inner (axis i x) (axis j y) = (if i = j then inner x y else 0)"
-  unfolding inner_vec_def
-  apply (cases "i = j")
-  apply clarsimp
-  apply (subst sum.remove [of _ j], simp_all)
-  apply (rule sum.neutral, simp add: axis_def)
-  apply (rule sum.neutral, simp add: axis_def)
-  done
+  by (simp add: inner_vec_def axis_def sum.neutral sum.remove [of _ j])
 
 lemma inner_axis: "inner x (axis i y) = inner (x $ i) y"
   by (simp add: inner_vec_def axis_def sum.remove [where x=i])
@@ -987,7 +972,6 @@
 
 lemma linear_vec [simp]: "linear vec"
   using Vector_Spaces_linear_vec
-  apply (auto )
   by unfold_locales (vector algebra_simps)+
 
 subsection \<open>Matrix operations\<close>
@@ -1033,20 +1017,14 @@
 lemma matrix_mul_lid [simp]:
   fixes A :: "'a::semiring_1 ^ 'm ^ 'n"
   shows "mat 1 ** A = A"
-  apply (simp add: matrix_matrix_mult_def mat_def)
-  apply vector
-  apply (auto simp only: if_distrib if_distribR sum.delta'[OF finite]
-    mult_1_left mult_zero_left if_True UNIV_I)
-  done
+  unfolding matrix_matrix_mult_def mat_def
+  by (auto simp: if_distrib if_distribR sum.delta'[OF finite] cong: if_cong)
 
 lemma matrix_mul_rid [simp]:
   fixes A :: "'a::semiring_1 ^ 'm ^ 'n"
   shows "A ** mat 1 = A"
-  apply (simp add: matrix_matrix_mult_def mat_def)
-  apply vector
-  apply (auto simp only: if_distrib if_distribR sum.delta[OF finite]
-    mult_1_right mult_zero_right if_True UNIV_I cong: if_cong)
-  done
+  unfolding matrix_matrix_mult_def mat_def
+  by (auto simp: if_distrib if_distribR sum.delta'[OF finite] cong: if_cong)
 
 proposition matrix_mul_assoc: "A ** (B ** C) = (A ** B) ** C"
   apply (vector matrix_matrix_mult_def sum_distrib_left sum_distrib_right mult.assoc)
@@ -1090,16 +1068,18 @@
 
 lemma matrix_eq:
   fixes A B :: "'a::semiring_1 ^ 'n ^ 'm"
-  shows "A = B \<longleftrightarrow>  (\<forall>x. A *v x = B *v x)" (is "?lhs \<longleftrightarrow> ?rhs")
-  apply auto
-  apply (subst vec_eq_iff)
-  apply clarify
-  apply (clarsimp simp add: matrix_vector_mult_def if_distrib if_distribR vec_eq_iff cong del: if_weak_cong)
-  apply (erule_tac x="axis ia 1" in allE)
-  apply (erule_tac x="i" in allE)
-  apply (auto simp add: if_distrib if_distribR axis_def
-    sum.delta[OF finite] cong del: if_weak_cong)
-  done
+  shows "A = B \<longleftrightarrow> (\<forall>x. A *v x = B *v x)" (is "?lhs \<longleftrightarrow> ?rhs")
+proof
+  assume ?rhs
+  then show ?lhs
+    apply (subst vec_eq_iff)
+    apply (clarsimp simp add: matrix_vector_mult_def if_distrib if_distribR vec_eq_iff cong: if_cong)
+    apply (erule_tac x="axis ia 1" in allE)
+    apply (erule_tac x="i" in allE)
+    apply (auto simp add: if_distrib if_distribR axis_def
+        sum.delta[OF finite] cong del: if_weak_cong)
+    done
+qed auto
 
 lemma matrix_vector_mul_component: "(A *v x)$k = inner (A$k) x"
   by (simp add: matrix_vector_mult_def inner_vec_def)
--- a/src/HOL/Analysis/Function_Metric.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Function_Metric.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -274,7 +274,7 @@
   also have "... \<le> (\<Sum>n. (1/2)^n * min (dist (x (from_nat n)) (z (from_nat n))) 1
                         + (1/2)^n * min (dist (y (from_nat n)) (z (from_nat n))) 1)"
     apply (rule suminf_le)
-    using ineq apply (metis (no_types, hide_lams) add.right_neutral distrib_left
+    using ineq apply (metis (no_types, opaque_lifting) add.right_neutral distrib_left
       le_divide_eq_numeral1(1) mult_2_right mult_left_mono zero_le_one zero_le_power)
     by (auto simp add: summable_add)
   also have "... = (\<Sum>n. (1/2)^n * min (dist (x (from_nat n)) (z (from_nat n))) 1)
--- a/src/HOL/Analysis/Further_Topology.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Further_Topology.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -2040,7 +2040,7 @@
     unfolding image_comp [symmetric] using \<open>U \<subseteq> S\<close> fim
     by (metis homeomorphism_image2 homeomorphism_of_subsets homkh subset_image_iff)
   ultimately show ?thesis
-    by (metis (no_types, hide_lams) homeomorphism_imp_open_map homhk image_comp open_openin subtopology_UNIV)
+    by (metis (no_types, opaque_lifting) homeomorphism_imp_open_map homhk image_comp open_openin subtopology_UNIV)
 qed
 
 lemma inv_of_domain_ss1:
@@ -5483,7 +5483,7 @@
     by (meson contg continuous_on_compose continuous_on_subset homeomorphism_cont1 top_greatest)
   then obtain j where contj: "continuous_on (ball 0 1) j"
                   and j: "\<And>z. z \<in> ball 0 1 \<Longrightarrow> exp(j z) = (g \<circ> h) z"
-    by (metis (mono_tags, hide_lams) continuous_logarithm_on_ball comp_apply non0)
+    by (metis (mono_tags, opaque_lifting) continuous_logarithm_on_ball comp_apply non0)
   have [simp]: "\<And>x. x \<in> S \<Longrightarrow> h (k x) = x"
     using hk homeomorphism_apply2 by blast
   have "\<exists>\<zeta>. continuous_on S \<zeta>\<and> (\<forall>x\<in>S. f x = exp (\<zeta> x))"
--- a/src/HOL/Analysis/Henstock_Kurzweil_Integration.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Henstock_Kurzweil_Integration.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -799,7 +799,7 @@
   assumes "\<And>x. x \<in> s \<Longrightarrow> f x = g x"
   shows "integral s f = integral s g"
   unfolding integral_def
-by (metis (full_types, hide_lams) assms has_integral_cong integrable_eq)
+by (metis (full_types, opaque_lifting) assms has_integral_cong integrable_eq)
 
 lemma integrable_on_cmult_left_iff [simp]:
   assumes "c \<noteq> 0"
@@ -5698,7 +5698,7 @@
   have "norm (?SUM ?p - integral (cbox a b) f) < e"
   proof (rule less_e)
     show "d fine ?p"
-      by (metis (mono_tags, hide_lams) qq fine_Un fine_Union imageE p(2))
+      by (metis (mono_tags, opaque_lifting) qq fine_Un fine_Union imageE p(2))
     note ptag = tagged_partial_division_of_Union_self[OF p(1)]
     have "p \<union> \<Union>(qq ` r) tagged_division_of \<Union>(snd ` p) \<union> \<Union>r"
     proof (rule tagged_division_Un[OF ptag tagged_division_Union [OF \<open>finite r\<close>]])
--- a/src/HOL/Analysis/Homotopy.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Homotopy.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -551,7 +551,7 @@
   then have "path q"
     by (simp add: path_def) (metis q continuous_on_cong)
   have piqs: "path_image q \<subseteq> s"
-    by (metis (no_types, hide_lams) pips f01 image_subset_iff path_image_def q)
+    by (metis (no_types, opaque_lifting) pips f01 image_subset_iff path_image_def q)
   have fb0: "\<And>a b. \<lbrakk>0 \<le> a; a \<le> 1; 0 \<le> b; b \<le> 1\<rbrakk> \<Longrightarrow> 0 \<le> (1 - a) * f b + a * b"
     using f01 by force
   have fb1: "\<lbrakk>0 \<le> a; a \<le> 1; 0 \<le> b; b \<le> 1\<rbrakk> \<Longrightarrow> (1 - a) * f b + a * b \<le> 1" for a b
@@ -1846,7 +1846,7 @@
   have 2: "openin (top_of_set S) ?B"
     by (subst openin_subopen, blast)
   have \<section>: "?A \<inter> ?B = {}"
-    by (clarsimp simp: set_eq_iff) (metis (no_types, hide_lams) Int_iff opD openin_Int)
+    by (clarsimp simp: set_eq_iff) (metis (no_types, opaque_lifting) Int_iff opD openin_Int)
   have *: "S \<subseteq> ?A \<union> ?B"
     by clarsimp (meson opI)
   have "?A = {} \<or> ?B = {}"
@@ -1916,7 +1916,7 @@
   assume ?lhs
   then have "\<And>a. a \<in> S \<Longrightarrow> \<exists>T. openin (top_of_set S) T \<and> a \<in> T \<and> (\<forall>x\<in>T. f x = f a)"
     unfolding locally_def
-    by (metis (mono_tags, hide_lams) constant_on_def constant_on_subset openin_subtopology_self)
+    by (metis (mono_tags, opaque_lifting) constant_on_def constant_on_subset openin_subtopology_self)
   then show ?rhs
     using assms
     by (simp add: locally_constant_imp_constant)
@@ -4519,7 +4519,7 @@
       have "\<not> aff_dim (affine hull S) \<le> 1"
         using \<open>\<not> collinear S\<close> collinear_aff_dim by auto
       then have "\<not> aff_dim (ball x r \<inter> affine hull S) \<le> 1"
-        by (metis (no_types, hide_lams) aff_dim_convex_Int_open IntI open_ball \<open>0 < r\<close> aff_dim_affine_hull affine_affine_hull affine_imp_convex centre_in_ball empty_iff hull_subset inf_commute subsetCE that)
+        by (metis (no_types, opaque_lifting) aff_dim_convex_Int_open IntI open_ball \<open>0 < r\<close> aff_dim_affine_hull affine_affine_hull affine_imp_convex centre_in_ball empty_iff hull_subset inf_commute subsetCE that)
       then have "\<not> collinear (ball x r \<inter> affine hull S)"
         by (simp add: collinear_aff_dim)
       then have *: "path_connected ((ball x r \<inter> affine hull S) - T)"
@@ -5254,7 +5254,7 @@
     and hj:  "\<And>x. j(h x) = x" "\<And>y. h(j y) = y"
     and ranh: "surj h"
     using isomorphisms_UNIV_UNIV
-    by (metis (mono_tags, hide_lams) DIM_real UNIV_eq_I range_eqI)
+    by (metis (mono_tags, opaque_lifting) DIM_real UNIV_eq_I range_eqI)
   obtain f g where hom: "homeomorphism (h ` T) (h ` T) f g"
                and f: "\<And>x. x \<in> h ` K \<Longrightarrow> f x \<in> h ` U"
                and sub: "{x. \<not> (f x = x \<and> g x = x)} \<subseteq> h ` S"
@@ -5275,7 +5275,7 @@
         using hom homeomorphism_def
         by (blast intro: continuous_on_compose cont_hj)+
       show "(j \<circ> f \<circ> h) ` T \<subseteq> T" "(j \<circ> g \<circ> h) ` T \<subseteq> T"
-        by auto (metis (mono_tags, hide_lams) hj(1) hom homeomorphism_def imageE imageI)+
+        by auto (metis (mono_tags, opaque_lifting) hj(1) hom homeomorphism_def imageE imageI)+
       show "\<And>x. x \<in> T \<Longrightarrow> (j \<circ> g \<circ> h) ((j \<circ> f \<circ> h) x) = x"
         using hj hom homeomorphism_apply1 by fastforce
       show "\<And>y. y \<in> T \<Longrightarrow> (j \<circ> f \<circ> h) ((j \<circ> g \<circ> h) y) = y"
--- a/src/HOL/Analysis/Jordan_Curve.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Jordan_Curve.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -582,7 +582,7 @@
     obtain z where zim: "z \<in> ?\<Theta>2" and zout: "z \<in> outside(?\<Theta>1 \<union> ?\<Theta>)"
       apply (auto simp: outside_inside)
       using nonempty_simple_path_endless [OF \<open>simple_path c2\<close>]
-      by (metis (no_types, hide_lams) Diff_Diff_Int Diff_iff c1c2 c2 c2c ex_in_conv pa2_disj_in1)
+      by (metis (no_types, opaque_lifting) Diff_Diff_Int Diff_iff c1c2 c2 c2c ex_in_conv pa2_disj_in1)
     obtain e where "e > 0" and e: "ball z e \<subseteq> outside(?\<Theta>1 \<union> ?\<Theta>)"
       using zout op_out1c open_contains_ball_eq by blast
     have "z \<in> frontier (inside (?\<Theta>2 \<union> ?\<Theta>))"
--- a/src/HOL/Analysis/Line_Segment.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Line_Segment.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -664,7 +664,7 @@
   fixes a :: "'a :: euclidean_space"
   shows "\<lbrakk>ball a r \<subseteq> T; T \<subseteq> cball a r\<rbrakk> \<Longrightarrow> convex T"
 apply (simp add: convex_contains_open_segment, clarify)
-by (metis (no_types, hide_lams) less_le_trans mem_ball mem_cball subsetCE dist_decreases_open_segment)
+by (metis (no_types, opaque_lifting) less_le_trans mem_ball mem_cball subsetCE dist_decreases_open_segment)
 
 lemma csegment_midpoint_subset: "closed_segment (midpoint a b) b \<subseteq> closed_segment a b"
   apply (clarsimp simp: midpoint_def in_segment)
@@ -707,7 +707,7 @@
   fixes a b ::"'a::real_vector"
   assumes  "(u *\<^sub>R b + v *\<^sub>R a) = (u *\<^sub>R a + v *\<^sub>R b)"  "u \<noteq> v"
   shows "a=b"
-  by (metis (no_types, hide_lams) add.commute add_diff_eq diff_add_cancel real_vector.scale_cancel_left real_vector.scale_left_diff_distrib assms)
+  by (metis (no_types, opaque_lifting) add.commute add_diff_eq diff_add_cancel real_vector.scale_cancel_left real_vector.scale_left_diff_distrib assms)
   
 lemma closed_segment_image_interval:
      "closed_segment a b = (\<lambda>u. (1 - u) *\<^sub>R a + u *\<^sub>R b) ` {0..1}"
--- a/src/HOL/Analysis/Linear_Algebra.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Linear_Algebra.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -347,7 +347,7 @@
 lemma\<^marker>\<open>tag unimportant\<close>  orthogonal_transformation_inv:
   "orthogonal_transformation f \<Longrightarrow> orthogonal_transformation (inv f)"
   for f :: "'a::euclidean_space \<Rightarrow> 'a::euclidean_space"
-  by (metis (no_types, hide_lams) bijection.inv_right bijection_def inj_linear_imp_inv_linear orthogonal_transformation orthogonal_transformation_bij orthogonal_transformation_inj)
+  by (metis (no_types, opaque_lifting) bijection.inv_right bijection_def inj_linear_imp_inv_linear orthogonal_transformation orthogonal_transformation_bij orthogonal_transformation_inj)
 
 lemma\<^marker>\<open>tag unimportant\<close>  orthogonal_transformation_norm:
   "orthogonal_transformation f \<Longrightarrow> norm (f x) = norm x"
--- a/src/HOL/Analysis/Path_Connected.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Path_Connected.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -55,7 +55,7 @@
   have g: "g = (\<lambda>x. -a + x) \<circ> ((\<lambda>x. a + x) \<circ> g)"
     by (rule ext) simp
   show ?thesis
-    by (metis (no_types, hide_lams) g continuous_on_compose homeomorphism_def homeomorphism_translation)
+    by (metis (no_types, opaque_lifting) g continuous_on_compose homeomorphism_def homeomorphism_translation)
 qed
 
 lemma path_translation_eq:
@@ -137,6 +137,24 @@
 
 subsection\<^marker>\<open>tag unimportant\<close>\<open>Basic lemmas about paths\<close>
 
+lemma path_of_real: "path complex_of_real" 
+  unfolding path_def by (intro continuous_intros)
+
+lemma path_const: "path (\<lambda>t. a)" for a::"'a::real_normed_vector"
+  unfolding path_def by (intro continuous_intros)
+
+lemma path_minus: "path g \<Longrightarrow> path (\<lambda>t. - g t)" for g::"real\<Rightarrow>'a::real_normed_vector"
+  unfolding path_def by (intro continuous_intros)
+
+lemma path_add: "\<lbrakk>path f; path g\<rbrakk> \<Longrightarrow> path (\<lambda>t. f t + g t)" for f::"real\<Rightarrow>'a::real_normed_vector"
+  unfolding path_def by (intro continuous_intros)
+
+lemma path_diff: "\<lbrakk>path f; path g\<rbrakk> \<Longrightarrow> path (\<lambda>t. f t - g t)" for f::"real\<Rightarrow>'a::real_normed_vector"
+  unfolding path_def by (intro continuous_intros)
+
+lemma path_mult: "\<lbrakk>path f; path g\<rbrakk> \<Longrightarrow> path (\<lambda>t. f t * g t)" for f::"real\<Rightarrow>'a::real_normed_field"
+  unfolding path_def by (intro continuous_intros)
+
 lemma pathin_iff_path_real [simp]: "pathin euclideanreal g \<longleftrightarrow> path g"
   by (simp add: pathin_def path_def)
 
@@ -2720,7 +2738,7 @@
       with b have "\<bar>x \<bullet> b\<bar> = norm x"
         using norm_Basis by (simp add: b)
       with xb show ?thesis
-        by (metis (mono_tags, hide_lams) abs_eq_iff abs_norm_cancel)
+        by (metis (mono_tags, opaque_lifting) abs_eq_iff abs_norm_cancel)
     qed
     with \<open>r > 0\<close> b show "sphere 0 r = {r *\<^sub>R b, - r *\<^sub>R b}"
       by (force simp: sphere_def dist_norm)
@@ -3465,7 +3483,7 @@
     fixes S :: "'a::real_normed_vector set"
     assumes "bounded S"
     shows  "outside(frontier S) \<subseteq> - closure S"
-  unfolding outside_inside Lattices.boolean_algebra_class.compl_le_compl_iff
+  unfolding outside_inside boolean_algebra_class.compl_le_compl_iff
 proof -
   { assume "interior S \<subseteq> inside (frontier S)"
     hence "interior S \<union> inside (frontier S) = inside (frontier S)"
@@ -3602,7 +3620,7 @@
 lemma inside_outside_intersect_connected:
       "\<lbrakk>connected T; inside S \<inter> T \<noteq> {}; outside S \<inter> T \<noteq> {}\<rbrakk> \<Longrightarrow> S \<inter> T \<noteq> {}"
   apply (simp add: inside_def outside_def ex_in_conv [symmetric] disjoint_eq_subset_Compl, clarify)
-  by (metis (no_types, hide_lams) Compl_anti_mono connected_component_eq connected_component_maximal contra_subsetD double_compl)
+  by (metis (no_types, opaque_lifting) Compl_anti_mono connected_component_eq connected_component_maximal contra_subsetD double_compl)
 
 lemma outside_bounded_nonempty:
   fixes S :: "'a :: {real_normed_vector, perfect_space} set"
--- a/src/HOL/Analysis/Polytope.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Polytope.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -2729,7 +2729,7 @@
         using \<open>T \<subseteq> S\<close> by blast
       then have "\<exists>y\<in>S. x \<in> convex hull (S - {y})"
         using True affine_independent_iff_card [of S]
-        by (metis (no_types, hide_lams) Diff_eq_empty_iff Diff_insert0 \<open>a \<notin> T\<close> \<open>T \<subseteq> S\<close> \<open>x \<in> convex hull T\<close> hull_mono insert_Diff_single subsetCE)
+        by (metis (no_types, opaque_lifting) Diff_eq_empty_iff Diff_insert0 \<open>a \<notin> T\<close> \<open>T \<subseteq> S\<close> \<open>x \<in> convex hull T\<close> hull_mono insert_Diff_single subsetCE)
     } note * = this
     have 1: "convex hull S \<subseteq> (\<Union> a\<in>S. convex hull (S - {a}))"
       by (subst caratheodory_aff_dim) (blast dest: *)
@@ -3044,7 +3044,7 @@
   by (simp add: polytope_imp_polyhedron simplex_imp_polytope)
 
 lemma simplex_dim_ge: "n simplex S \<Longrightarrow> -1 \<le> n"
-  by (metis (no_types, hide_lams) aff_dim_geq affine_independent_iff_card diff_add_cancel diff_diff_eq2 simplex_def)
+  by (metis (no_types, opaque_lifting) aff_dim_geq affine_independent_iff_card diff_add_cancel diff_diff_eq2 simplex_def)
 
 lemma simplex_empty [simp]: "n simplex {} \<longleftrightarrow> n = -1"
 proof
--- a/src/HOL/Analysis/Retracts.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Retracts.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -150,7 +150,7 @@
         \<forall>U T. continuous_on T f \<longrightarrow> f ` T \<subseteq> S \<longrightarrow>
                closedin (top_of_set U) T \<longrightarrow>
                 (\<exists>g. continuous_on U g \<and> g ` U \<subseteq> S \<and> (\<forall>x \<in> T. g x = f x)))"
-  by (metis (mono_tags, hide_lams) AR_imp_absolute_extensor absolute_extensor_imp_AR)
+  by (metis (mono_tags, opaque_lifting) AR_imp_absolute_extensor absolute_extensor_imp_AR)
 
 lemma AR_imp_retract:
   fixes S :: "'a::euclidean_space set"
@@ -1445,7 +1445,7 @@
           show "finite ((\<inter>) C ` \<U>)"
             by (simp add: insert.hyps(1))
           show "\<And>Ca. Ca \<in> (\<inter>) C ` \<U> \<Longrightarrow> closed Ca"
-            by (metis (no_types, hide_lams) Suc.prems(2) closed_Int subsetD imageE insert.prems insertI1 insertI2)
+            by (metis (no_types, opaque_lifting) Suc.prems(2) closed_Int subsetD imageE insert.prems insertI1 insertI2)
           show "\<And>Ca. Ca \<in> (\<inter>) C ` \<U> \<Longrightarrow> convex Ca"
             by (metis (mono_tags, lifting) Suc.prems(3) convex_Int imageE insert.prems insert_subset subsetCE)
           show "card ((\<inter>) C ` \<U>) < n"
--- a/src/HOL/Analysis/Starlike.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Starlike.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -1493,16 +1493,7 @@
     and "affine T"
     and "rel_interior S \<inter> T \<noteq> {}"
   shows "closure (S \<inter> T) = closure S \<inter> T"
-proof -
-  have "affine hull T = T"
-    using assms by auto
-  then have "rel_interior T = T"
-    using rel_interior_affine_hull[of T] by metis
-  moreover have "closure T = T"
-    using assms affine_closed[of T] by auto
-  ultimately show ?thesis
-    using convex_closure_inter_two[of S T] assms affine_imp_convex by auto
-qed
+  by (metis affine_imp_convex assms convex_closure_inter_two rel_interior_affine rel_interior_eq_closure)
 
 lemma connected_component_1_gen:
   fixes S :: "'a :: euclidean_space set"
@@ -1523,16 +1514,7 @@
     and "affine T"
     and "rel_interior S \<inter> T \<noteq> {}"
   shows "rel_interior (S \<inter> T) = rel_interior S \<inter> T"
-proof -
-  have "affine hull T = T"
-    using assms by auto
-  then have "rel_interior T = T"
-    using rel_interior_affine_hull[of T] by metis
-  moreover have "closure T = T"
-    using assms affine_closed[of T] by auto
-  ultimately show ?thesis
-    using convex_rel_interior_inter_two[of S T] assms affine_imp_convex by auto
-qed
+  by (simp add: affine_imp_convex assms convex_rel_interior_inter_two rel_interior_affine)
 
 lemma convex_affine_rel_frontier_Int:
    fixes S T :: "'n::euclidean_space set"
@@ -1547,49 +1529,8 @@
 lemma rel_interior_convex_Int_affine:
   fixes S :: "'a::euclidean_space set"
   assumes "convex S" "affine T" "interior S \<inter> T \<noteq> {}"
-    shows "rel_interior(S \<inter> T) = interior S \<inter> T"
-proof -
-  obtain a where aS: "a \<in> interior S" and aT:"a \<in> T"
-    using assms by force
-  have "rel_interior S = interior S"
-    by (metis (no_types) aS affine_hull_nonempty_interior equals0D rel_interior_interior)
-  then show ?thesis
-    by (metis (no_types) affine_imp_convex assms convex_rel_interior_inter_two hull_same rel_interior_affine_hull)
-qed
-
-lemma closure_convex_Int_affine:
-  fixes S :: "'a::euclidean_space set"
-  assumes "convex S" "affine T" "rel_interior S \<inter> T \<noteq> {}"
-  shows "closure(S \<inter> T) = closure S \<inter> T"
-proof
-  have "closure (S \<inter> T) \<subseteq> closure T"
-    by (simp add: closure_mono)
-  also have "... \<subseteq> T"
-    by (simp add: affine_closed assms)
-  finally show "closure(S \<inter> T) \<subseteq> closure S \<inter> T"
-    by (simp add: closure_mono)
-next
-  obtain a where "a \<in> rel_interior S" "a \<in> T"
-    using assms by auto
-  then have ssT: "subspace ((\<lambda>x. (-a)+x) ` T)" and "a \<in> S"
-    using affine_diffs_subspace rel_interior_subset assms by blast+
-  show "closure S \<inter> T \<subseteq> closure (S \<inter> T)"
-  proof
-    fix x  assume "x \<in> closure S \<inter> T"
-    show "x \<in> closure (S \<inter> T)"
-    proof (cases "x = a")
-      case True
-      then show ?thesis
-        using \<open>a \<in> S\<close> \<open>a \<in> T\<close> closure_subset by fastforce
-    next
-      case False
-      then have "x \<in> closure(open_segment a x)"
-        by auto
-      then show ?thesis
-        using \<open>x \<in> closure S \<inter> T\<close> assms convex_affine_closure_Int by blast
-    qed
-  qed
-qed
+  shows "rel_interior(S \<inter> T) = interior S \<inter> T"
+  by (metis Int_emptyI assms convex_affine_rel_interior_Int empty_iff interior_rel_interior_gen)
 
 lemma subset_rel_interior_convex:
   fixes S T :: "'n::euclidean_space set"
@@ -3325,7 +3266,7 @@
   assume ?rhs
   then show ?lhs
     unfolding between_mem_convex_hull
-    by (metis (no_types, hide_lams) collinear_closed_segment collinear_subset hull_redundant hull_subset insert_commute segment_convex_hull)
+    by (metis (no_types, opaque_lifting) collinear_closed_segment collinear_subset hull_redundant hull_subset insert_commute segment_convex_hull)
 qed
 
 
@@ -3404,7 +3345,7 @@
     shows "f ` (open_segment a b) = open_segment (f a) (f b)"
 proof -
   have "f ` (open_segment a b) = f ` (closed_segment a b) - {f a, f b}"
-    by (metis (no_types, hide_lams) empty_subsetI ends_in_segment image_insert image_is_empty inj_on_image_set_diff injf insert_subset open_segment_def segment_open_subset_closed)
+    by (metis (no_types, opaque_lifting) empty_subsetI ends_in_segment image_insert image_is_empty inj_on_image_set_diff injf insert_subset open_segment_def segment_open_subset_closed)
   also have "... = open_segment (f a) (f b)"
     using continuous_injective_image_segment_1 [OF assms]
     by (simp add: open_segment_def inj_on_image_set_diff [OF injf])
@@ -3947,7 +3888,7 @@
     have "K \<subseteq> \<Union>(insert (U \<union> V) (\<D> - {U \<union> V}))"
       using \<open>K \<subseteq> \<Union>\<D>\<close> by auto
     also have "... \<subseteq> (U \<union> V) \<union> (N - J)"
-      by (metis (no_types, hide_lams) Deq Un_subset_iff Un_upper2 J Union_insert order_trans sup_ge1)
+      by (metis (no_types, opaque_lifting) Deq Un_subset_iff Un_upper2 J Union_insert order_trans sup_ge1)
     finally have "J \<inter> K \<subseteq> U \<union> V"
       by blast
     moreover have "connected(J \<inter> K)"
@@ -6366,7 +6307,7 @@
   have "(adjoint f) -` {0} = {0}"
     by (metis \<open>inj (adjoint f)\<close> adjoint_linear assms surj_adjoint_iff_inj ker_orthogonal_comp_adjoint orthogonal_comp_UNIV)
   then have "(range(f))\<^sup>\<bottom> = {0}"
-    by (metis (no_types, hide_lams) adjoint_adjoint adjoint_linear assms ker_orthogonal_comp_adjoint set_zero)
+    by (metis (no_types, opaque_lifting) adjoint_adjoint adjoint_linear assms ker_orthogonal_comp_adjoint set_zero)
   then show "surj f"
     by (metis \<open>inj (adjoint f)\<close> adjoint_adjoint adjoint_linear assms surj_adjoint_iff_inj)
 next
@@ -6387,7 +6328,7 @@
   assume "\<not>inj f"
   then show ?rhs
     using all_zero_iff
-    by (metis (no_types, hide_lams) adjoint_clauses(2) adjoint_linear assms
+    by (metis (no_types, opaque_lifting) adjoint_clauses(2) adjoint_linear assms
         linear_injective_0 linear_injective_imp_surjective linear_surj_adj_imp_inj)
 next
   assume ?rhs
--- a/src/HOL/Analysis/Tagged_Division.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Tagged_Division.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -2359,8 +2359,8 @@
         using \<open>m\<le>n\<close> realff [of _ _ "1+_"] realff [of "1+_"_ "1+_"]
         apply (auto simp: divide_simps add.commute not_le nat_le_iff_add realff)
          apply (simp_all add: power_add)
-        apply (metis (no_types, hide_lams) mult_Suc mult_less_cancel2 not_less_eq mult.assoc)
-        apply (metis (no_types, hide_lams) mult_Suc mult_less_cancel2 not_less_eq mult.assoc)
+        apply (metis (no_types, opaque_lifting) mult_Suc mult_less_cancel2 not_less_eq mult.assoc)
+        apply (metis (no_types, opaque_lifting) mult_Suc mult_less_cancel2 not_less_eq mult.assoc)
         done
       then show "?K0(m,v) \<subseteq> ?K0(n,w) \<or> ?K0(n,w) \<subseteq> ?K0(m,v) \<or> interior(?K0(m,v)) \<inter> interior(?K0(n,w)) = {}"
         by meson
--- a/src/HOL/Analysis/Topology_Euclidean_Space.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Topology_Euclidean_Space.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -2222,7 +2222,7 @@
   then obtain T where "open T" and "x \<in> T" and "T \<subseteq> f ` S"
     by (metis interiorE)
   then show "x \<in> ?rhs"
-    by (metis (no_types, hide_lams) assms subsetD interior_maximal open_bijective_linear_image_eq subset_image_iff)
+    by (metis (no_types, opaque_lifting) assms subsetD interior_maximal open_bijective_linear_image_eq subset_image_iff)
 next
   fix x
   assume x: "x \<in> interior S"
--- a/src/HOL/Analysis/Uniform_Limit.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/Uniform_Limit.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -603,7 +603,7 @@
   then have "\<forall>\<^sub>F x in F. \<forall>y\<in>S. b/2 \<le> norm (f x y)"
     apply (rule eventually_mono)
     using b apply (simp only: dist_norm)
-    by (metis (no_types, hide_lams) diff_zero dist_commute dist_norm norm_triangle_half_l not_less)
+    by (metis (no_types, opaque_lifting) diff_zero dist_commute dist_norm norm_triangle_half_l not_less)
   then have "\<forall>\<^sub>F x in F. \<forall>y\<in>S. b/2 \<le> norm (f x y) \<and> norm (f x y - l y) < e * b\<^sup>2 / 2"
     apply (simp only: ball_conj_distrib dist_norm [symmetric])
     apply (rule eventually_conj, assumption)
--- a/src/HOL/Analysis/measurable.ML	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Analysis/measurable.ML	Tue Aug 17 17:09:20 2021 +0200
@@ -53,8 +53,8 @@
     preprocessors : (string * preprocessor) list }
   val empty: T = {
     measurable_thms = Item_Net.init eq_measurable_thms (single o Thm.prop_of o fst),
-    dest_thms = Thm.full_rules,
-    cong_thms = Thm.full_rules,
+    dest_thms = Thm.item_net,
+    cong_thms = Thm.item_net,
     preprocessors = [] };
   val extend = I;
   fun merge ({measurable_thms = t1, dest_thms = dt1, cong_thms = ct1, preprocessors = i1 },
--- a/src/HOL/Auth/Message.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Auth/Message.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -214,7 +214,7 @@
 lemma parts_image [simp]:
   "parts (f ` A) = (\<Union>x\<in>A. parts {f x})"
   apply auto
-  apply (metis (mono_tags, hide_lams) image_iff parts_singleton)
+  apply (metis (mono_tags, opaque_lifting) image_iff parts_singleton)
   apply (metis empty_subsetI image_eqI insert_absorb insert_subset parts_mono)
   done
 
--- a/src/HOL/Binomial.thy	Wed Jul 07 15:40:00 2021 +0200
+++ b/src/HOL/Binomial.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -933,7 +933,7 @@
   have "?lhs = (\<Sum>k\<le>m. (- a gchoose k) * (- x) ^ k * (x + y) ^ (m - k))"
     by (simp add: gbinomial_partial_sum_poly)
   also have "... = (\<Sum>k\<le>m. (-1) ^ k * (of_nat k - - a - 1 gchoose k) * (- x) ^ k * (x + y) ^ (m - k))"
-    by (metis (no_types, hide_lams) gbinomial_negated_upper)
+    by (metis (no_types, opaque_lifting) gbinomial_negated_upper)
   also have "... = ?rhs"
     by (intro sum.cong) (auto simp flip: power_mult_distrib)
   finally show ?thesis .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Bit_Operations.thy	Tue Aug 17 17:09:20 2021 +0200
@@ -0,0 +1,3580 @@
+(*  Author:  Florian Haftmann, TUM
+*)
+
+section \<open>Bit operations in suitable algebraic structures\<close>
+
+theory Bit_Operations
+  imports Presburger Groups_List
+begin
+
+subsection \<open>Abstract bit structures\<close>
+
+class semiring_bits = semiring_parity +
+  assumes bits_induct [case_names stable rec]:
+    \<open>(\<And>a. a div 2 = a \<Longrightarrow> P a)
+     \<Longrightarrow> (\<And>a b. P a \<Longrightarrow> (of_bool b + 2 * a) div 2 = a \<Longrightarrow> P (of_bool b + 2 * a))
+        \<Longrightarrow> P a\<close>
+  assumes bits_div_0 [simp]: \<open>0 div a = 0\<close>
+    and bits_div_by_1 [simp]: \<open>a div 1 = a\<close>
+    and bits_mod_div_trivial [simp]: \<open>a mod b div b = 0\<close>
+    and even_succ_div_2 [simp]: \<open>even a \<Longrightarrow> (1 + a) div 2 = a div 2\<close>
+    and even_mask_div_iff: \<open>even ((2 ^ m - 1) div 2 ^ n) \<longleftrightarrow> 2 ^ n = 0 \<or> m \<le> n\<close>
+    and exp_div_exp_eq: \<open>2 ^ m div 2 ^ n = of_bool (2 ^ m \<noteq> 0 \<and> m \<ge> n) * 2 ^ (m - n)\<close>
+    and div_exp_eq: \<open>a div 2 ^ m div 2 ^ n = a div 2 ^ (m + n)\<close>
+    and mod_exp_eq: \<open>a mod 2 ^ m mod 2 ^ n = a mod 2 ^ min m n\<close>
+    and mult_exp_mod_exp_eq: \<open>m \<le> n \<Longrightarrow> (a * 2 ^ m) mod (2 ^ n) = (a mod 2 ^ (n - m)) * 2 ^ m\<close>
+    and div_exp_mod_exp_eq: \<open>a div 2 ^ n mod 2 ^ m = a mod (2 ^ (n + m)) div 2 ^ n\<close>
+    and even_mult_exp_div_exp_iff: \<open>even (a * 2 ^ m div 2 ^ n) \<longleftrightarrow> m > n \<or> 2 ^ n = 0 \<or> (m \<le> n \<and> even (a div 2 ^ (n - m)))\<close>
+  fixes bit :: \<open>'a \<Rightarrow> nat \<Rightarrow> bool\<close>
+  assumes bit_iff_odd: \<open>bit a n \<longleftrightarrow> odd (a div 2 ^ n)\<close>
+begin
+
+text \<open>
+  Having \<^const>\<open>bit\<close> as definitional class operation
+  takes into account that specific instances can be implemented
+  differently wrt. code generation.
+\<close>
+
+lemma bits_div_by_0 [simp]:
+  \<open>a div 0 = 0\<close>
+  by (metis add_cancel_right_right bits_mod_div_trivial mod_mult_div_eq mult_not_zero)
+
+lemma bits_1_div_2 [simp]:
+  \<open>1 div 2 = 0\<close>
+  using even_succ_div_2 [of 0] by simp
+
+lemma bits_1_div_exp [simp]:
+  \<open>1 div 2 ^ n = of_bool (n = 0)\<close>
+  using div_exp_eq [of 1 1] by (cases n) simp_all
+
+lemma even_succ_div_exp [simp]:
+  \<open>(1 + a) div 2 ^ n = a div 2 ^ n\<close> if \<open>even a\<close> and \<open>n > 0\<close>
+proof (cases n)
+  case 0
+  with that show ?thesis
+    by simp
+next
+  case (Suc n)
+  with \<open>even a\<close> have \<open>(1 + a) div 2 ^ Suc n = a div 2 ^ Suc n\<close>
+  proof (induction n)
+    case 0
+    then show ?case
+      by simp
+  next
+    case (Suc n)
+    then show ?case
+      using div_exp_eq [of _ 1 \<open>Suc n\<close>, symmetric]
+      by simp
+  qed
+  with Suc show ?thesis
+    by simp
+qed
+
+lemma even_succ_mod_exp [simp]:
+  \<open>(1 + a) mod 2 ^ n = 1 + (a mod 2 ^ n)\<close> if \<open>even a\<close> and \<open>n > 0\<close>
+  using div_mult_mod_eq [of \<open>1 + a\<close> \<open>2 ^ n\<close>] that
+  apply simp
+  by (metis local.add.left_commute local.add_left_cancel local.div_mult_mod_eq)
+
+lemma bits_mod_by_1 [simp]:
+  \<open>a mod 1 = 0\<close>
+  using div_mult_mod_eq [of a 1] by simp
+
+lemma bits_mod_0 [simp]:
+  \<open>0 mod a = 0\<close>
+  using div_mult_mod_eq [of 0 a] by simp
+
+lemma bits_one_mod_two_eq_one [simp]:
+  \<open>1 mod 2 = 1\<close>
+  by (simp add: mod2_eq_if)
+
+lemma bit_0 [simp]:
+  \<open>bit a 0 \<longleftrightarrow> odd a\<close>
+  by (simp add: bit_iff_odd)
+
+lemma bit_Suc:
+  \<open>bit a (Suc n) \<longleftrightarrow> bit (a div 2) n\<close>
+  using div_exp_eq [of a 1 n] by (simp add: bit_iff_odd)
+
+lemma bit_rec:
+  \<open>bit a n \<longleftrightarrow> (if n = 0 then odd a else bit (a div 2) (n - 1))\<close>
+  by (cases n) (simp_all add: bit_Suc)
+
+lemma bit_0_eq [simp]:
+  \<open>bit 0 = bot\<close>
+  by (simp add: fun_eq_iff bit_iff_odd)
+
+context
+  fixes a
+  assumes stable: \<open>a div 2 = a\<close>
+begin
+
+lemma bits_stable_imp_add_self:
+  \<open>a + a mod 2 = 0\<close>
+proof -
+  have \<open>a div 2 * 2 + a mod 2 = a\<close>
+    by (fact div_mult_mod_eq)
+  then have \<open>a * 2 + a mod 2 = a\<close>
+    by (simp add: stable)
+  then show ?thesis
+    by (simp add: mult_2_right ac_simps)
+qed
+
+lemma stable_imp_bit_iff_odd:
+  \<open>bit a n \<longleftrightarrow> odd a\<close>
+  by (induction n) (simp_all add: stable bit_Suc)
+
+end
+
+lemma bit_iff_idd_imp_stable:
+  \<open>a div 2 = a\<close> if \<open>\<And>n. bit a n \<longleftrightarrow> odd a\<close>
+using that proof (induction a rule: bits_induct)
+  case (stable a)
+  then show ?case
+    by simp
+next
+  case (rec a b)
+  from rec.prems [of 1] have [simp]: \<open>b = odd a\<close>
+    by (simp add: rec.hyps bit_Suc)
+  from rec.hyps have hyp: \<open>(of_bool (odd a) + 2 * a) div 2 = a\<close>
+    by simp
+  have \<open>bit a n \<longleftrightarrow> odd a\<close> for n
+    using rec.prems [of \<open>Suc n\<close>] by (simp add: hyp bit_Suc)
+  then have \<open>a div 2 = a\<close>
+    by (rule rec.IH)
+  then have \<open>of_bool (odd a) + 2 * a = 2 * (a div 2) + of_bool (odd a)\<close>
+    by (simp add: ac_simps)
+  also have \<open>\<dots> = a\<close>
+    using mult_div_mod_eq [of 2 a]
+    by (simp add: of_bool_odd_eq_mod_2)
+  finally show ?case
+    using \<open>a div 2 = a\<close> by (simp add: hyp)
+qed
+
+lemma exp_eq_0_imp_not_bit:
+  \<open>\<not> bit a n\<close> if \<open>2 ^ n = 0\<close>
+  using that by (simp add: bit_iff_odd)
+
+lemma bit_eqI:
+  \<open>a = b\<close> if \<open>\<And>n. 2 ^ n \<noteq> 0 \<Longrightarrow> bit a n \<longleftrightarrow> bit b n\<close>
+proof -
+  have \<open>bit a n \<longleftrightarrow> bit b n\<close> for n
+  proof (cases \<open>2 ^ n = 0\<close>)
+    case True
+    then show ?thesis
+      by (simp add: exp_eq_0_imp_not_bit)
+  next
+    case False
+    then show ?thesis
+      by (rule that)
+  qed
+  then show ?thesis proof (induction a arbitrary: b rule: bits_induct)
+    case (stable a)
+    from stable(2) [of 0] have **: \<open>even b \<longleftrightarrow> even a\<close>
+      by simp
+    have \<open>b div 2 = b\<close>
+    proof (rule bit_iff_idd_imp_stable)
+      fix n
+      from stable have *: \<open>bit b n \<longleftrightarrow> bit a n\<close>
+        by simp
+      also have \<open>bit a n \<longleftrightarrow> odd a\<close>
+        using stable by (simp add: stable_imp_bit_iff_odd)
+      finally show \<open>bit b n \<longleftrightarrow> odd b\<close>
+        by (simp add: **)
+    qed
+    from ** have \<open>a mod 2 = b mod 2\<close>
+      by (simp add: mod2_eq_if)
+    then have \<open>a mod 2 + (a + b) = b mod 2 + (a + b)\<close>
+      by simp
+    then have \<open>a + a mod 2 + b = b + b mod 2 + a\<close>
+      by (simp add: ac_simps)
+    with \<open>a div 2 = a\<close> \<open>b div 2 = b\<close> show ?case
+      by (simp add: bits_stable_imp_add_self)
+  next
+    case (rec a p)
+    from rec.prems [of 0] have [simp]: \<open>p = odd b\<close>
+      by simp
+    from rec.hyps have \<open>bit a n \<longleftrightarrow> bit (b div 2) n\<close> for n
+      using rec.prems [of \<open>Suc n\<close>] by (simp add: bit_Suc)
+    then have \<open>a = b div 2\<close>
+      by (rule rec.IH)
+    then have \<open>2 * a = 2 * (b div 2)\<close>
+      by simp
+    then have \<open>b mod 2 + 2 * a = b mod 2 + 2 * (b div 2)\<close>
+      by simp
+    also have \<open>\<dots> = b\<close>
+      by (fact mod_mult_div_eq)
+    finally show ?case
+      by (auto simp add: mod2_eq_if)
+  qed
+qed
+
+lemma bit_eq_iff:
+  \<open>a = b \<longleftrightarrow> (\<forall>n. bit a n \<longleftrightarrow> bit b n)\<close>
+  by (auto intro: bit_eqI)
+
+named_theorems bit_simps \<open>Simplification rules for \<^const>\<open>bit\<close>\<close>
+
+lemma bit_exp_iff [bit_simps]:
+  \<open>bit (2 ^ m) n \<longleftrightarrow> 2 ^ m \<noteq> 0 \<and> m = n\<close>
+  by (auto simp add: bit_iff_odd exp_div_exp_eq)
+
+lemma bit_1_iff [bit_simps]:
+  \<open>bit 1 n \<longleftrightarrow> 1 \<noteq> 0 \<and> n = 0\<close>
+  using bit_exp_iff [of 0 n] by simp
+
+lemma bit_2_iff [bit_simps]:
+  \<open>bit 2 n \<longleftrightarrow> 2 \<noteq> 0 \<and> n = 1\<close>
+  using bit_exp_iff [of 1 n] by auto
+
+lemma even_bit_succ_iff:
+  \<open>bit (1 + a) n \<longleftrightarrow> bit a n \<or> n = 0\<close> if \<open>even a\<close>
+  using that by (cases \<open>n = 0\<close>) (simp_all add: bit_iff_odd)
+
+lemma odd_bit_iff_bit_pred:
+  \<open>bit a n \<longleftrightarrow> bit (a - 1) n \<or> n = 0\<close> if \<open>odd a\<close>
+proof -
+  from \<open>odd a\<close> obtain b where \<open>a = 2 * b + 1\<close> ..
+  moreover have \<open>bit (2 * b) n \<or> n = 0 \<longleftrightarrow> bit (1 + 2 * b) n\<close>
+    using even_bit_succ_iff by simp
+  ultimately show ?thesis by (simp add: ac_simps)
+qed
+
+lemma bit_double_iff [bit_simps]:
+  \<open>bit (2 * a) n \<longleftrightarrow> bit a (n - 1) \<and> n \<noteq> 0 \<and> 2 ^ n \<noteq> 0\<close>
+  using even_mult_exp_div_exp_iff [of a 1 n]
+  by (cases n, auto simp add: bit_iff_odd ac_simps)
+
+lemma bit_eq_rec:
+  \<open>a = b \<longleftrightarrow> (even a \<longleftrightarrow> even b) \<and> a div 2 = b div 2\<close> (is \<open>?P = ?Q\<close>)
+proof
+  assume ?P
+  then show ?Q
+    by simp
+next
+  assume ?Q
+  then have \<open>even a \<longleftrightarrow> even b\<close> and \<open>a div 2 = b div 2\<close>
+    by simp_all
+  show ?P
+  proof (rule bit_eqI)
+    fix n
+    show \<open>bit a n \<longleftrightarrow> bit b n\<close>
+    proof (cases n)
+      case 0
+      with \<open>even a \<longleftrightarrow> even b\<close> show ?thesis
+        by simp
+    next
+      case (Suc n)
+      moreover from \<open>a div 2 = b div 2\<close> have \<open>bit (a div 2) n = bit (b div 2) n\<close>
+        by simp
+      ultimately show ?thesis
+        by (simp add: bit_Suc)
+    qed
+  qed
+qed
+
+lemma bit_mod_2_iff [simp]:
+  \<open>bit (a mod 2) n \<longleftrightarrow> n = 0 \<and> odd a\<close>
+  by (cases a rule: parity_cases) (simp_all add: bit_iff_odd)
+
+lemma bit_mask_iff:
+  \<open>bit (2 ^ m - 1) n \<longleftrightarrow> 2 ^ n \<noteq> 0 \<and> n < m\<close>
+  by (simp add: bit_iff_odd even_mask_div_iff not_le)
+
+lemma bit_Numeral1_iff [simp]:
+  \<open>bit (numeral Num.One) n \<longleftrightarrow> n = 0\<close>
+  by (simp add: bit_rec)
+
+lemma exp_add_not_zero_imp:
+  \<open>2 ^ m \<noteq> 0\<close> and \<open>2 ^ n \<noteq> 0\<close> if \<open>2 ^ (m + n) \<noteq> 0\<close>
+proof -
+  have \<open>\<not> (2 ^ m = 0 \<or> 2 ^ n = 0)\<close>
+  proof (rule notI)
+    assume \<open>2 ^ m = 0 \<or> 2 ^ n = 0\<close>
+    then have \<open>2 ^ (m + n) = 0\<close>
+      by (rule disjE) (simp_all add: power_add)
+    with that show False ..
+  qed
+  then show \<open>2 ^ m \<noteq> 0\<close> and \<open>2 ^ n \<noteq> 0\<close>
+    by simp_all
+qed
+
+lemma bit_disjunctive_add_iff:
+  \<open>bit (a + b) n \<longleftrightarrow> bit a n \<or> bit b n\<close>
+  if \<open>\<And>n. \<not> bit a n \<or> \<not> bit b n\<close>
+proof (cases \<open>2 ^ n = 0\<close>)
+  case True
+  then show ?thesis
+    by (simp add: exp_eq_0_imp_not_bit)
+next
+  case False
+  with that show ?thesis proof (induction n arbitrary: a b)
+    case 0
+    from "0.prems"(1) [of 0] show ?case
+      by auto
+  next
+    case (Suc n)
+    from Suc.prems(1) [of 0] have even: \<open>even a \<or> even b\<close>
+      by auto
+    have bit: \<open>\<not> bit (a div 2) n \<or> \<not> bit (b div 2) n\<close> for n
+      using Suc.prems(1) [of \<open>Suc n\<close>] by (simp add: bit_Suc)
+    from Suc.prems(2) have \<open>2 * 2 ^ n \<noteq> 0\<close> \<open>2 ^ n \<noteq> 0\<close>
+      by (auto simp add: mult_2)
+    have \<open>a + b = (a div 2 * 2 + a mod 2) + (b div 2 * 2 + b mod 2)\<close>
+      using div_mult_mod_eq [of a 2] div_mult_mod_eq [of b 2] by simp
+    also have \<open>\<dots> = of_bool (odd a \<or> odd b) + 2 * (a div 2 + b div 2)\<close>
+      using even by (auto simp add: algebra_simps mod2_eq_if)
+    finally have \<open>bit ((a + b) div 2) n \<longleftrightarrow> bit (a div 2 + b div 2) n\<close>
+      using \<open>2 * 2 ^ n \<noteq> 0\<close> by simp (simp_all flip: bit_Suc add: bit_double_iff)
+    also have \<open>\<dots> \<longleftrightarrow> bit (a div 2) n \<or> bit (b div 2) n\<close>
+      using bit \<open>2 ^ n \<noteq> 0\<close> by (rule Suc.IH)
+    finally show ?case
+      by (simp add: bit_Suc)
+  qed
+qed
+
+lemma
+  exp_add_not_zero_imp_left: \<open>2 ^ m \<noteq> 0\<close>
+  and exp_add_not_zero_imp_right: \<open>2 ^ n \<noteq> 0\<close>
+  if \<open>2 ^ (m + n) \<noteq> 0\<close>
+proof -
+  have \<open>\<not> (2 ^ m = 0 \<or> 2 ^ n = 0)\<close>
+  proof (rule notI)
+    assume \<open>2 ^ m = 0 \<or> 2 ^ n = 0\<close>
+    then have \<open>2 ^ (m + n) = 0\<close>
+      by (rule disjE) (simp_all add: power_add)
+    with that show False ..
+  qed
+  then show \<open>2 ^ m \<noteq> 0\<close> and \<open>2 ^ n \<noteq> 0\<close>
+    by simp_all
+qed
+
+lemma exp_not_zero_imp_exp_diff_not_zero:
+  \<open>2 ^ (n - m) \<noteq> 0\<close> if \<open>2 ^ n \<noteq> 0\<close>
+proof (cases \<open>m \<le> n\<close>)
+  case True
+  moreover define q where \<open>q = n - m\<close>
+  ultimately have \<open>n = m + q\<close>
+    by simp
+  with that show ?thesis
+    by (simp add: exp_add_not_zero_imp_right)
+next
+  case False
+  with that show ?thesis
+    by simp
+qed
+
+end
+
+lemma nat_bit_induct [case_names zero even odd]:
+  "P n" if zero: "P 0"
+    and even: "\<And>n. P n \<Longrightarrow> n > 0 \<Longrightarrow> P (2 * n)"
+    and odd: "\<And>n. P n \<Longrightarrow> P (Suc (2 * n))"
+proof (induction n rule: less_induct)
+  case (less n)
+  show "P n"
+  proof (cases "n = 0")
+    case True with zero show ?thesis by simp
+  next
+    case False
+    with less have hyp: "P (n div 2)" by simp
+    show ?thesis
+    proof (cases "even n")
+      case True
+      then have "n \<noteq> 1"
+        by auto
+      with \<open>n \<noteq> 0\<close> have "n div 2 > 0"
+        by simp
+      with \<open>even n\<close> hyp even [of "n div 2"] show ?thesis
+        by simp
+    next
+      case False
+      with hyp odd [of "n div 2"] show ?thesis
+        by simp
+    qed
+  qed
+qed
+
+instantiation nat :: semiring_bits
+begin
+
+definition bit_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> bool\<close>
+  where \<open>bit_nat m n \<longleftrightarrow> odd (m div 2 ^ n)\<close>
+
+instance
+proof
+  show \<open>P n\<close> if stable: \<open>\<And>n. n div 2 = n \<Longrightarrow> P n\<close>
+    and rec: \<open>\<And>n b. P n \<Longrightarrow> (of_bool b + 2 * n) div 2 = n \<Longrightarrow> P (of_bool b + 2 * n)\<close>
+    for P and n :: nat
+  proof (induction n rule: nat_bit_induct)
+    case zero
+    from stable [of 0] show ?case
+      by simp
+  next
+    case (even n)
+    with rec [of n False] show ?case
+      by simp
+  next
+    case (odd n)
+    with rec [of n True] show ?case
+      by simp
+  qed
+  show \<open>q mod 2 ^ m mod 2 ^ n = q mod 2 ^ min m n\<close>
+    for q m n :: nat
+    apply (auto simp add: less_iff_Suc_add power_add mod_mod_cancel split: split_min_lin)
+    apply (metis div_mult2_eq mod_div_trivial mod_eq_self_iff_div_eq_0 mod_mult_self2_is_0 power_commutes)
+    done
+  show \<open>(q * 2 ^ m) mod (2 ^ n) = (q mod 2 ^ (n - m)) * 2 ^ m\<close> if \<open>m \<le> n\<close>
+    for q m n :: nat
+    using that
+    apply (auto simp add: mod_mod_cancel div_mult2_eq power_add mod_mult2_eq le_iff_add split: split_min_lin)
+    done
+  show \<open>even ((2 ^ m - (1::nat)) div 2 ^ n) \<longleftrightarrow> 2 ^ n = (0::nat) \<or> m \<le> n\<close>
+    for m n :: nat
+    using even_mask_div_iff' [where ?'a = nat, of m n] by simp
+  show \<open>even (q * 2 ^ m div 2 ^ n) \<longleftrightarrow> n < m \<or> (2::nat) ^ n = 0 \<or> m \<le> n \<and> even (q div 2 ^ (n - m))\<close>
+    for m n q r :: nat
+    apply (auto simp add: not_less power_add ac_simps dest!: le_Suc_ex)
+    apply (metis (full_types) dvd_mult dvd_mult_imp_div dvd_power_iff_le not_less not_less_eq order_refl power_Suc)
+    done
+qed (auto simp add: div_mult2_eq mod_mult2_eq power_add power_diff bit_nat_def)
+
+end
+
+lemma int_bit_induct [case_names zero minus even odd]:
+  "P k" if zero_int: "P 0"
+    and minus_int: "P (- 1)"
+    and even_int: "\<And>k. P k \<Longrightarrow> k \<noteq> 0 \<Longrightarrow> P (k * 2)"
+    and odd_int: "\<And>k. P k \<Longrightarrow> k \<noteq> - 1 \<Longrightarrow> P (1 + (k * 2))" for k :: int
+proof (cases "k \<ge> 0")
+  case True
+  define n where "n = nat k"
+  with True have "k = int n"
+    by simp
+  then show "P k"
+  proof (induction n arbitrary: k rule: nat_bit_induct)
+    case zero
+    then show ?case
+      by (simp add: zero_int)
+  next
+    case (even n)
+    have "P (int n * 2)"
+      by (rule even_int) (use even in simp_all)
+    with even show ?case
+      by (simp add: ac_simps)
+  next
+    case (odd n)
+    have "P (1 + (int n * 2))"
+      by (rule odd_int) (use odd in simp_all)
+    with odd show ?case
+      by (simp add: ac_simps)
+  qed
+next
+  case False
+  define n where "n = nat (- k - 1)"
+  with False have "k = - int n - 1"
+    by simp
+  then show "P k"
+  proof (induction n arbitrary: k rule: nat_bit_induct)
+    case zero
+    then show ?case
+      by (simp add: minus_int)
+  next
+    case (even n)
+    have "P (1 + (- int (Suc n) * 2))"
+      by (rule odd_int) (use even in \<open>simp_all add: algebra_simps\<close>)
+    also have "\<dots> = - int (2 * n) - 1"
+      by (simp add: algebra_simps)
+    finally show ?case
+      using even.prems by simp
+  next
+    case (odd n)
+    have "P (- int (Suc n) * 2)"
+      by (rule even_int) (use odd in \<open>simp_all add: algebra_simps\<close>)
+    also have "\<dots> = - int (Suc (2 * n)) - 1"
+      by (simp add: algebra_simps)
+    finally show ?case
+      using odd.prems by simp
+  qed
+qed
+
+context semiring_bits
+begin
+
+lemma bit_of_bool_iff [bit_simps]:
+  \<open>bit (of_bool b) n \<longleftrightarrow> b \<and> n = 0\<close>
+  by (simp add: bit_1_iff)
+
+lemma even_of_nat_iff:
+  \<open>even (of_nat n) \<longleftrightarrow> even n\<close>
+  by (induction n rule: nat_bit_induct) simp_all
+
+lemma bit_of_nat_iff [bit_simps]:
+  \<open>bit (of_nat m) n \<longleftrightarrow> (2::'a) ^ n \<noteq> 0 \<and> bit m n\<close>
+proof (cases \<open>(2::'a) ^ n = 0\<close>)
+  case True
+  then show ?thesis
+    by (simp add: exp_eq_0_imp_not_bit)
+next
+  case False
+  then have \<open>bit (of_nat m) n \<longleftrightarrow> bit m n\<close>
+  proof (induction m arbitrary: n rule: nat_bit_induct)
+    case zero
+    then show ?case
+      by simp
+  next
+    case (even m)
+    then show ?case
+      by (cases n)
+        (auto simp add: bit_double_iff Bit_Operations.bit_double_iff dest: mult_not_zero)
+  next
+    case (odd m)
+    then show ?case
+      by (cases n)
+         (auto simp add: bit_double_iff even_bit_succ_iff Bit_Operations.bit_Suc dest: mult_not_zero)
+  qed
+  with False show ?thesis
+    by simp
+qed
+
+end
+
+instantiation int :: semiring_bits
+begin
+
+definition bit_int :: \<open>int \<Rightarrow> nat \<Rightarrow> bool\<close>
+  where \<open>bit_int k n \<longleftrightarrow> odd (k div 2 ^ n)\<close>
+
+instance
+proof
+  show \<open>P k\<close> if stable: \<open>\<And>k. k div 2 = k \<Longrightarrow> P k\<close>
+    and rec: \<open>\<And>k b. P k \<Longrightarrow> (of_bool b + 2 * k) div 2 = k \<Longrightarrow> P (of_bool b + 2 * k)\<close>
+    for P and k :: int
+  proof (induction k rule: int_bit_induct)
+    case zero
+    from stable [of 0] show ?case
+      by simp
+  next
+    case minus
+    from stable [of \<open>- 1\<close>] show ?case
+      by simp
+  next
+    case (even k)
+    with rec [of k False] show ?case
+      by (simp add: ac_simps)
+  next
+    case (odd k)
+    with rec [of k True] show ?case
+      by (simp add: ac_simps)
+  qed
+  show \<open>(2::int) ^ m div 2 ^ n = of_bool ((2::int) ^ m \<noteq> 0 \<and> n \<le> m) * 2 ^ (m - n)\<close>
+    for m n :: nat
+  proof (cases \<open>m < n\<close>)
+    case True
+    then have \<open>n = m + (n - m)\<close>
+      by simp
+    then have \<open>(2::int) ^ m div 2 ^ n = (2::int) ^ m div 2 ^ (m + (n - m))\<close>
+      by simp
+    also have \<open>\<dots> = (2::int) ^ m div (2 ^ m * 2 ^ (n - m))\<close>
+      by (simp add: power_add)
+    also have \<open>\<dots> = (2::int) ^ m div 2 ^ m div 2 ^ (n - m)\<close>
+      by (simp add: zdiv_zmult2_eq)
+    finally show ?thesis using \<open>m < n\<close> by simp
+  next
+    case False
+    then show ?thesis
+      by (simp add: power_diff)
+  qed
+  show \<open>k mod 2 ^ m mod 2 ^ n = k mod 2 ^ min m n\<close>
+    for m n :: nat and k :: int
+    using mod_exp_eq [of \<open>nat k\<close> m n]
+    apply (auto simp add: mod_mod_cancel zdiv_zmult2_eq power_add zmod_zmult2_eq le_iff_add split: split_min_lin)
+     apply (auto simp add: less_iff_Suc_add mod_mod_cancel power_add)
+    apply (simp only: flip: mult.left_commute [of \<open>2 ^ m\<close>])
+    apply (subst zmod_zmult2_eq) apply simp_all
+    done
+  show \<open>(k * 2 ^ m) mod (2 ^ n) = (k mod 2 ^ (n - m)) * 2 ^ m\<close>
+    if \<open>m \<le> n\<close> for m n :: nat and k :: int
+    using that
+    apply (auto simp add: power_add zmod_zmult2_eq le_iff_add split: split_min_lin)
+    done
+  show \<open>even ((2 ^ m - (1::int)) div 2 ^ n) \<longleftrightarrow> 2 ^ n = (0::int) \<or> m \<le> n\<close>
+    for m n :: nat
+    using even_mask_div_iff' [where ?'a = int, of m n] by simp
+  show \<open>even (k * 2 ^ m div 2 ^ n) \<longleftrightarrow> n < m \<or> (2::int) ^ n = 0 \<or> m \<le> n \<and> even (k div 2 ^ (n - m))\<close>
+    for m n :: nat and k l :: int
+    apply (auto simp add: not_less power_add ac_simps dest!: le_Suc_ex)
+    apply (metis Suc_leI dvd_mult dvd_mult_imp_div dvd_power_le dvd_refl power.simps(2))
+    done
+qed (auto simp add: zdiv_zmult2_eq zmod_zmult2_eq power_add power_diff not_le bit_int_def)
+
+end
+
+lemma bit_not_int_iff':
+  \<open>bit (- k - 1) n \<longleftrightarrow> \<not> bit k n\<close>
+  for k :: int
+proof (induction n arbitrary: k)
+  case 0
+  show ?case
+    by simp
+next
+  case (Suc n)
+  have \<open>- k - 1 = - (k + 2) + 1\<close>
+    by simp
+  also have \<open>(- (k + 2) + 1) div 2 = - (k div 2) - 1\<close>
+  proof (cases \<open>even k\<close>)
+    case True
+    then have \<open>- k div 2 = - (k div 2)\<close>
+      by rule (simp flip: mult_minus_right)
+    with True show ?thesis
+      by simp
+  next
+    case False
+    have \<open>4 = 2 * (2::int)\<close>
+      by simp
+    also have \<open>2 * 2 div 2 = (2::int)\<close>
+      by (simp only: nonzero_mult_div_cancel_left)
+    finally have *: \<open>4 div 2 = (2::int)\<close> .
+    from False obtain l where k: \<open>k = 2 * l + 1\<close> ..
+    then have \<open>- k - 2 = 2 * - (l + 2) + 1\<close>
+      by simp
+    then have \<open>(- k - 2) div 2 + 1 = - (k div 2) - 1\<close>
+      by (simp flip: mult_minus_right add: *) (simp add: k)
+    with False show ?thesis
+      by simp
+  qed
+  finally have \<open>(- k - 1) div 2 = - (k div 2) - 1\<close> .
+  with Suc show ?case
+    by (simp add: bit_Suc)
+qed
+
+lemma bit_nat_iff [bit_simps]:
+  \<open>bit (nat k) n \<longleftrightarrow> k \<ge> 0 \<and> bit k n\<close>
+proof (cases \<open>k \<ge> 0\<close>)
+  case True
+  moreover define m where \<open>m = nat k\<close>
+  ultimately have \<open>k = int m\<close>
+    by simp
+  then show ?thesis
+    by (simp add: bit_simps)
+next
+  case False
+  then show ?thesis
+    by simp
+qed
+
+
+subsection \<open>Bit operations\<close>
+
+class semiring_bit_operations = semiring_bits +
+  fixes "and" :: \<open>'a \<Rightarrow> 'a \<Rightarrow> 'a\<close>  (infixr \<open>AND\<close> 64)
+    and or :: \<open>'a \<Rightarrow> 'a \<Rightarrow> 'a\<close>  (infixr \<open>OR\<close> 59)
+    and xor :: \<open>'a \<Rightarrow> 'a \<Rightarrow> 'a\<close>  (infixr \<open>XOR\<close> 59)
+    and mask :: \<open>nat \<Rightarrow> 'a\<close>
+    and set_bit :: \<open>nat \<Rightarrow> 'a \<Rightarrow> 'a\<close>
+    and unset_bit :: \<open>nat \<Rightarrow> 'a \<Rightarrow> 'a\<close>
+    and flip_bit :: \<open>nat \<Rightarrow> 'a \<Rightarrow> 'a\<close>
+    and push_bit :: \<open>nat \<Rightarrow> 'a \<Rightarrow> 'a\<close>
+    and drop_bit :: \<open>nat \<Rightarrow> 'a \<Rightarrow> 'a\<close>
+    and take_bit :: \<open>nat \<Rightarrow> 'a \<Rightarrow> 'a\<close>
+  assumes bit_and_iff [bit_simps]: \<open>bit (a AND b) n \<longleftrightarrow> bit a n \<and> bit b n\<close>
+    and bit_or_iff [bit_simps]: \<open>bit (a OR b) n \<longleftrightarrow> bit a n \<or> bit b n\<close>
+    and bit_xor_iff [bit_simps]: \<open>bit (a XOR b) n \<longleftrightarrow> bit a n \<noteq> bit b n\<close>
+    and mask_eq_exp_minus_1: \<open>mask n = 2 ^ n - 1\<close>
+    and set_bit_eq_or: \<open>set_bit n a = a OR push_bit n 1\<close>
+    and bit_unset_bit_iff [bit_simps]: \<open>bit (unset_bit m a) n \<longleftrightarrow> bit a n \<and> m \<noteq> n\<close>
+    and flip_bit_eq_xor: \<open>flip_bit n a = a XOR push_bit n 1\<close>
+    and push_bit_eq_mult: \<open>push_bit n a = a * 2 ^ n\<close>
+    and drop_bit_eq_div: \<open>drop_bit n a = a div 2 ^ n\<close>
+    and take_bit_eq_mod: \<open>take_bit n a = a mod 2 ^ n\<close>
+begin
+
+text \<open>
+  We want the bitwise operations to bind slightly weaker
+  than \<open>+\<close> and \<open>-\<close>.
+
+  Logically, \<^const>\<open>push_bit\<close>,
+  \<^const>\<open>drop_bit\<close> and \<^const>\<open>take_bit\<close> are just aliases; having them
+  as separate operations makes proofs easier, otherwise proof automation
+  would fiddle with concrete expressions \<^term>\<open>2 ^ n\<close> in a way obfuscating the basic
+  algebraic relationships between those operations.
+
+  For the sake of code generation operations 
+  are specified as definitional class operations,
+  taking into account that specific instances of these can be implemented
+  differently wrt. code generation.
+\<close>
+
+sublocale "and": semilattice \<open>(AND)\<close>
+  by standard (auto simp add: bit_eq_iff bit_and_iff)
+
+sublocale or: semilattice_neutr \<open>(OR)\<close> 0
+  by standard (auto simp add: bit_eq_iff bit_or_iff)
+
+sublocale xor: comm_monoid \<open>(XOR)\<close> 0
+  by standard (auto simp add: bit_eq_iff bit_xor_iff)
+
+lemma even_and_iff:
+  \<open>even (a AND b) \<longleftrightarrow> even a \<or> even b\<close>
+  using bit_and_iff [of a b 0] by auto
+
+lemma even_or_iff:
+  \<open>even (a OR b) \<longleftrightarrow> even a \<and> even b\<close>
+  using bit_or_iff [of a b 0] by auto
+
+lemma even_xor_iff:
+  \<open>even (a XOR b) \<longleftrightarrow> (even a \<longleftrightarrow> even b)\<close>
+  using bit_xor_iff [of a b 0] by auto
+
+lemma zero_and_eq [simp]:
+  \<open>0 AND a = 0\<close>
+  by (simp add: bit_eq_iff bit_and_iff)
+
+lemma and_zero_eq [simp]:
+  \<open>a AND 0 = 0\<close>
+  by (simp add: bit_eq_iff bit_and_iff)
+
+lemma one_and_eq:
+  \<open>1 AND a = a mod 2\<close>
+  by (simp add: bit_eq_iff bit_and_iff) (auto simp add: bit_1_iff)
+
+lemma and_one_eq:
+  \<open>a AND 1 = a mod 2\<close>
+  using one_and_eq [of a] by (simp add: ac_simps)
+
+lemma one_or_eq:
+  \<open>1 OR a = a + of_bool (even a)\<close>
+  by (simp add: bit_eq_iff bit_or_iff add.commute [of _ 1] even_bit_succ_iff) (auto simp add: bit_1_iff)
+
+lemma or_one_eq:
+  \<open>a OR 1 = a + of_bool (even a)\<close>
+  using one_or_eq [of a] by (simp add: ac_simps)
+
+lemma one_xor_eq:
+  \<open>1 XOR a = a + of_bool (even a) - of_bool (odd a)\<close>
+  by (simp add: bit_eq_iff bit_xor_iff add.commute [of _ 1] even_bit_succ_iff) (auto simp add: bit_1_iff odd_bit_iff_bit_pred elim: oddE)
+
+lemma xor_one_eq:
+  \<open>a XOR 1 = a + of_bool (even a) - of_bool (odd a)\<close>
+  using one_xor_eq [of a] by (simp add: ac_simps)
+
+lemma bit_iff_odd_drop_bit:
+  \<open>bit a n \<longleftrightarrow> odd (drop_bit n a)\<close>
+  by (simp add: bit_iff_odd drop_bit_eq_div)
+
+lemma even_drop_bit_iff_not_bit:
+  \<open>even (drop_bit n a) \<longleftrightarrow> \<not> bit a n\<close>
+  by (simp add: bit_iff_odd_drop_bit)
+
+lemma div_push_bit_of_1_eq_drop_bit:
+  \<open>a div push_bit n 1 = drop_bit n a\<close>
+  by (simp add: push_bit_eq_mult drop_bit_eq_div)
+
+lemma bits_ident:
+  "push_bit n (drop_bit n a) + take_bit n a = a"
+  using div_mult_mod_eq by (simp add: push_bit_eq_mult take_bit_eq_mod drop_bit_eq_div)
+
+lemma push_bit_push_bit [simp]:
+  "push_bit m (push_bit n a) = push_bit (m + n) a"
+  by (simp add: push_bit_eq_mult power_add ac_simps)
+
+lemma push_bit_0_id [simp]:
+  "push_bit 0 = id"
+  by (simp add: fun_eq_iff push_bit_eq_mult)
+
+lemma push_bit_of_0 [simp]:
+  "push_bit n 0 = 0"
+  by (simp add: push_bit_eq_mult)
+
+lemma push_bit_of_1:
+  "push_bit n 1 = 2 ^ n"
+  by (simp add: push_bit_eq_mult)
+
+lemma push_bit_Suc [simp]:
+  "push_bit (Suc n) a = push_bit n (a * 2)"
+  by (simp add: push_bit_eq_mult ac_simps)
+
+lemma push_bit_double:
+  "push_bit n (a * 2) = push_bit n a * 2"
+  by (simp add: push_bit_eq_mult ac_simps)
+
+lemma push_bit_add:
+  "push_bit n (a + b) = push_bit n a + push_bit n b"
+  by (simp add: push_bit_eq_mult algebra_simps)
+
+lemma push_bit_numeral [simp]:
+  \<open>push_bit (numeral l) (numeral k) = push_bit (pred_numeral l) (numeral (Num.Bit0 k))\<close>
+  by (simp add: numeral_eq_Suc mult_2_right) (simp add: numeral_Bit0)
+
+lemma take_bit_0 [simp]:
+  "take_bit 0 a = 0"
+  by (simp add: take_bit_eq_mod)
+
+lemma take_bit_Suc:
+  \<open>take_bit (Suc n) a = take_bit n (a div 2) * 2 + a mod 2\<close>
+proof -
+  have \<open>take_bit (Suc n) (a div 2 * 2 + of_bool (odd a)) = take_bit n (a div 2) * 2 + of_bool (odd a)\<close>
+    using even_succ_mod_exp [of \<open>2 * (a div 2)\<close> \<open>Suc n\<close>]
+      mult_exp_mod_exp_eq [of 1 \<open>Suc n\<close> \<open>a div 2\<close>]
+    by (auto simp add: take_bit_eq_mod ac_simps)
+  then show ?thesis
+    using div_mult_mod_eq [of a 2] by (simp add: mod_2_eq_odd)
+qed
+
+lemma take_bit_rec:
+  \<open>take_bit n a = (if n = 0 then 0 else take_bit (n - 1) (a div 2) * 2 + a mod 2)\<close>
+  by (cases n) (simp_all add: take_bit_Suc)
+
+lemma take_bit_Suc_0 [simp]:
+  \<open>take_bit (Suc 0) a = a mod 2\<close>
+  by (simp add: take_bit_eq_mod)
+
+lemma take_bit_of_0 [simp]:
+  "take_bit n 0 = 0"
+  by (simp add: take_bit_eq_mod)
+
+lemma take_bit_of_1 [simp]:
+  "take_bit n 1 = of_bool (n > 0)"
+  by (cases n) (simp_all add: take_bit_Suc)
+
+lemma drop_bit_of_0 [simp]:
+  "drop_bit n 0 = 0"
+  by (simp add: drop_bit_eq_div)
+
+lemma drop_bit_of_1 [simp]:
+  "drop_bit n 1 = of_bool (n = 0)"
+  by (simp add: drop_bit_eq_div)
+
+lemma drop_bit_0 [simp]:
+  "drop_bit 0 = id"
+  by (simp add: fun_eq_iff drop_bit_eq_div)
+
+lemma drop_bit_Suc:
+  "drop_bit (Suc n) a = drop_bit n (a div 2)"
+  using div_exp_eq [of a 1] by (simp add: drop_bit_eq_div)
+
+lemma drop_bit_rec:
+  "drop_bit n a = (if n = 0 then a else drop_bit (n - 1) (a div 2))"
+  by (cases n) (simp_all add: drop_bit_Suc)
+
+lemma drop_bit_half:
+  "drop_bit n (a div 2) = drop_bit n a div 2"
+  by (induction n arbitrary: a) (simp_all add: drop_bit_Suc)
+
+lemma drop_bit_of_bool [simp]:
+  "drop_bit n (of_bool b) = of_bool (n = 0 \<and> b)"
+  by (cases n) simp_all
+
+lemma even_take_bit_eq [simp]:
+  \<open>even (take_bit n a) \<longleftrightarrow> n = 0 \<or> even a\<close>
+  by (simp add: take_bit_rec [of n a])
+
+lemma take_bit_take_bit [simp]:
+  "take_bit m (take_bit n a) = take_bit (min m n) a"
+  by (simp add: take_bit_eq_mod mod_exp_eq ac_simps)
+
+lemma drop_bit_drop_bit [simp]:
+  "drop_bit m (drop_bit n a) = drop_bit (m + n) a"
+  by (simp add: drop_bit_eq_div power_add div_exp_eq ac_simps)
+
+lemma push_bit_take_bit:
+  "push_bit m (take_bit n a) = take_bit (m + n) (push_bit m a)"
+  apply (simp add: push_bit_eq_mult take_bit_eq_mod power_add ac_simps)
+  using mult_exp_mod_exp_eq [of m \<open>m + n\<close> a] apply (simp add: ac_simps power_add)
+  done
+
+lemma take_bit_push_bit:
+  "take_bit m (push_bit n a) = push_bit n (take_bit (m - n) a)"
+proof (cases "m \<le> n")
+  case True
+  then show ?thesis
+    apply (simp add:)
+    apply (simp_all add: push_bit_eq_mult take_bit_eq_mod)
+    apply (auto dest!: le_Suc_ex simp add: power_add ac_simps)
+    using mult_exp_mod_exp_eq [of m m \<open>a * 2 ^ n\<close> for n]
+    apply (simp add: ac_simps)
+    done
+next
+  case False
+  then show ?thesis
+    using push_bit_take_bit [of n "m - n" a]
+    by simp
+qed
+
+lemma take_bit_drop_bit:
+  "take_bit m (drop_bit n a) = drop_bit n (take_bit (m + n) a)"
+  by (simp add: drop_bit_eq_div take_bit_eq_mod ac_simps div_exp_mod_exp_eq)
+
+lemma drop_bit_take_bit:
+  "drop_bit m (take_bit n a) = take_bit (n - m) (drop_bit m a)"
+proof (cases "m \<le> n")
+  case True
+  then show ?thesis
+    using take_bit_drop_bit [of "n - m" m a] by simp
+next
+  case False
+  then obtain q where \<open>m = n + q\<close>
+    by (auto simp add: not_le dest: less_imp_Suc_add)
+  then have \<open>drop_bit m (take_bit n a) = 0\<close>
+    using div_exp_eq [of \<open>a mod 2 ^ n\<close> n q]
+    by (simp add: take_bit_eq_mod drop_bit_eq_div)
+  with False show ?thesis
+    by simp
+qed
+
+lemma even_push_bit_iff [simp]:
+  \<open>even (push_bit n a) \<longleftrightarrow> n \<noteq> 0 \<or> even a\<close>
+  by (simp add: push_bit_eq_mult) auto
+
+lemma bit_push_bit_iff [bit_simps]:
+  \<open>bit (push_bit m a) n \<longleftrightarrow> m \<le> n \<and> 2 ^ n \<noteq> 0 \<and> bit a (n - m)\<close>
+  by (auto simp add: bit_iff_odd push_bit_eq_mult even_mult_exp_div_exp_iff)
+
+lemma bit_drop_bit_eq [bit_simps]:
+  \<open>bit (drop_bit n a) = bit a \<circ> (+) n\<close>
+  by (simp add: bit_iff_odd fun_eq_iff ac_simps flip: drop_bit_eq_div)
+
+lemma bit_take_bit_iff [bit_simps]:
+  \<open>bit (take_bit m a) n \<longleftrightarrow> n < m \<and> bit a n\<close>
+  by (simp add: bit_iff_odd drop_bit_take_bit not_le flip: drop_bit_eq_div)
+
+lemma stable_imp_drop_bit_eq:
+  \<open>drop_bit n a = a\<close>
+  if \<open>a div 2 = a\<close>
+  by (induction n) (simp_all add: that drop_bit_Suc)
+
+lemma stable_imp_take_bit_eq:
+  \<open>take_bit n a = (if even a then 0 else 2 ^ n - 1)\<close>
+    if \<open>a div 2 = a\<close>
+proof (rule bit_eqI)
+  fix m
+  assume \<open>2 ^ m \<noteq> 0\<close>
+  with that show \<open>bit (take_bit n a) m \<longleftrightarrow> bit (if even a then 0 else 2 ^ n - 1) m\<close>
+    by (simp add: bit_take_bit_iff bit_mask_iff stable_imp_bit_iff_odd)
+qed
+
+lemma exp_dvdE:
+  assumes \<open>2 ^ n dvd a\<close>
+  obtains b where \<open>a = push_bit n b\<close>
+proof -
+  from assms obtain b where \<open>a = 2 ^ n * b\<close> ..
+  then have \<open>a = push_bit n b\<close>
+    by (simp add: push_bit_eq_mult ac_simps)
+  with that show thesis .
+qed
+
+lemma take_bit_eq_0_iff:
+  \<open>take_bit n a = 0 \<longleftrightarrow> 2 ^ n dvd a\<close> (is \<open>?P \<longleftrightarrow> ?Q\<close>)
+proof
+  assume ?P
+  then show ?Q
+    by (simp add: take_bit_eq_mod mod_0_imp_dvd)
+next
+  assume ?Q
+  then obtain b where \<open>a = push_bit n b\<close>
+    by (rule exp_dvdE)
+  then show ?P
+    by (simp add: take_bit_push_bit)
+qed
+
+lemma take_bit_tightened:
+  \<open>take_bit m a = take_bit m b\<close> if \<open>take_bit n a = take_bit n b\<close> and \<open>m \<le> n\<close> 
+proof -
+  from that have \<open>take_bit m (take_bit n a) = take_bit m (take_bit n b)\<close>
+    by simp
+  then have \<open>take_bit (min m n) a = take_bit (min m n) b\<close>
+    by simp
+  with that show ?thesis
+    by (simp add: min_def)
+qed
+
+lemma take_bit_eq_self_iff_drop_bit_eq_0:
+  \<open>take_bit n a = a \<longleftrightarrow> drop_bit n a = 0\<close> (is \<open>?P \<longleftrightarrow> ?Q\<close>)
+proof
+  assume ?P
+  show ?Q
+  proof (rule bit_eqI)
+    fix m
+    from \<open>?P\<close> have \<open>a = take_bit n a\<close> ..
+    also have \<open>\<not> bit (take_bit n a) (n + m)\<close>
+      unfolding bit_simps
+      by (simp add: bit_simps) 
+    finally show \<open>bit (drop_bit n a) m \<longleftrightarrow> bit 0 m\<close>
+      by (simp add: bit_simps)
+  qed
+next
+  assume ?Q
+  show ?P
+  proof (rule bit_eqI)
+    fix m
+    from \<open>?Q\<close> have \<open>\<not> bit (drop_bit n a) (m - n)\<close>
+      by simp
+    then have \<open> \<not> bit a (n + (m - n))\<close>
+      by (simp add: bit_simps)
+    then show \<open>bit (take_bit n a) m \<longleftrightarrow> bit a m\<close>
+      by (cases \<open>m < n\<close>) (auto simp add: bit_simps)
+  qed
+qed
+
+lemma drop_bit_exp_eq:
+  \<open>drop_bit m (2 ^ n) = of_bool (m \<le> n \<and> 2 ^ n \<noteq> 0) * 2 ^ (n - m)\<close>
+  by (rule bit_eqI) (auto simp add: bit_simps)
+
+lemma take_bit_and [simp]:
+  \<open>take_bit n (a AND b) = take_bit n a AND take_bit n b\<close>
+  by (auto simp add: bit_eq_iff bit_take_bit_iff bit_and_iff)
+
+lemma take_bit_or [simp]:
+  \<open>take_bit n (a OR b) = take_bit n a OR take_bit n b\<close>
+  by (auto simp add: bit_eq_iff bit_take_bit_iff bit_or_iff)
+
+lemma take_bit_xor [simp]:
+  \<open>take_bit n (a XOR b) = take_bit n a XOR take_bit n b\<close>
+  by (auto simp add: bit_eq_iff bit_take_bit_iff bit_xor_iff)
+
+lemma push_bit_and [simp]:
+  \<open>push_bit n (a AND b) = push_bit n a AND push_bit n b\<close>
+  by (rule bit_eqI) (auto simp add: bit_push_bit_iff bit_and_iff)
+
+lemma push_bit_or [simp]:
+  \<open>push_bit n (a OR b) = push_bit n a OR push_bit n b\<close>
+  by (rule bit_eqI) (auto simp add: bit_push_bit_iff bit_or_iff)
+
+lemma push_bit_xor [simp]:
+  \<open>push_bit n (a XOR b) = push_bit n a XOR push_bit n b\<close>
+  by (rule bit_eqI) (auto simp add: bit_push_bit_iff bit_xor_iff)
+
+lemma drop_bit_and [simp]:
+  \<open>drop_bit n (a AND b) = drop_bit n a AND drop_bit n b\<close>
+  by (rule bit_eqI) (auto simp add: bit_drop_bit_eq bit_and_iff)
+
+lemma drop_bit_or [simp]:
+  \<open>drop_bit n (a OR b) = drop_bit n a OR drop_bit n b\<close>
+  by (rule bit_eqI) (auto simp add: bit_drop_bit_eq bit_or_iff)
+
+lemma drop_bit_xor [simp]:
+  \<open>drop_bit n (a XOR b) = drop_bit n a XOR drop_bit n b\<close>
+  by (rule bit_eqI) (auto simp add: bit_drop_bit_eq bit_xor_iff)
+
+lemma bit_mask_iff [bit_simps]:
+  \<open>bit (mask m) n \<longleftrightarrow> 2 ^ n \<noteq> 0 \<and> n < m\<close>
+  by (simp add: mask_eq_exp_minus_1 bit_mask_iff)
+
+lemma even_mask_iff:
+  \<open>even (mask n) \<longleftrightarrow> n = 0\<close>
+  using bit_mask_iff [of n 0] by auto
+
+lemma mask_0 [simp]:
+  \<open>mask 0 = 0\<close>
+  by (simp add: mask_eq_exp_minus_1)
+
+lemma mask_Suc_0 [simp]:
+  \<open>mask (Suc 0) = 1\<close>
+  by (simp add: mask_eq_exp_minus_1 add_implies_diff sym)
+
+lemma mask_Suc_exp:
+  \<open>mask (Suc n) = 2 ^ n OR mask n\<close>
+  by (rule bit_eqI)
+    (auto simp add: bit_or_iff bit_mask_iff bit_exp_iff not_less le_less_Suc_eq)
+
+lemma mask_Suc_double:
+  \<open>mask (Suc n) = 1 OR 2 * mask n\<close>
+proof (rule bit_eqI)
+  fix q
+  assume \<open>2 ^ q \<noteq> 0\<close>
+  show \<open>bit (mask (Suc n)) q \<longleftrightarrow> bit (1 OR 2 * mask n) q\<close>
+    by (cases q)
+      (simp_all add: even_mask_iff even_or_iff bit_or_iff bit_mask_iff bit_exp_iff bit_double_iff not_less le_less_Suc_eq bit_1_iff, auto simp add: mult_2)
+qed
+
+lemma mask_numeral:
+  \<open>mask (numeral n) = 1 + 2 * mask (pred_numeral n)\<close>
+  by (simp add: numeral_eq_Suc mask_Suc_double one_or_eq ac_simps)
+
+lemma take_bit_mask [simp]:
+  \<open>take_bit m (mask n) = mask (min m n)\<close>
+  by (rule bit_eqI) (simp add: bit_simps)
+
+lemma take_bit_eq_mask:
+  \<open>take_bit n a = a AND mask n\<close>
+  by (rule bit_eqI)
+    (auto simp add: bit_take_bit_iff bit_and_iff bit_mask_iff)
+
+lemma or_eq_0_iff:
+  \<open>a OR b = 0 \<longleftrightarrow> a = 0 \<and> b = 0\<close>
+  by (auto simp add: bit_eq_iff bit_or_iff)
+
+lemma disjunctive_add:
+  \<open>a + b = a OR b\<close> if \<open>\<And>n. \<not> bit a n \<or> \<not> bit b n\<close>
+  by (rule bit_eqI) (use that in \<open>simp add: bit_disjunctive_add_iff bit_or_iff\<close>)
+
+lemma bit_iff_and_drop_bit_eq_1:
+  \<open>bit a n \<longleftrightarrow> drop_bit n a AND 1 = 1\<close>
+  by (simp add: bit_iff_odd_drop_bit and_one_eq odd_iff_mod_2_eq_one)
+
+lemma bit_iff_and_push_bit_not_eq_0:
+  \<open>bit a n \<longleftrightarrow> a AND push_bit n 1 \<noteq> 0\<close>
+  apply (cases \<open>2 ^ n = 0\<close>)
+  apply (simp_all add: push_bit_of_1 bit_eq_iff bit_and_iff bit_push_bit_iff exp_eq_0_imp_not_bit)
+  apply (simp_all add: bit_exp_iff)
+  done
+
+lemmas set_bit_def = set_bit_eq_or
+
+lemma bit_set_bit_iff [bit_simps]:
+  \<open>bit (set_bit m a) n \<longleftrightarrow> bit a n \<or> (m = n \<and> 2 ^ n \<noteq> 0)\<close>
+  by (auto simp add: set_bit_def push_bit_of_1 bit_or_iff bit_exp_iff)
+
+lemma even_set_bit_iff:
+  \<open>even (set_bit m a) \<longleftrightarrow> even a \<and> m \<noteq> 0\<close>
+  using bit_set_bit_iff [of m a 0] by auto
+
+lemma even_unset_bit_iff:
+  \<open>even (unset_bit m a) \<longleftrightarrow> even a \<or> m = 0\<close>
+  using bit_unset_bit_iff [of m a 0] by auto
+
+lemma and_exp_eq_0_iff_not_bit:
+  \<open>a AND 2 ^ n = 0 \<longleftrightarrow> \<not> bit a n\<close> (is \<open>?P \<longleftrightarrow> ?Q\<close>)
+proof
+  assume ?Q
+  then show ?P
+    by (auto intro: bit_eqI simp add: bit_simps)
+next
+  assume ?P
+  show ?Q
+  proof (rule notI)
+    assume \<open>bit a n\<close>
+    then have \<open>a AND 2 ^ n = 2 ^ n\<close>
+      by (auto intro: bit_eqI simp add: bit_simps)
+    with \<open>?P\<close> show False
+      using \<open>bit a n\<close> exp_eq_0_imp_not_bit by auto
+  qed
+qed
+
+lemmas flip_bit_def = flip_bit_eq_xor
+
+lemma bit_flip_bit_iff [bit_simps]:
+  \<open>bit (flip_bit m a) n \<longleftrightarrow> (m = n \<longleftrightarrow> \<not> bit a n) \<and> 2 ^ n \<noteq> 0\<close>
+  by (auto simp add: flip_bit_def push_bit_of_1 bit_xor_iff bit_exp_iff exp_eq_0_imp_not_bit)
+
+lemma even_flip_bit_iff:
+  \<open>even (flip_bit m a) \<longleftrightarrow> \<not> (even a \<longleftrightarrow> m = 0)\<close>
+  using bit_flip_bit_iff [of m a 0] by auto
+
+lemma set_bit_0 [simp]:
+  \<open>set_bit 0 a = 1 + 2 * (a div 2)\<close>
+proof (rule bit_eqI)
+  fix m
+  assume *: \<open>2 ^ m \<noteq> 0\<close>
+  then show \<open>bit (set_bit 0 a) m = bit (1 + 2 * (a div 2)) m\<close>
+    by (simp add: bit_set_bit_iff bit_double_iff even_bit_succ_iff)
+      (cases m, simp_all add: bit_Suc)
+qed
+
+lemma set_bit_Suc:
+  \<open>set_bit (Suc n) a = a mod 2 + 2 * set_bit n (a div 2)\<close>
+proof (rule bit_eqI)
+  fix m
+  assume *: \<open>2 ^ m \<noteq> 0\<close>
+  show \<open>bit (set_bit (Suc n) a) m \<longleftrightarrow> bit (a mod 2 + 2 * set_bit n (a div 2)) m\<close>
+  proof (cases m)
+    case 0
+    then show ?thesis
+      by (simp add: even_set_bit_iff)
+  next
+    case (Suc m)
+    with * have \<open>2 ^ m \<noteq> 0\<close>
+      using mult_2 by auto
+    show ?thesis
+      by (cases a rule: parity_cases)
+        (simp_all add: bit_set_bit_iff bit_double_iff even_bit_succ_iff *,
+        simp_all add: Suc \<open>2 ^ m \<noteq> 0\<close> bit_Suc)
+  qed
+qed
+
+lemma unset_bit_0 [simp]:
+  \<open>unset_bit 0 a = 2 * (a div 2)\<close>
+proof (rule bit_eqI)
+  fix m
+  assume *: \<open>2 ^ m \<noteq> 0\<close>
+  then show \<open>bit (unset_bit 0 a) m = bit (2 * (a div 2)) m\<close>
+    by (simp add: bit_unset_bit_iff bit_double_iff)
+      (cases m, simp_all add: bit_Suc)
+qed
+
+lemma unset_bit_Suc:
+  \<open>unset_bit (Suc n) a = a mod 2 + 2 * unset_bit n (a div 2)\<close>
+proof (rule bit_eqI)
+  fix m
+  assume *: \<open>2 ^ m \<noteq> 0\<close>
+  then show \<open>bit (unset_bit (Suc n) a) m \<longleftrightarrow> bit (a mod 2 + 2 * unset_bit n (a div 2)) m\<close>
+  proof (cases m)
+    case 0
+    then show ?thesis
+      by (simp add: even_unset_bit_iff)
+  next
+    case (Suc m)
+    show ?thesis
+      by (cases a rule: parity_cases)
+        (simp_all add: bit_unset_bit_iff bit_double_iff even_bit_succ_iff *,
+         simp_all add: Suc bit_Suc)
+  qed
+qed
+
+lemma flip_bit_0 [simp]:
+  \<open>flip_bit 0 a = of_bool (even a) + 2 * (a div 2)\<close>
+proof (rule bit_eqI)
+  fix m
+  assume *: \<open>2 ^ m \<noteq> 0\<close>
+  then show \<open>bit (flip_bit 0 a) m = bit (of_bool (even a) + 2 * (a div 2)) m\<close>
+    by (simp add: bit_flip_bit_iff bit_double_iff even_bit_succ_iff)
+      (cases m, simp_all add: bit_Suc)
+qed
+
+lemma flip_bit_Suc:
+  \<open>flip_bit (Suc n) a = a mod 2 + 2 * flip_bit n (a div 2)\<close>
+proof (rule bit_eqI)
+  fix m
+  assume *: \<open>2 ^ m \<noteq> 0\<close>
+  show \<open>bit (flip_bit (Suc n) a) m \<longleftrightarrow> bit (a mod 2 + 2 * flip_bit n (a div 2)) m\<close>
+  proof (cases m)
+    case 0
+    then show ?thesis
+      by (simp add: even_flip_bit_iff)
+  next
+    case (Suc m)
+    with * have \<open>2 ^ m \<noteq> 0\<close>
+      using mult_2 by auto
+    show ?thesis
+      by (cases a rule: parity_cases)
+        (simp_all add: bit_flip_bit_iff bit_double_iff even_bit_succ_iff,
+        simp_all add: Suc \<open>2 ^ m \<noteq> 0\<close> bit_Suc)
+  qed
+qed
+
+lemma flip_bit_eq_if:
+  \<open>flip_bit n a = (if bit a n then unset_bit else set_bit) n a\<close>
+  by (rule bit_eqI) (auto simp add: bit_set_bit_iff bit_unset_bit_iff bit_flip_bit_iff)
+
+lemma take_bit_set_bit_eq:
+  \<open>take_bit n (set_bit m a) = (if n \<le> m then take_bit n a else set_bit m (take_bit n a))\<close>
+  by (rule bit_eqI) (auto simp add: bit_take_bit_iff bit_set_bit_iff)
+
+lemma take_bit_unset_bit_eq:
+  \<open>take_bit n (unset_bit m a) = (if n \<le> m then take_bit n a else unset_bit m (take_bit n a))\<close>
+  by (rule bit_eqI) (auto simp add: bit_take_bit_iff bit_unset_bit_iff)
+
+lemma take_bit_flip_bit_eq:
+  \<open>take_bit n (flip_bit m a) = (if n \<le> m then take_bit n a else flip_bit m (take_bit n a))\<close>
+  by (rule bit_eqI) (auto simp add: bit_take_bit_iff bit_flip_bit_iff)
+
+end
+
+class ring_bit_operations = semiring_bit_operations + ring_parity +
+  fixes not :: \<open>'a \<Rightarrow> 'a\<close>  (\<open>NOT\<close>)
+  assumes bit_not_iff [bit_simps]: \<open>\<And>n. bit (NOT a) n \<longleftrightarrow> 2 ^ n \<noteq> 0 \<and> \<not> bit a n\<close>
+  assumes minus_eq_not_minus_1: \<open>- a = NOT (a - 1)\<close>
+begin
+
+text \<open>
+  For the sake of code generation \<^const>\<open>not\<close> is specified as
+  definitional class operation.  Note that \<^const>\<open>not\<close> has no
+  sensible definition for unlimited but only positive bit strings
+  (type \<^typ>\<open>nat\<close>).
+\<close>
+
+lemma bits_minus_1_mod_2_eq [simp]:
+  \<open>(- 1) mod 2 = 1\<close>
+  by (simp add: mod_2_eq_odd)
+
+lemma not_eq_complement:
+  \<open>NOT a = - a - 1\<close>
+  using minus_eq_not_minus_1 [of \<open>a + 1\<close>] by simp
+
+lemma minus_eq_not_plus_1:
+  \<open>- a = NOT a + 1\<close>
+  using not_eq_complement [of a] by simp
+
+lemma bit_minus_iff [bit_simps]:
+  \<open>bit (- a) n \<longleftrightarrow> 2 ^ n \<noteq> 0 \<and> \<not> bit (a - 1) n\<close>
+  by (simp add: minus_eq_not_minus_1 bit_not_iff)
+
+lemma even_not_iff [simp]:
+  \<open>even (NOT a) \<longleftrightarrow> odd a\<close>
+  using bit_not_iff [of a 0] by auto
+
+lemma bit_not_exp_iff [bit_simps]:
+  \<open>bit (NOT (2 ^ m)) n \<longleftrightarrow> 2 ^ n \<noteq> 0 \<and> n \<noteq> m\<close>
+  by (auto simp add: bit_not_iff bit_exp_iff)
+
+lemma bit_minus_1_iff [simp]:
+  \<open>bit (- 1) n \<longleftrightarrow> 2 ^ n \<noteq> 0\<close>
+  by (simp add: bit_minus_iff)
+
+lemma bit_minus_exp_iff [bit_simps]:
+  \<open>bit (- (2 ^ m)) n \<longleftrightarrow> 2 ^ n \<noteq> 0 \<and> n \<ge> m\<close>
+  by (auto simp add: bit_simps simp flip: mask_eq_exp_minus_1)
+
+lemma bit_minus_2_iff [simp]:
+  \<open>bit (- 2) n \<longleftrightarrow> 2 ^ n \<noteq> 0 \<and> n > 0\<close>
+  by (simp add: bit_minus_iff bit_1_iff)
+
+lemma not_one [simp]:
+  \<open>NOT 1 = - 2\<close>
+  by (simp add: bit_eq_iff bit_not_iff) (simp add: bit_1_iff)
+
+sublocale "and": semilattice_neutr \<open>(AND)\<close> \<open>- 1\<close>
+  by standard (rule bit_eqI, simp add: bit_and_iff)
+
+sublocale bit: abstract_boolean_algebra \<open>(AND)\<close> \<open>(OR)\<close> NOT 0 \<open>- 1\<close>
+  by standard (auto simp add: bit_and_iff bit_or_iff bit_not_iff intro: bit_eqI)
+
+sublocale bit: abstract_boolean_algebra_sym_diff \<open>(AND)\<close> \<open>(OR)\<close> NOT 0 \<open>- 1\<close> \<open>(XOR)\<close>
+  apply standard
+  apply (rule bit_eqI)
+  apply (auto simp add: bit_simps)
+  done
+
+lemma and_eq_not_not_or:
+  \<open>a AND b = NOT (NOT a OR NOT b)\<close>
+  by simp
+
+lemma or_eq_not_not_and:
+  \<open>a OR b = NOT (NOT a AND NOT b)\<close>
+  by simp
+
+lemma not_add_distrib:
+  \<open>NOT (a + b) = NOT a - b\<close>
+  by (simp add: not_eq_complement algebra_simps)
+
+lemma not_diff_distrib:
+  \<open>NOT (a - b) = NOT a + b\<close>
+  using not_add_distrib [of a \<open>- b\<close>] by simp
+
+lemma and_eq_minus_1_iff:
+  \<open>a AND b = - 1 \<longleftrightarrow> a = - 1 \<and> b = - 1\<close>
+proof
+  assume \<open>a = - 1 \<and> b = - 1\<close>
+  then show \<open>a AND b = - 1\<close>
+    by simp
+next
+  assume \<open>a AND b = - 1\<close>
+  have *: \<open>bit a n\<close> \<open>bit b n\<close> if \<open>2 ^ n \<noteq> 0\<close> for n
+  proof -
+    from \<open>a AND b = - 1\<close>
+    have \<open>bit (a AND b) n = bit (- 1) n\<close>
+      by (simp add: bit_eq_iff)
+    then show \<open>bit a n\<close> \<open>bit b n\<close>
+      using that by (simp_all add: bit_and_iff)
+  qed
+  have \<open>a = - 1\<close>
+    by (rule bit_eqI) (simp add: *)
+  moreover have \<open>b = - 1\<close>
+    by (rule bit_eqI) (simp add: *)
+  ultimately show \<open>a = - 1 \<and> b = - 1\<close>
+    by simp
+qed
+
+lemma disjunctive_diff:
+  \<open>a - b = a AND NOT b\<close> if \<open>\<And>n. bit b n \<Longrightarrow> bit a n\<close>
+proof -
+  have \<open>NOT a + b = NOT a OR b\<close>
+    by (rule disjunctive_add) (auto simp add: bit_not_iff dest: that)
+  then have \<open>NOT (NOT a + b) = NOT (NOT a OR b)\<close>
+    by simp
+  then show ?thesis
+    by (simp add: not_add_distrib)
+qed
+
+lemma push_bit_minus:
+  \<open>push_bit n (- a) = - push_bit n a\<close>
+  by (simp add: push_bit_eq_mult)
+
+lemma take_bit_not_take_bit:
+  \<open>take_bit n (NOT (take_bit n a)) = take_bit n (NOT a)\<close>
+  by (auto simp add: bit_eq_iff bit_take_bit_iff bit_not_iff)
+
+lemma take_bit_not_iff:
+  \<open>take_bit n (NOT a) = take_bit n (NOT b) \<longleftrightarrow> take_bit n a = take_bit n b\<close>
+  apply (simp add: bit_eq_iff)
+  apply (simp add: bit_not_iff bit_take_bit_iff bit_exp_iff)
+  apply (use exp_eq_0_imp_not_bit in blast)
+  done
+
+lemma take_bit_not_eq_mask_diff:
+  \<open>take_bit n (NOT a) = mask n - take_bit n a\<close>
+proof -
+  have \<open>take_bit n (NOT a) = take_bit n (NOT (take_bit n a))\<close>
+    by (simp add: take_bit_not_take_bit)
+  also have \<open>\<dots> = mask n AND NOT (take_bit n a)\<close>
+    by (simp add: take_bit_eq_mask ac_simps)
+  also have \<open>\<dots> = mask n - take_bit n a\<close>
+    by (subst disjunctive_diff)
+      (auto simp add: bit_take_bit_iff bit_mask_iff exp_eq_0_imp_not_bit)
+  finally show ?thesis
+    by simp
+qed
+
+lemma mask_eq_take_bit_minus_one:
+  \<open>mask n = take_bit n (- 1)\<close>
+  by (simp add: bit_eq_iff bit_mask_iff bit_take_bit_iff conj_commute)
+
+lemma take_bit_minus_one_eq_mask:
+  \<open>take_bit n (- 1) = mask n\<close>
+  by (simp add: mask_eq_take_bit_minus_one)
+
+lemma minus_exp_eq_not_mask:
+  \<open>- (2 ^ n) = NOT (mask n)\<close>
+  by (rule bit_eqI) (simp add: bit_minus_iff bit_not_iff flip: mask_eq_exp_minus_1)
+
+lemma push_bit_minus_one_eq_not_mask:
+  \<open>push_bit n (- 1) = NOT (mask n)\<close>
+  by (simp add: push_bit_eq_mult minus_exp_eq_not_mask)
+
+lemma take_bit_not_mask_eq_0:
+  \<open>take_bit m (NOT (mask n)) = 0\<close> if \<open>n \<ge> m\<close>
+  by (rule bit_eqI) (use that in \<open>simp add: bit_take_bit_iff bit_not_iff bit_mask_iff\<close>)
+
+lemma unset_bit_eq_and_not:
+  \<open>unset_bit n a = a AND NOT (push_bit n 1)\<close>
+  by (rule bit_eqI) (auto simp add: bit_simps)
+
+lemmas unset_bit_def = unset_bit_eq_and_not
+
+end
+
+
+subsection \<open>Instance \<^typ>\<open>int\<close>\<close>
+
+instantiation int :: ring_bit_operations
+begin
+
+definition not_int :: \<open>int \<Rightarrow> int\<close>
+  where \<open>not_int k = - k - 1\<close>
+
+lemma not_int_rec:
+  \<open>NOT k = of_bool (even k) + 2 * NOT (k div 2)\<close> for k :: int
+  by (auto simp add: not_int_def elim: oddE)
+
+lemma even_not_iff_int:
+  \<open>even (NOT k) \<longleftrightarrow> odd k\<close> for k :: int
+  by (simp add: not_int_def)
+
+lemma not_int_div_2:
+  \<open>NOT k div 2 = NOT (k div 2)\<close> for k :: int
+  by (cases k) (simp_all add: not_int_def divide_int_def nat_add_distrib)
+
+lemma bit_not_int_iff [bit_simps]:
+  \<open>bit (NOT k) n \<longleftrightarrow> \<not> bit k n\<close>
+  for k :: int
+  by (simp add: bit_not_int_iff' not_int_def)
+
+function and_int :: \<open>int \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>(k::int) AND l = (if k \<in> {0, - 1} \<and> l \<in> {0, - 1}
+    then - of_bool (odd k \<and> odd l)
+    else of_bool (odd k \<and> odd l) + 2 * ((k div 2) AND (l div 2)))\<close>
+  by auto
+
+termination proof (relation \<open>measure (\<lambda>(k, l). nat (\<bar>k\<bar> + \<bar>l\<bar>))\<close>)
+  show \<open>wf (measure (\<lambda>(k, l). nat (\<bar>k\<bar> + \<bar>l\<bar>)))\<close>
+    by simp
+  show \<open>((k div 2, l div 2), k, l) \<in> measure (\<lambda>(k, l). nat (\<bar>k\<bar> + \<bar>l\<bar>))\<close>
+    if \<open>\<not> (k \<in> {0, - 1} \<and> l \<in> {0, - 1})\<close> for k l
+  proof -
+    have less_eq: \<open>\<bar>k div 2\<bar> \<le> \<bar>k\<bar>\<close> for k :: int
+      by (cases k) (simp_all add: divide_int_def nat_add_distrib)
+    have less: \<open>\<bar>k div 2\<bar> < \<bar>k\<bar>\<close> if \<open>k \<notin> {0, - 1}\<close> for k :: int
+    proof (cases k)
+      case (nonneg n)
+      with that show ?thesis
+        by (simp add: int_div_less_self)
+    next
+      case (neg n)
+      with that have \<open>n \<noteq> 0\<close>
+        by simp
+      then have \<open>n div 2 < n\<close>
+        by (simp add: div_less_iff_less_mult)
+      with neg that show ?thesis
+        by (simp add: divide_int_def nat_add_distrib)
+    qed
+    from that have *: \<open>k \<notin> {0, - 1} \<or> l \<notin> {0, - 1}\<close>
+      by simp
+    then have \<open>0 < \<bar>k\<bar> + \<bar>l\<bar>\<close>
+      by auto
+    moreover from * have \<open>\<bar>k div 2\<bar> + \<bar>l div 2\<bar> < \<bar>k\<bar> + \<bar>l\<bar>\<close>
+    proof
+      assume \<open>k \<notin> {0, - 1}\<close>
+      then have \<open>\<bar>k div 2\<bar> < \<bar>k\<bar>\<close>
+        by (rule less)
+      with less_eq [of l] show ?thesis
+        by auto
+    next
+      assume \<open>l \<notin> {0, - 1}\<close>
+      then have \<open>\<bar>l div 2\<bar> < \<bar>l\<bar>\<close>
+        by (rule less)
+      with less_eq [of k] show ?thesis
+        by auto
+    qed
+    ultimately show ?thesis
+      by simp
+  qed
+qed
+
+declare and_int.simps [simp del]
+
+lemma and_int_rec:
+  \<open>k AND l = of_bool (odd k \<and> odd l) + 2 * ((k div 2) AND (l div 2))\<close>
+    for k l :: int
+proof (cases \<open>k \<in> {0, - 1} \<and> l \<in> {0, - 1}\<close>)
+  case True
+  then show ?thesis
+    by auto (simp_all add: and_int.simps)
+next
+  case False
+  then show ?thesis
+    by (auto simp add: ac_simps and_int.simps [of k l])
+qed
+
+lemma bit_and_int_iff:
+  \<open>bit (k AND l) n \<longleftrightarrow> bit k n \<and> bit l n\<close> for k l :: int
+proof (induction n arbitrary: k l)
+  case 0
+  then show ?case
+    by (simp add: and_int_rec [of k l])
+next
+  case (Suc n)
+  then show ?case
+    by (simp add: and_int_rec [of k l] bit_Suc)
+qed
+
+lemma even_and_iff_int:
+  \<open>even (k AND l) \<longleftrightarrow> even k \<or> even l\<close> for k l :: int
+  using bit_and_int_iff [of k l 0] by auto
+
+definition or_int :: \<open>int \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>k OR l = NOT (NOT k AND NOT l)\<close> for k l :: int
+
+lemma or_int_rec:
+  \<open>k OR l = of_bool (odd k \<or> odd l) + 2 * ((k div 2) OR (l div 2))\<close>
+  for k l :: int
+  using and_int_rec [of \<open>NOT k\<close> \<open>NOT l\<close>]
+  by (simp add: or_int_def even_not_iff_int not_int_div_2)
+    (simp_all add: not_int_def)
+
+lemma bit_or_int_iff:
+  \<open>bit (k OR l) n \<longleftrightarrow> bit k n \<or> bit l n\<close> for k l :: int
+  by (simp add: or_int_def bit_not_int_iff bit_and_int_iff)
+
+definition xor_int :: \<open>int \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>k XOR l = k AND NOT l OR NOT k AND l\<close> for k l :: int
+
+lemma xor_int_rec:
+  \<open>k XOR l = of_bool (odd k \<noteq> odd l) + 2 * ((k div 2) XOR (l div 2))\<close>
+  for k l :: int
+  by (simp add: xor_int_def or_int_rec [of \<open>k AND NOT l\<close> \<open>NOT k AND l\<close>] even_and_iff_int even_not_iff_int)
+    (simp add: and_int_rec [of \<open>NOT k\<close> \<open>l\<close>] and_int_rec [of \<open>k\<close> \<open>NOT l\<close>] not_int_div_2)
+
+lemma bit_xor_int_iff:
+  \<open>bit (k XOR l) n \<longleftrightarrow> bit k n \<noteq> bit l n\<close> for k l :: int
+  by (auto simp add: xor_int_def bit_or_int_iff bit_and_int_iff bit_not_int_iff)
+
+definition mask_int :: \<open>nat \<Rightarrow> int\<close>
+  where \<open>mask n = (2 :: int) ^ n - 1\<close>
+
+definition push_bit_int :: \<open>nat \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>push_bit_int n k = k * 2 ^ n\<close>
+
+definition drop_bit_int :: \<open>nat \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>drop_bit_int n k = k div 2 ^ n\<close>
+
+definition take_bit_int :: \<open>nat \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>take_bit_int n k = k mod 2 ^ n\<close>
+
+definition set_bit_int :: \<open>nat \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>set_bit n k = k OR push_bit n 1\<close> for k :: int
+
+definition unset_bit_int :: \<open>nat \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>unset_bit n k = k AND NOT (push_bit n 1)\<close> for k :: int
+
+definition flip_bit_int :: \<open>nat \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>flip_bit n k = k XOR push_bit n 1\<close> for k :: int
+
+instance proof
+  fix k l :: int and m n :: nat
+  show \<open>- k = NOT (k - 1)\<close>
+    by (simp add: not_int_def)
+  show \<open>bit (k AND l) n \<longleftrightarrow> bit k n \<and> bit l n\<close>
+    by (fact bit_and_int_iff)
+  show \<open>bit (k OR l) n \<longleftrightarrow> bit k n \<or> bit l n\<close>
+    by (fact bit_or_int_iff)
+  show \<open>bit (k XOR l) n \<longleftrightarrow> bit k n \<noteq> bit l n\<close>
+    by (fact bit_xor_int_iff)
+  show \<open>bit (unset_bit m k) n \<longleftrightarrow> bit k n \<and> m \<noteq> n\<close>
+  proof -
+    have \<open>unset_bit m k = k AND NOT (push_bit m 1)\<close>
+      by (simp add: unset_bit_int_def)
+    also have \<open>NOT (push_bit m 1 :: int) = - (push_bit m 1 + 1)\<close>
+      by (simp add: not_int_def)
+    finally show ?thesis by (simp only: bit_simps bit_and_int_iff)
+      (auto simp add: bit_simps bit_not_int_iff' push_bit_int_def)
+  qed
+qed (simp_all add: bit_not_int_iff mask_int_def set_bit_int_def flip_bit_int_def
+  push_bit_int_def drop_bit_int_def take_bit_int_def)
+
+end
+
+lemma bit_push_bit_iff_int:
+  \<open>bit (push_bit m k) n \<longleftrightarrow> m \<le> n \<and> bit k (n - m)\<close> for k :: int
+  by (auto simp add: bit_push_bit_iff)
+
+lemma take_bit_nonnegative [simp]:
+  \<open>take_bit n k \<ge> 0\<close> for k :: int
+  by (simp add: take_bit_eq_mod)
+
+lemma not_take_bit_negative [simp]:
+  \<open>\<not> take_bit n k < 0\<close> for k :: int
+  by (simp add: not_less)
+
+lemma take_bit_int_less_exp [simp]:
+  \<open>take_bit n k < 2 ^ n\<close> for k :: int
+  by (simp add: take_bit_eq_mod)
+
+lemma take_bit_int_eq_self_iff:
+  \<open>take_bit n k = k \<longleftrightarrow> 0 \<le> k \<and> k < 2 ^ n\<close> (is \<open>?P \<longleftrightarrow> ?Q\<close>)
+  for k :: int
+proof
+  assume ?P
+  moreover note take_bit_int_less_exp [of n k] take_bit_nonnegative [of n k]
+  ultimately show ?Q
+    by simp
+next
+  assume ?Q
+  then show ?P
+    by (simp add: take_bit_eq_mod)
+qed
+
+lemma take_bit_int_eq_self:
+  \<open>take_bit n k = k\<close> if \<open>0 \<le> k\<close> \<open>k < 2 ^ n\<close> for k :: int
+  using that by (simp add: take_bit_int_eq_self_iff)
+
+lemma mask_half_int:
+  \<open>mask n div 2 = (mask (n - 1) :: int)\<close>
+  by (cases n) (simp_all add: mask_eq_exp_minus_1 algebra_simps)
+
+lemma mask_nonnegative_int [simp]:
+  \<open>mask n \<ge> (0::int)\<close>
+  by (simp add: mask_eq_exp_minus_1)
+
+lemma not_mask_negative_int [simp]:
+  \<open>\<not> mask n < (0::int)\<close>
+  by (simp add: not_less)
+
+lemma not_nonnegative_int_iff [simp]:
+  \<open>NOT k \<ge> 0 \<longleftrightarrow> k < 0\<close> for k :: int
+  by (simp add: not_int_def)
+
+lemma not_negative_int_iff [simp]:
+  \<open>NOT k < 0 \<longleftrightarrow> k \<ge> 0\<close> for k :: int
+  by (subst Not_eq_iff [symmetric]) (simp add: not_less not_le)
+
+lemma and_nonnegative_int_iff [simp]:
+  \<open>k AND l \<ge> 0 \<longleftrightarrow> k \<ge> 0 \<or> l \<ge> 0\<close> for k l :: int
+proof (induction k arbitrary: l rule: int_bit_induct)
+  case zero
+  then show ?case
+    by simp
+next
+  case minus
+  then show ?case
+    by simp
+next
+  case (even k)
+  then show ?case
+    using and_int_rec [of \<open>k * 2\<close> l]
+    by (simp add: pos_imp_zdiv_nonneg_iff zero_le_mult_iff)
+next
+  case (odd k)
+  from odd have \<open>0 \<le> k AND l div 2 \<longleftrightarrow> 0 \<le> k \<or> 0 \<le> l div 2\<close>
+    by simp
+  then have \<open>0 \<le> (1 + k * 2) div 2 AND l div 2 \<longleftrightarrow> 0 \<le> (1 + k * 2) div 2 \<or> 0 \<le> l div 2\<close>
+    by simp
+  with and_int_rec [of \<open>1 + k * 2\<close> l]
+  show ?case
+    by (auto simp add: zero_le_mult_iff not_le)
+qed
+
+lemma and_negative_int_iff [simp]:
+  \<open>k AND l < 0 \<longleftrightarrow> k < 0 \<and> l < 0\<close> for k l :: int
+  by (subst Not_eq_iff [symmetric]) (simp add: not_less)
+
+lemma and_less_eq:
+  \<open>k AND l \<le> k\<close> if \<open>l < 0\<close> for k l :: int
+using that proof (induction k arbitrary: l rule: int_bit_induct)
+  case zero
+  then show ?case
+    by simp
+next
+  case minus
+  then show ?case
+    by simp
+next
+  case (even k)
+  from even.IH [of \<open>l div 2\<close>] even.hyps even.prems
+  show ?case
+    by (simp add: and_int_rec [of _ l])
+next
+  case (odd k)
+  from odd.IH [of \<open>l div 2\<close>] odd.hyps odd.prems
+  show ?case
+    by (simp add: and_int_rec [of _ l]) linarith
+qed
+
+lemma or_nonnegative_int_iff [simp]:
+  \<open>k OR l \<ge> 0 \<longleftrightarrow> k \<ge> 0 \<and> l \<ge> 0\<close> for k l :: int
+  by (simp only: or_eq_not_not_and not_nonnegative_int_iff) simp
+
+lemma or_negative_int_iff [simp]:
+  \<open>k OR l < 0 \<longleftrightarrow> k < 0 \<or> l < 0\<close> for k l :: int
+  by (subst Not_eq_iff [symmetric]) (simp add: not_less)
+
+lemma or_greater_eq:
+  \<open>k OR l \<ge> k\<close> if \<open>l \<ge> 0\<close> for k l :: int
+using that proof (induction k arbitrary: l rule: int_bit_induct)
+  case zero
+  then show ?case
+    by simp
+next
+  case minus
+  then show ?case
+    by simp
+next
+  case (even k)
+  from even.IH [of \<open>l div 2\<close>] even.hyps even.prems
+  show ?case
+    by (simp add: or_int_rec [of _ l]) linarith
+next
+  case (odd k)
+  from odd.IH [of \<open>l div 2\<close>] odd.hyps odd.prems
+  show ?case
+    by (simp add: or_int_rec [of _ l])
+qed
+
+lemma xor_nonnegative_int_iff [simp]:
+  \<open>k XOR l \<ge> 0 \<longleftrightarrow> (k \<ge> 0 \<longleftrightarrow> l \<ge> 0)\<close> for k l :: int
+  by (simp only: bit.xor_def or_nonnegative_int_iff) auto
+
+lemma xor_negative_int_iff [simp]:
+  \<open>k XOR l < 0 \<longleftrightarrow> (k < 0) \<noteq> (l < 0)\<close> for k l :: int
+  by (subst Not_eq_iff [symmetric]) (auto simp add: not_less)
+
+lemma OR_upper: \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+  fixes x y :: int
+  assumes \<open>0 \<le> x\<close> \<open>x < 2 ^ n\<close> \<open>y < 2 ^ n\<close>
+  shows \<open>x OR y < 2 ^ n\<close>
+using assms proof (induction x arbitrary: y n rule: int_bit_induct)
+  case zero
+  then show ?case
+    by simp
+next
+  case minus
+  then show ?case
+    by simp
+next
+  case (even x)
+  from even.IH [of \<open>n - 1\<close> \<open>y div 2\<close>] even.prems even.hyps
+  show ?case 
+    by (cases n) (auto simp add: or_int_rec [of \<open>_ * 2\<close>] elim: oddE)
+next
+  case (odd x)
+  from odd.IH [of \<open>n - 1\<close> \<open>y div 2\<close>] odd.prems odd.hyps
+  show ?case
+    by (cases n) (auto simp add: or_int_rec [of \<open>1 + _ * 2\<close>], linarith)
+qed
+
+lemma XOR_upper: \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+  fixes x y :: int
+  assumes \<open>0 \<le> x\<close> \<open>x < 2 ^ n\<close> \<open>y < 2 ^ n\<close>
+  shows \<open>x XOR y < 2 ^ n\<close>
+using assms proof (induction x arbitrary: y n rule: int_bit_induct)
+  case zero
+  then show ?case
+    by simp
+next
+  case minus
+  then show ?case
+    by simp
+next
+  case (even x)
+  from even.IH [of \<open>n - 1\<close> \<open>y div 2\<close>] even.prems even.hyps
+  show ?case 
+    by (cases n) (auto simp add: xor_int_rec [of \<open>_ * 2\<close>] elim: oddE)
+next
+  case (odd x)
+  from odd.IH [of \<open>n - 1\<close> \<open>y div 2\<close>] odd.prems odd.hyps
+  show ?case
+    by (cases n) (auto simp add: xor_int_rec [of \<open>1 + _ * 2\<close>])
+qed
+
+lemma AND_lower [simp]: \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+  fixes x y :: int
+  assumes \<open>0 \<le> x\<close>
+  shows \<open>0 \<le> x AND y\<close>
+  using assms by simp
+
+lemma OR_lower [simp]: \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+  fixes x y :: int
+  assumes \<open>0 \<le> x\<close> \<open>0 \<le> y\<close>
+  shows \<open>0 \<le> x OR y\<close>
+  using assms by simp
+
+lemma XOR_lower [simp]: \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+  fixes x y :: int
+  assumes \<open>0 \<le> x\<close> \<open>0 \<le> y\<close>
+  shows \<open>0 \<le> x XOR y\<close>
+  using assms by simp
+
+lemma AND_upper1 [simp]: \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+  fixes x y :: int
+  assumes \<open>0 \<le> x\<close>
+  shows \<open>x AND y \<le> x\<close>
+using assms proof (induction x arbitrary: y rule: int_bit_induct)
+  case (odd k)
+  then have \<open>k AND y div 2 \<le> k\<close>
+    by simp
+  then show ?case 
+    by (simp add: and_int_rec [of \<open>1 + _ * 2\<close>])
+qed (simp_all add: and_int_rec [of \<open>_ * 2\<close>])
+
+lemmas AND_upper1' [simp] = order_trans [OF AND_upper1] \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+lemmas AND_upper1'' [simp] = order_le_less_trans [OF AND_upper1] \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+
+lemma AND_upper2 [simp]: \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+  fixes x y :: int
+  assumes \<open>0 \<le> y\<close>
+  shows \<open>x AND y \<le> y\<close>
+  using assms AND_upper1 [of y x] by (simp add: ac_simps)
+
+lemmas AND_upper2' [simp] = order_trans [OF AND_upper2] \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+lemmas AND_upper2'' [simp] = order_le_less_trans [OF AND_upper2] \<^marker>\<open>contributor \<open>Stefan Berghofer\<close>\<close>
+
+lemma plus_and_or: \<open>(x AND y) + (x OR y) = x + y\<close> for x y :: int
+proof (induction x arbitrary: y rule: int_bit_induct)
+  case zero
+  then show ?case
+    by simp
+next
+  case minus
+  then show ?case
+    by simp
+next
+  case (even x)
+  from even.IH [of \<open>y div 2\<close>]
+  show ?case
+    by (auto simp add: and_int_rec [of _ y] or_int_rec [of _ y] elim: oddE)
+next
+  case (odd x)
+  from odd.IH [of \<open>y div 2\<close>]
+  show ?case
+    by (auto simp add: and_int_rec [of _ y] or_int_rec [of _ y] elim: oddE)
+qed
+
+lemma push_bit_minus_one:
+  "push_bit n (- 1 :: int) = - (2 ^ n)"
+  by (simp add: push_bit_eq_mult)
+
+lemma minus_1_div_exp_eq_int:
+  \<open>- 1 div (2 :: int) ^ n = - 1\<close>
+  by (induction n) (use div_exp_eq [symmetric, of \<open>- 1 :: int\<close> 1] in \<open>simp_all add: ac_simps\<close>)
+
+lemma drop_bit_minus_one [simp]:
+  \<open>drop_bit n (- 1 :: int) = - 1\<close>
+  by (simp add: drop_bit_eq_div minus_1_div_exp_eq_int)
+
+lemma take_bit_Suc_from_most:
+  \<open>take_bit (Suc n) k = 2 ^ n * of_bool (bit k n) + take_bit n k\<close> for k :: int
+  by (simp only: take_bit_eq_mod power_Suc2) (simp_all add: bit_iff_odd odd_iff_mod_2_eq_one zmod_zmult2_eq)
+
+lemma take_bit_minus:
+  \<open>take_bit n (- take_bit n k) = take_bit n (- k)\<close>
+    for k :: int
+  by (simp add: take_bit_eq_mod mod_minus_eq)
+
+lemma take_bit_diff:
+  \<open>take_bit n (take_bit n k - take_bit n l) = take_bit n (k - l)\<close>
+    for k l :: int
+  by (simp add: take_bit_eq_mod mod_diff_eq)
+
+lemma bit_imp_take_bit_positive:
+  \<open>0 < take_bit m k\<close> if \<open>n < m\<close> and \<open>bit k n\<close> for k :: int
+proof (rule ccontr)
+  assume \<open>\<not> 0 < take_bit m k\<close>
+  then have \<open>take_bit m k = 0\<close>
+    by (auto simp add: not_less intro: order_antisym)
+  then have \<open>bit (take_bit m k) n = bit 0 n\<close>
+    by simp
+  with that show False
+    by (simp add: bit_take_bit_iff)
+qed
+
+lemma take_bit_mult:
+  \<open>take_bit n (take_bit n k * take_bit n l) = take_bit n (k * l)\<close>
+  for k l :: int
+  by (simp add: take_bit_eq_mod mod_mult_eq)
+
+lemma (in ring_1) of_nat_nat_take_bit_eq [simp]:
+  \<open>of_nat (nat (take_bit n k)) = of_int (take_bit n k)\<close>
+  by simp
+
+lemma take_bit_minus_small_eq:
+  \<open>take_bit n (- k) = 2 ^ n - k\<close> if \<open>0 < k\<close> \<open>k \<le> 2 ^ n\<close> for k :: int
+proof -
+  define m where \<open>m = nat k\<close>
+  with that have \<open>k = int m\<close> and \<open>0 < m\<close> and \<open>m \<le> 2 ^ n\<close>
+    by simp_all
+  have \<open>(2 ^ n - m) mod 2 ^ n = 2 ^ n - m\<close>
+    using \<open>0 < m\<close> by simp
+  then have \<open>int ((2 ^ n - m) mod 2 ^ n) = int (2 ^ n - m)\<close>
+    by simp
+  then have \<open>(2 ^ n - int m) mod 2 ^ n = 2 ^ n - int m\<close>
+    using \<open>m \<le> 2 ^ n\<close> by (simp only: of_nat_mod of_nat_diff) simp
+  with \<open>k = int m\<close> have \<open>(2 ^ n - k) mod 2 ^ n = 2 ^ n - k\<close>
+    by simp
+  then show ?thesis
+    by (simp add: take_bit_eq_mod)
+qed
+
+lemma drop_bit_push_bit_int:
+  \<open>drop_bit m (push_bit n k) = drop_bit (m - n) (push_bit (n - m) k)\<close> for k :: int
+  by (cases \<open>m \<le> n\<close>) (auto simp add: mult.left_commute [of _ \<open>2 ^ n\<close>] mult.commute [of _ \<open>2 ^ n\<close>] mult.assoc
+    mult.commute [of k] drop_bit_eq_div push_bit_eq_mult not_le power_add dest!: le_Suc_ex less_imp_Suc_add)
+
+lemma push_bit_nonnegative_int_iff [simp]:
+  \<open>push_bit n k \<ge> 0 \<longleftrightarrow> k \<ge> 0\<close> for k :: int
+  by (simp add: push_bit_eq_mult zero_le_mult_iff power_le_zero_eq)
+
+lemma push_bit_negative_int_iff [simp]:
+  \<open>push_bit n k < 0 \<longleftrightarrow> k < 0\<close> for k :: int
+  by (subst Not_eq_iff [symmetric]) (simp add: not_less)
+
+lemma drop_bit_nonnegative_int_iff [simp]:
+  \<open>drop_bit n k \<ge> 0 \<longleftrightarrow> k \<ge> 0\<close> for k :: int
+  by (induction n) (auto simp add: drop_bit_Suc drop_bit_half)
+
+lemma drop_bit_negative_int_iff [simp]:
+  \<open>drop_bit n k < 0 \<longleftrightarrow> k < 0\<close> for k :: int
+  by (subst Not_eq_iff [symmetric]) (simp add: not_less)
+
+lemma set_bit_nonnegative_int_iff [simp]:
+  \<open>set_bit n k \<ge> 0 \<longleftrightarrow> k \<ge> 0\<close> for k :: int
+  by (simp add: set_bit_def)
+
+lemma set_bit_negative_int_iff [simp]:
+  \<open>set_bit n k < 0 \<longleftrightarrow> k < 0\<close> for k :: int
+  by (simp add: set_bit_def)
+
+lemma unset_bit_nonnegative_int_iff [simp]:
+  \<open>unset_bit n k \<ge> 0 \<longleftrightarrow> k \<ge> 0\<close> for k :: int
+  by (simp add: unset_bit_def)
+
+lemma unset_bit_negative_int_iff [simp]:
+  \<open>unset_bit n k < 0 \<longleftrightarrow> k < 0\<close> for k :: int
+  by (simp add: unset_bit_def)
+
+lemma flip_bit_nonnegative_int_iff [simp]:
+  \<open>flip_bit n k \<ge> 0 \<longleftrightarrow> k \<ge> 0\<close> for k :: int
+  by (simp add: flip_bit_def)
+
+lemma flip_bit_negative_int_iff [simp]:
+  \<open>flip_bit n k < 0 \<longleftrightarrow> k < 0\<close> for k :: int
+  by (simp add: flip_bit_def)
+
+lemma set_bit_greater_eq:
+  \<open>set_bit n k \<ge> k\<close> for k :: int
+  by (simp add: set_bit_def or_greater_eq)
+
+lemma unset_bit_less_eq:
+  \<open>unset_bit n k \<le> k\<close> for k :: int
+  by (simp add: unset_bit_def and_less_eq)
+
+lemma set_bit_eq:
+  \<open>set_bit n k = k + of_bool (\<not> bit k n) * 2 ^ n\<close> for k :: int
+proof (rule bit_eqI)
+  fix m
+  show \<open>bit (set_bit n k) m \<longleftrightarrow> bit (k + of_bool (\<not> bit k n) * 2 ^ n) m\<close>
+  proof (cases \<open>m = n\<close>)
+    case True
+    then show ?thesis
+      apply (simp add: bit_set_bit_iff)
+      apply (simp add: bit_iff_odd div_plus_div_distrib_dvd_right)
+      done
+  next
+    case False
+    then show ?thesis
+      apply (clarsimp simp add: bit_set_bit_iff)
+      apply (subst disjunctive_add)
+      apply (clarsimp simp add: bit_exp_iff)
+      apply (clarsimp simp add: bit_or_iff bit_exp_iff)
+      done
+  qed
+qed
+
+lemma unset_bit_eq:
+  \<open>unset_bit n k = k - of_bool (bit k n) * 2 ^ n\<close> for k :: int
+proof (rule bit_eqI)
+  fix m
+  show \<open>bit (unset_bit n k) m \<longleftrightarrow> bit (k - of_bool (bit k n) * 2 ^ n) m\<close>
+  proof (cases \<open>m = n\<close>)
+    case True
+    then show ?thesis
+      apply (simp add: bit_unset_bit_iff)
+      apply (simp add: bit_iff_odd)
+      using div_plus_div_distrib_dvd_right [of \<open>2 ^ n\<close> \<open>- (2 ^ n)\<close> k]
+      apply (simp add: dvd_neg_div)
+      done
+  next
+    case False
+    then show ?thesis
+      apply (clarsimp simp add: bit_unset_bit_iff)
+      apply (subst disjunctive_diff)
+      apply (clarsimp simp add: bit_exp_iff)
+      apply (clarsimp simp add: bit_and_iff bit_not_iff bit_exp_iff)
+      done
+  qed
+qed
+
+lemma and_int_unfold [code]:
+  \<open>k AND l = (if k = 0 \<or> l = 0 then 0 else if k = - 1 then l else if l = - 1 then k
+    else (k mod 2) * (l mod 2) + 2 * ((k div 2) AND (l div 2)))\<close> for k l :: int
+  by (auto simp add: and_int_rec [of k l] zmult_eq_1_iff elim: oddE)
+
+lemma or_int_unfold [code]:
+  \<open>k OR l = (if k = - 1 \<or> l = - 1 then - 1 else if k = 0 then l else if l = 0 then k
+    else max (k mod 2) (l mod 2) + 2 * ((k div 2) OR (l div 2)))\<close> for k l :: int
+  by (auto simp add: or_int_rec [of k l] elim: oddE)
+
+lemma xor_int_unfold [code]:
+  \<open>k XOR l = (if k = - 1 then NOT l else if l = - 1 then NOT k else if k = 0 then l else if l = 0 then k
+    else \<bar>k mod 2 - l mod 2\<bar> + 2 * ((k div 2) XOR (l div 2)))\<close> for k l :: int
+  by (auto simp add: xor_int_rec [of k l] not_int_def elim!: oddE)
+
+
+subsection \<open>Instance \<^typ>\<open>nat\<close>\<close>
+
+instantiation nat :: semiring_bit_operations
+begin
+
+definition and_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> nat\<close>
+  where \<open>m AND n = nat (int m AND int n)\<close> for m n :: nat
+
+definition or_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> nat\<close>
+  where \<open>m OR n = nat (int m OR int n)\<close> for m n :: nat
+
+definition xor_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> nat\<close>
+  where \<open>m XOR n = nat (int m XOR int n)\<close> for m n :: nat
+
+definition mask_nat :: \<open>nat \<Rightarrow> nat\<close>
+  where \<open>mask n = (2 :: nat) ^ n - 1\<close>
+
+definition push_bit_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> nat\<close>
+  where \<open>push_bit_nat n m = m * 2 ^ n\<close>
+
+definition drop_bit_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> nat\<close>
+  where \<open>drop_bit_nat n m = m div 2 ^ n\<close>
+
+definition take_bit_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> nat\<close>
+  where \<open>take_bit_nat n m = m mod 2 ^ n\<close>
+
+definition set_bit_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> nat\<close>
+  where \<open>set_bit m n = n OR push_bit m 1\<close> for m n :: nat
+
+definition unset_bit_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> nat\<close>
+  where \<open>unset_bit m n = nat (unset_bit m (int n))\<close> for m n :: nat
+
+definition flip_bit_nat :: \<open>nat \<Rightarrow> nat \<Rightarrow> nat\<close>
+  where \<open>flip_bit m n = n XOR push_bit m 1\<close> for m n :: nat
+
+instance proof
+  fix m n q :: nat
+  show \<open>bit (m AND n) q \<longleftrightarrow> bit m q \<and> bit n q\<close>
+    by (simp add: and_nat_def bit_simps)
+  show \<open>bit (m OR n) q \<longleftrightarrow> bit m q \<or> bit n q\<close>
+    by (simp add: or_nat_def bit_simps)
+  show \<open>bit (m XOR n) q \<longleftrightarrow> bit m q \<noteq> bit n q\<close>
+    by (simp add: xor_nat_def bit_simps)
+  show \<open>bit (unset_bit m n) q \<longleftrightarrow> bit n q \<and> m \<noteq> q\<close>
+    by (simp add: unset_bit_nat_def bit_simps)
+qed (simp_all add: mask_nat_def set_bit_nat_def flip_bit_nat_def push_bit_nat_def drop_bit_nat_def take_bit_nat_def)
+
+end
+
+lemma take_bit_nat_less_exp [simp]:
+  \<open>take_bit n m < 2 ^ n\<close> for n m ::nat 
+  by (simp add: take_bit_eq_mod)
+
+lemma take_bit_nat_eq_self_iff:
+  \<open>take_bit n m = m \<longleftrightarrow> m < 2 ^ n\<close> (is \<open>?P \<longleftrightarrow> ?Q\<close>)
+  for n m :: nat
+proof
+  assume ?P
+  moreover note take_bit_nat_less_exp [of n m]
+  ultimately show ?Q
+    by simp
+next
+  assume ?Q
+  then show ?P
+    by (simp add: take_bit_eq_mod)
+qed
+
+lemma take_bit_nat_eq_self:
+  \<open>take_bit n m = m\<close> if \<open>m < 2 ^ n\<close> for m n :: nat
+  using that by (simp add: take_bit_nat_eq_self_iff)
+
+lemma take_bit_nat_less_eq_self [simp]:
+  \<open>take_bit n m \<le> m\<close> for n m :: nat
+  by (simp add: take_bit_eq_mod)
+
+lemma take_bit_nat_less_self_iff:
+  \<open>take_bit n m < m \<longleftrightarrow> 2 ^ n \<le> m\<close> (is \<open>?P \<longleftrightarrow> ?Q\<close>)
+  for m n :: nat
+proof
+  assume ?P
+  then have \<open>take_bit n m \<noteq> m\<close>
+    by simp
+  then show \<open>?Q\<close>
+    by (simp add: take_bit_nat_eq_self_iff)
+next
+  have \<open>take_bit n m < 2 ^ n\<close>
+    by (fact take_bit_nat_less_exp)
+  also assume ?Q
+  finally show ?P .
+qed
+
+lemma bit_push_bit_iff_nat:
+  \<open>bit (push_bit m q) n \<longleftrightarrow> m \<le> n \<and> bit q (n - m)\<close> for q :: nat
+  by (auto simp add: bit_push_bit_iff)
+
+lemma and_nat_rec:
+  \<open>m AND n = of_bool (odd m \<and> odd n) + 2 * ((m div 2) AND (n div 2))\<close> for m n :: nat
+  apply (simp add: and_nat_def and_int_rec [of \<open>int m\<close> \<open>int n\<close>] zdiv_int nat_add_distrib nat_mult_distrib)
+  apply (subst nat_add_distrib)
+    apply auto
+  done
+
+lemma or_nat_rec:
+  \<open>m OR n = of_bool (odd m \<or> odd n) + 2 * ((m div 2) OR (n div 2))\<close> for m n :: nat
+  apply (simp add: or_nat_def or_int_rec [of \<open>int m\<close> \<open>int n\<close>] zdiv_int nat_add_distrib nat_mult_distrib)
+  apply (subst nat_add_distrib)
+    apply auto
+  done
+
+lemma xor_nat_rec:
+  \<open>m XOR n = of_bool (odd m \<noteq> odd n) + 2 * ((m div 2) XOR (n div 2))\<close> for m n :: nat
+  apply (simp add: xor_nat_def xor_int_rec [of \<open>int m\<close> \<open>int n\<close>] zdiv_int nat_add_distrib nat_mult_distrib)
+  apply (subst nat_add_distrib)
+    apply auto
+  done
+
+lemma Suc_0_and_eq [simp]:
+  \<open>Suc 0 AND n = n mod 2\<close>
+  using one_and_eq [of n] by simp
+
+lemma and_Suc_0_eq [simp]:
+  \<open>n AND Suc 0 = n mod 2\<close>
+  using and_one_eq [of n] by simp
+
+lemma Suc_0_or_eq:
+  \<open>Suc 0 OR n = n + of_bool (even n)\<close>
+  using one_or_eq [of n] by simp
+
+lemma or_Suc_0_eq:
+  \<open>n OR Suc 0 = n + of_bool (even n)\<close>
+  using or_one_eq [of n] by simp
+
+lemma Suc_0_xor_eq:
+  \<open>Suc 0 XOR n = n + of_bool (even n) - of_bool (odd n)\<close>
+  using one_xor_eq [of n] by simp
+
+lemma xor_Suc_0_eq:
+  \<open>n XOR Suc 0 = n + of_bool (even n) - of_bool (odd n)\<close>
+  using xor_one_eq [of n] by simp
+
+lemma and_nat_unfold [code]:
+  \<open>m AND n = (if m = 0 \<or> n = 0 then 0 else (m mod 2) * (n mod 2) + 2 * ((m div 2) AND (n div 2)))\<close>
+    for m n :: nat
+  by (auto simp add: and_nat_rec [of m n] elim: oddE)
+
+lemma or_nat_unfold [code]:
+  \<open>m OR n = (if m = 0 then n else if n = 0 then m
+    else max (m mod 2) (n mod 2) + 2 * ((m div 2) OR (n div 2)))\<close> for m n :: nat
+  by (auto simp add: or_nat_rec [of m n] elim: oddE)
+
+lemma xor_nat_unfold [code]:
+  \<open>m XOR n = (if m = 0 then n else if n = 0 then m
+    else (m mod 2 + n mod 2) mod 2 + 2 * ((m div 2) XOR (n div 2)))\<close> for m n :: nat
+  by (auto simp add: xor_nat_rec [of m n] elim!: oddE)
+
+lemma [code]:
+  \<open>unset_bit 0 m = 2 * (m div 2)\<close>
+  \<open>unset_bit (Suc n) m = m mod 2 + 2 * unset_bit n (m div 2)\<close>
+  by (simp_all add: unset_bit_Suc)
+  
+
+subsection \<open>Common algebraic structure\<close>
+
+class unique_euclidean_semiring_with_bit_operations =
+  unique_euclidean_semiring_with_nat + semiring_bit_operations
+begin
+
+lemma take_bit_of_exp [simp]:
+  \<open>take_bit m (2 ^ n) = of_bool (n < m) * 2 ^ n\<close>
+  by (simp add: take_bit_eq_mod exp_mod_exp)
+
+lemma take_bit_of_2 [simp]:
+  \<open>take_bit n 2 = of_bool (2 \<le> n) * 2\<close>
+  using take_bit_of_exp [of n 1] by simp
+
+lemma take_bit_of_mask:
+  \<open>take_bit m (2 ^ n - 1) = 2 ^ min m n - 1\<close>
+  by (simp add: take_bit_eq_mod mask_mod_exp)
+
+lemma push_bit_eq_0_iff [simp]:
+  "push_bit n a = 0 \<longleftrightarrow> a = 0"
+  by (simp add: push_bit_eq_mult)
+
+lemma take_bit_add:
+  "take_bit n (take_bit n a + take_bit n b) = take_bit n (a + b)"
+  by (simp add: take_bit_eq_mod mod_simps)
+
+lemma take_bit_of_1_eq_0_iff [simp]:
+  "take_bit n 1 = 0 \<longleftrightarrow> n = 0"
+  by (simp add: take_bit_eq_mod)
+
+lemma take_bit_Suc_1 [simp]:
+  \<open>take_bit (Suc n) 1 = 1\<close>
+  by (simp add: take_bit_Suc)
+
+lemma take_bit_Suc_bit0 [simp]:
+  \<open>take_bit (Suc n) (numeral (Num.Bit0 k)) = take_bit n (numeral k) * 2\<close>
+  by (simp add: take_bit_Suc numeral_Bit0_div_2)
+
+lemma take_bit_Suc_bit1 [simp]:
+  \<open>take_bit (Suc n) (numeral (Num.Bit1 k)) = take_bit n (numeral k) * 2 + 1\<close>
+  by (simp add: take_bit_Suc numeral_Bit1_div_2 mod_2_eq_odd)
+
+lemma take_bit_numeral_1 [simp]:
+  \<open>take_bit (numeral l) 1 = 1\<close>
+  by (simp add: take_bit_rec [of \<open>numeral l\<close> 1])
+
+lemma take_bit_numeral_bit0 [simp]:
+  \<open>take_bit (numeral l) (numeral (Num.Bit0 k)) = take_bit (pred_numeral l) (numeral k) * 2\<close>
+  by (simp add: take_bit_rec numeral_Bit0_div_2)
+
+lemma take_bit_numeral_bit1 [simp]:
+  \<open>take_bit (numeral l) (numeral (Num.Bit1 k)) = take_bit (pred_numeral l) (numeral k) * 2 + 1\<close>
+  by (simp add: take_bit_rec numeral_Bit1_div_2 mod_2_eq_odd)
+
+lemma drop_bit_Suc_bit0 [simp]:
+  \<open>drop_bit (Suc n) (numeral (Num.Bit0 k)) = drop_bit n (numeral k)\<close>
+  by (simp add: drop_bit_Suc numeral_Bit0_div_2)
+
+lemma drop_bit_Suc_bit1 [simp]:
+  \<open>drop_bit (Suc n) (numeral (Num.Bit1 k)) = drop_bit n (numeral k)\<close>
+  by (simp add: drop_bit_Suc numeral_Bit1_div_2)
+
+lemma drop_bit_numeral_bit0 [simp]:
+  \<open>drop_bit (numeral l) (numeral (Num.Bit0 k)) = drop_bit (pred_numeral l) (numeral k)\<close>
+  by (simp add: drop_bit_rec numeral_Bit0_div_2)
+
+lemma drop_bit_numeral_bit1 [simp]:
+  \<open>drop_bit (numeral l) (numeral (Num.Bit1 k)) = drop_bit (pred_numeral l) (numeral k)\<close>
+  by (simp add: drop_bit_rec numeral_Bit1_div_2)
+
+lemma drop_bit_of_nat:
+  "drop_bit n (of_nat m) = of_nat (drop_bit n m)"
+  by (simp add: drop_bit_eq_div Bit_Operations.drop_bit_eq_div of_nat_div [of m "2 ^ n"])
+
+lemma bit_of_nat_iff_bit [bit_simps]:
+  \<open>bit (of_nat m) n \<longleftrightarrow> bit m n\<close>
+proof -
+  have \<open>even (m div 2 ^ n) \<longleftrightarrow> even (of_nat (m div 2 ^ n))\<close>
+    by simp
+  also have \<open>of_nat (m div 2 ^ n) = of_nat m div of_nat (2 ^ n)\<close>
+    by (simp add: of_nat_div)
+  finally show ?thesis
+    by (simp add: bit_iff_odd semiring_bits_class.bit_iff_odd)
+qed
+
+lemma of_nat_drop_bit:
+  \<open>of_nat (drop_bit m n) = drop_bit m (of_nat n)\<close>
+  by (simp add: drop_bit_eq_div Bit_Operations.drop_bit_eq_div of_nat_div)
+
+lemma bit_push_bit_iff_of_nat_iff [bit_simps]:
+  \<open>bit (push_bit m (of_nat r)) n \<longleftrightarrow> m \<le> n \<and> bit (of_nat r) (n - m)\<close>
+  by (auto simp add: bit_push_bit_iff)
+
+lemma take_bit_sum:
+  "take_bit n a = (\<Sum>k = 0..<n. push_bit k (of_bool (bit a k)))"
+  for n :: nat
+proof (induction n arbitrary: a)
+  case 0
+  then show ?case
+    by simp
+next
+  case (Suc n)
+  have "(\<Sum>k = 0..<Suc n. push_bit k (of_bool (bit a k))) = 
+    of_bool (odd a) + (\<Sum>k = Suc 0..<Suc n. push_bit k (of_bool (bit a k)))"
+    by (simp add: sum.atLeast_Suc_lessThan ac_simps)
+  also have "(\<Sum>k = Suc 0..<Suc n. push_bit k (of_bool (bit a k)))
+    = (\<Sum>k = 0..<n. push_bit k (of_bool (bit (a div 2) k))) * 2"
+    by (simp only: sum.atLeast_Suc_lessThan_Suc_shift) (simp add: sum_distrib_right push_bit_double drop_bit_Suc bit_Suc)
+  finally show ?case
+    using Suc [of "a div 2"] by (simp add: ac_simps take_bit_Suc mod_2_eq_odd)
+qed
+
+end
+
+instance nat :: unique_euclidean_semiring_with_bit_operations ..
+
+instance int :: unique_euclidean_semiring_with_bit_operations ..
+
+
+subsection \<open>More properties\<close>
+
+lemma take_bit_eq_mask_iff:
+  \<open>take_bit n k = mask n \<longleftrightarrow> take_bit n (k + 1) = 0\<close> (is \<open>?P \<longleftrightarrow> ?Q\<close>)
+  for k :: int
+proof
+  assume ?P
+  then have \<open>take_bit n (take_bit n k + take_bit n 1) = 0\<close>
+    by (simp add: mask_eq_exp_minus_1 take_bit_eq_0_iff)
+  then show ?Q
+    by (simp only: take_bit_add)
+next
+  assume ?Q
+  then have \<open>take_bit n (k + 1) - 1 = - 1\<close>
+    by simp
+  then have \<open>take_bit n (take_bit n (k + 1) - 1) = take_bit n (- 1)\<close>
+    by simp
+  moreover have \<open>take_bit n (take_bit n (k + 1) - 1) = take_bit n k\<close>
+    by (simp add: take_bit_eq_mod mod_simps)
+  ultimately show ?P
+    by (simp add: take_bit_minus_one_eq_mask)
+qed
+
+lemma take_bit_eq_mask_iff_exp_dvd:
+  \<open>take_bit n k = mask n \<longleftrightarrow> 2 ^ n dvd k + 1\<close>
+  for k :: int
+  by (simp add: take_bit_eq_mask_iff flip: take_bit_eq_0_iff)
+
+context ring_bit_operations
+begin
+
+lemma even_of_int_iff:
+  \<open>even (of_int k) \<longleftrightarrow> even k\<close>
+  by (induction k rule: int_bit_induct) simp_all
+
+lemma bit_of_int_iff [bit_simps]:
+  \<open>bit (of_int k) n \<longleftrightarrow> (2::'a) ^ n \<noteq> 0 \<and> bit k n\<close>
+proof (cases \<open>(2::'a) ^ n = 0\<close>)
+  case True
+  then show ?thesis
+    by (simp add: exp_eq_0_imp_not_bit)
+next
+  case False
+  then have \<open>bit (of_int k) n \<longleftrightarrow> bit k n\<close>
+  proof (induction k arbitrary: n rule: int_bit_induct)
+    case zero
+    then show ?case
+      by simp
+  next
+    case minus
+    then show ?case
+      by simp
+  next
+    case (even k)
+    then show ?case
+      using bit_double_iff [of \<open>of_int k\<close> n] Bit_Operations.bit_double_iff [of k n]
+      by (cases n) (auto simp add: ac_simps dest: mult_not_zero)
+  next
+    case (odd k)
+    then show ?case
+      using bit_double_iff [of \<open>of_int k\<close> n]
+      by (cases n) (auto simp add: ac_simps bit_double_iff even_bit_succ_iff Bit_Operations.bit_Suc dest: mult_not_zero)
+  qed
+  with False show ?thesis
+    by simp
+qed
+
+lemma push_bit_of_int:
+  \<open>push_bit n (of_int k) = of_int (push_bit n k)\<close>
+  by (simp add: push_bit_eq_mult Bit_Operations.push_bit_eq_mult)
+
+lemma of_int_push_bit:
+  \<open>of_int (push_bit n k) = push_bit n (of_int k)\<close>
+  by (simp add: push_bit_eq_mult Bit_Operations.push_bit_eq_mult)
+
+lemma take_bit_of_int:
+  \<open>take_bit n (of_int k) = of_int (take_bit n k)\<close>
+  by (rule bit_eqI) (simp add: bit_take_bit_iff Bit_Operations.bit_take_bit_iff bit_of_int_iff)
+
+lemma of_int_take_bit:
+  \<open>of_int (take_bit n k) = take_bit n (of_int k)\<close>
+  by (rule bit_eqI) (simp add: bit_take_bit_iff Bit_Operations.bit_take_bit_iff bit_of_int_iff)
+
+lemma of_int_not_eq:
+  \<open>of_int (NOT k) = NOT (of_int k)\<close>
+  by (rule bit_eqI) (simp add: bit_not_iff Bit_Operations.bit_not_iff bit_of_int_iff)
+
+lemma of_int_and_eq:
+  \<open>of_int (k AND l) = of_int k AND of_int l\<close>
+  by (rule bit_eqI) (simp add: bit_of_int_iff bit_and_iff Bit_Operations.bit_and_iff)
+
+lemma of_int_or_eq:
+  \<open>of_int (k OR l) = of_int k OR of_int l\<close>
+  by (rule bit_eqI) (simp add: bit_of_int_iff bit_or_iff Bit_Operations.bit_or_iff)
+
+lemma of_int_xor_eq:
+  \<open>of_int (k XOR l) = of_int k XOR of_int l\<close>
+  by (rule bit_eqI) (simp add: bit_of_int_iff bit_xor_iff Bit_Operations.bit_xor_iff)
+
+lemma of_int_mask_eq:
+  \<open>of_int (mask n) = mask n\<close>
+  by (induction n) (simp_all add: mask_Suc_double Bit_Operations.mask_Suc_double of_int_or_eq)
+
+end
+
+lemma take_bit_incr_eq:
+  \<open>take_bit n (k + 1) = 1 + take_bit n k\<close> if \<open>take_bit n k \<noteq> 2 ^ n - 1\<close>
+  for k :: int
+proof -
+  from that have \<open>2 ^ n \<noteq> k mod 2 ^ n + 1\<close>
+    by (simp add: take_bit_eq_mod)
+  moreover have \<open>k mod 2 ^ n < 2 ^ n\<close>
+    by simp
+  ultimately have *: \<open>k mod 2 ^ n + 1 < 2 ^ n\<close>
+    by linarith
+  have \<open>(k + 1) mod 2 ^ n = (k mod 2 ^ n + 1) mod 2 ^ n\<close>
+    by (simp add: mod_simps)
+  also have \<open>\<dots> = k mod 2 ^ n + 1\<close>
+    using * by (simp add: zmod_trivial_iff)
+  finally have \<open>(k + 1) mod 2 ^ n = k mod 2 ^ n + 1\<close> .
+  then show ?thesis
+    by (simp add: take_bit_eq_mod)
+qed
+
+lemma take_bit_decr_eq:
+  \<open>take_bit n (k - 1) = take_bit n k - 1\<close> if \<open>take_bit n k \<noteq> 0\<close>
+  for k :: int
+proof -
+  from that have \<open>k mod 2 ^ n \<noteq> 0\<close>
+    by (simp add: take_bit_eq_mod)
+  moreover have \<open>k mod 2 ^ n \<ge> 0\<close> \<open>k mod 2 ^ n < 2 ^ n\<close>
+    by simp_all
+  ultimately have *: \<open>k mod 2 ^ n > 0\<close>
+    by linarith
+  have \<open>(k - 1) mod 2 ^ n = (k mod 2 ^ n - 1) mod 2 ^ n\<close>
+    by (simp add: mod_simps)
+  also have \<open>\<dots> = k mod 2 ^ n - 1\<close>
+    by (simp add: zmod_trivial_iff)
+      (use \<open>k mod 2 ^ n < 2 ^ n\<close> * in linarith)
+  finally have \<open>(k - 1) mod 2 ^ n = k mod 2 ^ n - 1\<close> .
+  then show ?thesis
+    by (simp add: take_bit_eq_mod)
+qed
+
+lemma take_bit_int_greater_eq:
+  \<open>k + 2 ^ n \<le> take_bit n k\<close> if \<open>k < 0\<close> for k :: int
+proof -
+  have \<open>k + 2 ^ n \<le> take_bit n (k + 2 ^ n)\<close>
+  proof (cases \<open>k > - (2 ^ n)\<close>)
+    case False
+    then have \<open>k + 2 ^ n \<le> 0\<close>
+      by simp
+    also note take_bit_nonnegative
+    finally show ?thesis .
+  next
+    case True
+    with that have \<open>0 \<le> k + 2 ^ n\<close> and \<open>k + 2 ^ n < 2 ^ n\<close>
+      by simp_all
+    then show ?thesis
+      by (simp only: take_bit_eq_mod mod_pos_pos_trivial)
+  qed
+  then show ?thesis
+    by (simp add: take_bit_eq_mod)
+qed
+
+lemma take_bit_int_less_eq:
+  \<open>take_bit n k \<le> k - 2 ^ n\<close> if \<open>2 ^ n \<le> k\<close> and \<open>n > 0\<close> for k :: int
+  using that zmod_le_nonneg_dividend [of \<open>k - 2 ^ n\<close> \<open>2 ^ n\<close>]
+  by (simp add: take_bit_eq_mod)
+
+lemma take_bit_int_less_eq_self_iff:
+  \<open>take_bit n k \<le> k \<longleftrightarrow> 0 \<le> k\<close> (is \<open>?P \<longleftrightarrow> ?Q\<close>)
+  for k :: int
+proof
+  assume ?P
+  show ?Q
+  proof (rule ccontr)
+    assume \<open>\<not> 0 \<le> k\<close>
+    then have \<open>k < 0\<close>
+      by simp
+    with \<open>?P\<close>
+    have \<open>take_bit n k < 0\<close>
+      by (rule le_less_trans)
+    then show False
+      by simp
+  qed
+next
+  assume ?Q
+  then show ?P
+    by (simp add: take_bit_eq_mod zmod_le_nonneg_dividend)
+qed
+
+lemma take_bit_int_less_self_iff:
+  \<open>take_bit n k < k \<longleftrightarrow> 2 ^ n \<le> k\<close>
+  for k :: int
+  by (auto simp add: less_le take_bit_int_less_eq_self_iff take_bit_int_eq_self_iff
+    intro: order_trans [of 0 \<open>2 ^ n\<close> k])
+
+lemma take_bit_int_greater_self_iff:
+  \<open>k < take_bit n k \<longleftrightarrow> k < 0\<close>
+  for k :: int
+  using take_bit_int_less_eq_self_iff [of n k] by auto
+
+lemma take_bit_int_greater_eq_self_iff:
+  \<open>k \<le> take_bit n k \<longleftrightarrow> k < 2 ^ n\<close>
+  for k :: int
+  by (auto simp add: le_less take_bit_int_greater_self_iff take_bit_int_eq_self_iff
+    dest: sym not_sym intro: less_trans [of k 0 \<open>2 ^ n\<close>])
+
+lemma minus_numeral_inc_eq:
+  \<open>- numeral (Num.inc n) = NOT (numeral n :: int)\<close>
+  by (simp add: not_int_def sub_inc_One_eq add_One)
+
+lemma sub_one_eq_not_neg:
+  \<open>Num.sub n num.One = NOT (- numeral n :: int)\<close>
+  by (simp add: not_int_def)
+
+lemma bit_numeral_int_iff [bit_simps]:
+  \<open>bit (numeral m :: int) n \<longleftrightarrow> bit (numeral m :: nat) n\<close>
+  using bit_of_nat_iff_bit [of \<open>numeral m\<close> n] by simp
+
+lemma bit_minus_int_iff [bit_simps]:
+  \<open>bit (- k) n \<longleftrightarrow> \<not> bit (k - 1) n\<close>
+  for k :: int
+  using bit_not_int_iff' [of \<open>k - 1\<close>] by simp
+
+lemma bit_numeral_int_simps [simp]:
+  \<open>bit (1 :: int) (numeral n) \<longleftrightarrow> bit (0 :: int) (pred_numeral n)\<close>
+  \<open>bit (numeral (num.Bit0 w) :: int) (numeral n) \<longleftrightarrow> bit (numeral w :: int) (pred_numeral n)\<close>
+  \<open>bit (numeral (num.Bit1 w) :: int) (numeral n) \<longleftrightarrow> bit (numeral w :: int) (pred_numeral n)\<close>
+  \<open>bit (numeral (Num.BitM w) :: int) (numeral n) \<longleftrightarrow> \<not> bit (- numeral w :: int) (pred_numeral n)\<close>
+  \<open>bit (- numeral (num.Bit0 w) :: int) (numeral n) \<longleftrightarrow> bit (- numeral w :: int) (pred_numeral n)\<close>
+  \<open>bit (- numeral (num.Bit1 w) :: int) (numeral n) \<longleftrightarrow> \<not> bit (numeral w :: int) (pred_numeral n)\<close>
+  \<open>bit (- numeral (Num.BitM w) :: int) (numeral n) \<longleftrightarrow> bit (- (numeral w) :: int) (pred_numeral n)\<close>
+  by (simp_all add: bit_1_iff numeral_eq_Suc bit_Suc add_One sub_inc_One_eq bit_minus_int_iff)
+
+lemma bit_numeral_Bit0_Suc_iff [simp]:
+  \<open>bit (numeral (Num.Bit0 m) :: int) (Suc n) \<longleftrightarrow> bit (numeral m :: int) n\<close>
+  by (simp add: bit_Suc)
+
+lemma bit_numeral_Bit1_Suc_iff [simp]:
+  \<open>bit (numeral (Num.Bit1 m) :: int) (Suc n) \<longleftrightarrow> bit (numeral m :: int) n\<close>
+  by (simp add: bit_Suc)
+
+lemma int_not_numerals [simp]:
+  \<open>NOT (numeral (Num.Bit0 n) :: int) = - numeral (Num.Bit1 n)\<close>
+  \<open>NOT (numeral (Num.Bit1 n) :: int) = - numeral (Num.inc (num.Bit1 n))\<close>
+  \<open>NOT (numeral (Num.BitM n) :: int) = - numeral (num.Bit0 n)\<close>
+  \<open>NOT (- numeral (Num.Bit0 n) :: int) = numeral (Num.BitM n)\<close>
+  \<open>NOT (- numeral (Num.Bit1 n) :: int) = numeral (Num.Bit0 n)\<close>
+  by (simp_all add: not_int_def add_One inc_BitM_eq) 
+
+text \<open>FIXME: The rule sets below are very large (24 rules for each
+  operator). Is there a simpler way to do this?\<close>
+
+context
+begin
+
+private lemma eqI:
+  \<open>k = l\<close>
+  if num: \<open>\<And>n. bit k (numeral n) \<longleftrightarrow> bit l (numeral n)\<close>
+    and even: \<open>even k \<longleftrightarrow> even l\<close>
+  for k l :: int
+proof (rule bit_eqI)
+  fix n
+  show \<open>bit k n \<longleftrightarrow> bit l n\<close>
+  proof (cases n)
+    case 0
+    with even show ?thesis
+      by simp
+  next
+    case (Suc n)
+    with num [of \<open>num_of_nat (Suc n)\<close>] show ?thesis
+      by (simp only: numeral_num_of_nat)
+  qed
+qed
+
+lemma int_and_numerals [simp]:
+  \<open>numeral (Num.Bit0 x) AND numeral (Num.Bit0 y) = (2 :: int) * (numeral x AND numeral y)\<close>
+  \<open>numeral (Num.Bit0 x) AND numeral (Num.Bit1 y) = (2 :: int) * (numeral x AND numeral y)\<close>
+  \<open>numeral (Num.Bit1 x) AND numeral (Num.Bit0 y) = (2 :: int) * (numeral x AND numeral y)\<close>
+  \<open>numeral (Num.Bit1 x) AND numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x AND numeral y)\<close>
+  \<open>numeral (Num.Bit0 x) AND - numeral (Num.Bit0 y) = (2 :: int) * (numeral x AND - numeral y)\<close>
+  \<open>numeral (Num.Bit0 x) AND - numeral (Num.Bit1 y) = (2 :: int) * (numeral x AND - numeral (y + Num.One))\<close>
+  \<open>numeral (Num.Bit1 x) AND - numeral (Num.Bit0 y) = (2 :: int) * (numeral x AND - numeral y)\<close>
+  \<open>numeral (Num.Bit1 x) AND - numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x AND - numeral (y + Num.One))\<close>
+  \<open>- numeral (Num.Bit0 x) AND numeral (Num.Bit0 y) = (2 :: int) * (- numeral x AND numeral y)\<close>
+  \<open>- numeral (Num.Bit0 x) AND numeral (Num.Bit1 y) = (2 :: int) * (- numeral x AND numeral y)\<close>
+  \<open>- numeral (Num.Bit1 x) AND numeral (Num.Bit0 y) = (2 :: int) * (- numeral (x + Num.One) AND numeral y)\<close>
+  \<open>- numeral (Num.Bit1 x) AND numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral (x + Num.One) AND numeral y)\<close>
+  \<open>- numeral (Num.Bit0 x) AND - numeral (Num.Bit0 y) = (2 :: int) * (- numeral x AND - numeral y)\<close>
+  \<open>- numeral (Num.Bit0 x) AND - numeral (Num.Bit1 y) = (2 :: int) * (- numeral x AND - numeral (y + Num.One))\<close>
+  \<open>- numeral (Num.Bit1 x) AND - numeral (Num.Bit0 y) = (2 :: int) * (- numeral (x + Num.One) AND - numeral y)\<close>
+  \<open>- numeral (Num.Bit1 x) AND - numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral (x + Num.One) AND - numeral (y + Num.One))\<close>
+  \<open>(1::int) AND numeral (Num.Bit0 y) = 0\<close>
+  \<open>(1::int) AND numeral (Num.Bit1 y) = 1\<close>
+  \<open>(1::int) AND - numeral (Num.Bit0 y) = 0\<close>
+  \<open>(1::int) AND - numeral (Num.Bit1 y) = 1\<close>
+  \<open>numeral (Num.Bit0 x) AND (1::int) = 0\<close>
+  \<open>numeral (Num.Bit1 x) AND (1::int) = 1\<close>
+  \<open>- numeral (Num.Bit0 x) AND (1::int) = 0\<close>
+  \<open>- numeral (Num.Bit1 x) AND (1::int) = 1\<close>
+  by (auto simp add: bit_and_iff bit_minus_iff even_and_iff bit_double_iff even_bit_succ_iff add_One sub_inc_One_eq intro: eqI)
+
+lemma int_or_numerals [simp]:
+  \<open>numeral (Num.Bit0 x) OR numeral (Num.Bit0 y) = (2 :: int) * (numeral x OR numeral y)\<close>
+  \<open>numeral (Num.Bit0 x) OR numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x OR numeral y)\<close>
+  \<open>numeral (Num.Bit1 x) OR numeral (Num.Bit0 y) = 1 + (2 :: int) * (numeral x OR numeral y)\<close>
+  \<open>numeral (Num.Bit1 x) OR numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x OR numeral y)\<close>
+  \<open>numeral (Num.Bit0 x) OR - numeral (Num.Bit0 y) = (2 :: int) * (numeral x OR - numeral y)\<close>
+  \<open>numeral (Num.Bit0 x) OR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x OR - numeral (y + Num.One))\<close>
+  \<open>numeral (Num.Bit1 x) OR - numeral (Num.Bit0 y) = 1 + (2 :: int) * (numeral x OR - numeral y)\<close>
+  \<open>numeral (Num.Bit1 x) OR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x OR - numeral (y + Num.One))\<close>
+  \<open>- numeral (Num.Bit0 x) OR numeral (Num.Bit0 y) = (2 :: int) * (- numeral x OR numeral y)\<close>
+  \<open>- numeral (Num.Bit0 x) OR numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral x OR numeral y)\<close>
+  \<open>- numeral (Num.Bit1 x) OR numeral (Num.Bit0 y) = 1 + (2 :: int) * (- numeral (x + Num.One) OR numeral y)\<close>
+  \<open>- numeral (Num.Bit1 x) OR numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral (x + Num.One) OR numeral y)\<close>
+  \<open>- numeral (Num.Bit0 x) OR - numeral (Num.Bit0 y) = (2 :: int) * (- numeral x OR - numeral y)\<close>
+  \<open>- numeral (Num.Bit0 x) OR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral x OR - numeral (y + Num.One))\<close>
+  \<open>- numeral (Num.Bit1 x) OR - numeral (Num.Bit0 y) = 1 + (2 :: int) * (- numeral (x + Num.One) OR - numeral y)\<close>
+  \<open>- numeral (Num.Bit1 x) OR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral (x + Num.One) OR - numeral (y + Num.One))\<close>
+  \<open>(1::int) OR numeral (Num.Bit0 y) = numeral (Num.Bit1 y)\<close>
+  \<open>(1::int) OR numeral (Num.Bit1 y) = numeral (Num.Bit1 y)\<close>
+  \<open>(1::int) OR - numeral (Num.Bit0 y) = - numeral (Num.BitM y)\<close>
+  \<open>(1::int) OR - numeral (Num.Bit1 y) = - numeral (Num.Bit1 y)\<close>
+  \<open>numeral (Num.Bit0 x) OR (1::int) = numeral (Num.Bit1 x)\<close>
+  \<open>numeral (Num.Bit1 x) OR (1::int) = numeral (Num.Bit1 x)\<close>
+  \<open>- numeral (Num.Bit0 x) OR (1::int) = - numeral (Num.BitM x)\<close>
+  \<open>- numeral (Num.Bit1 x) OR (1::int) = - numeral (Num.Bit1 x)\<close>
+  by (auto simp add: bit_or_iff bit_minus_iff even_or_iff bit_double_iff even_bit_succ_iff add_One sub_inc_One_eq sub_BitM_One_eq intro: eqI)
+
+lemma int_xor_numerals [simp]:
+  \<open>numeral (Num.Bit0 x) XOR numeral (Num.Bit0 y) = (2 :: int) * (numeral x XOR numeral y)\<close>
+  \<open>numeral (Num.Bit0 x) XOR numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x XOR numeral y)\<close>
+  \<open>numeral (Num.Bit1 x) XOR numeral (Num.Bit0 y) = 1 + (2 :: int) * (numeral x XOR numeral y)\<close>
+  \<open>numeral (Num.Bit1 x) XOR numeral (Num.Bit1 y) = (2 :: int) * (numeral x XOR numeral y)\<close>
+  \<open>numeral (Num.Bit0 x) XOR - numeral (Num.Bit0 y) = (2 :: int) * (numeral x XOR - numeral y)\<close>
+  \<open>numeral (Num.Bit0 x) XOR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x XOR - numeral (y + Num.One))\<close>
+  \<open>numeral (Num.Bit1 x) XOR - numeral (Num.Bit0 y) = 1 + (2 :: int) * (numeral x XOR - numeral y)\<close>
+  \<open>numeral (Num.Bit1 x) XOR - numeral (Num.Bit1 y) = (2 :: int) * (numeral x XOR - numeral (y + Num.One))\<close>
+  \<open>- numeral (Num.Bit0 x) XOR numeral (Num.Bit0 y) = (2 :: int) * (- numeral x XOR numeral y)\<close>
+  \<open>- numeral (Num.Bit0 x) XOR numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral x XOR numeral y)\<close>
+  \<open>- numeral (Num.Bit1 x) XOR numeral (Num.Bit0 y) = 1 + (2 :: int) * (- numeral (x + Num.One) XOR numeral y)\<close>
+  \<open>- numeral (Num.Bit1 x) XOR numeral (Num.Bit1 y) = (2 :: int) * (- numeral (x + Num.One) XOR numeral y)\<close>
+  \<open>- numeral (Num.Bit0 x) XOR - numeral (Num.Bit0 y) = (2 :: int) * (- numeral x XOR - numeral y)\<close>
+  \<open>- numeral (Num.Bit0 x) XOR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral x XOR - numeral (y + Num.One))\<close>
+  \<open>- numeral (Num.Bit1 x) XOR - numeral (Num.Bit0 y) = 1 + (2 :: int) * (- numeral (x + Num.One) XOR - numeral y)\<close>
+  \<open>- numeral (Num.Bit1 x) XOR - numeral (Num.Bit1 y) = (2 :: int) * (- numeral (x + Num.One) XOR - numeral (y + Num.One))\<close>
+  \<open>(1::int) XOR numeral (Num.Bit0 y) = numeral (Num.Bit1 y)\<close>
+  \<open>(1::int) XOR numeral (Num.Bit1 y) = numeral (Num.Bit0 y)\<close>
+  \<open>(1::int) XOR - numeral (Num.Bit0 y) = - numeral (Num.BitM y)\<close>
+  \<open>(1::int) XOR - numeral (Num.Bit1 y) = - numeral (Num.Bit0 (y + Num.One))\<close>
+  \<open>numeral (Num.Bit0 x) XOR (1::int) = numeral (Num.Bit1 x)\<close>
+  \<open>numeral (Num.Bit1 x) XOR (1::int) = numeral (Num.Bit0 x)\<close>
+  \<open>- numeral (Num.Bit0 x) XOR (1::int) = - numeral (Num.BitM x)\<close>
+  \<open>- numeral (Num.Bit1 x) XOR (1::int) = - numeral (Num.Bit0 (x + Num.One))\<close>
+  by (auto simp add: bit_xor_iff bit_minus_iff even_xor_iff bit_double_iff even_bit_succ_iff add_One sub_inc_One_eq sub_BitM_One_eq intro: eqI)
+
+end
+
+context semiring_bit_operations
+begin
+
+lemma push_bit_of_nat:
+  \<open>push_bit n (of_nat m) = of_nat (push_bit n m)\<close>
+  by (simp add: push_bit_eq_mult Bit_Operations.push_bit_eq_mult)
+
+lemma of_nat_push_bit:
+  \<open>of_nat (push_bit m n) = push_bit m (of_nat n)\<close>
+  by (simp add: push_bit_eq_mult Bit_Operations.push_bit_eq_mult)
+
+lemma take_bit_of_nat:
+  \<open>take_bit n (of_nat m) = of_nat (take_bit n m)\<close>
+  by (rule bit_eqI) (simp add: bit_take_bit_iff Bit_Operations.bit_take_bit_iff bit_of_nat_iff)
+
+lemma of_nat_take_bit:
+  \<open>of_nat (take_bit n m) = take_bit n (of_nat m)\<close>
+  by (rule bit_eqI) (simp add: bit_take_bit_iff Bit_Operations.bit_take_bit_iff bit_of_nat_iff)
+
+end
+
+lemma push_bit_nat_eq:
+  \<open>push_bit n (nat k) = nat (push_bit n k)\<close>
+  by (cases \<open>k \<ge> 0\<close>) (simp_all add: push_bit_eq_mult nat_mult_distrib not_le mult_nonneg_nonpos2)
+
+lemma drop_bit_nat_eq:
+  \<open>drop_bit n (nat k) = nat (drop_bit n k)\<close>
+  apply (cases \<open>k \<ge> 0\<close>)
+   apply (simp_all add: drop_bit_eq_div nat_div_distrib nat_power_eq not_le)
+  apply (simp add: divide_int_def)
+  done
+
+lemma take_bit_nat_eq:
+  \<open>take_bit n (nat k) = nat (take_bit n k)\<close> if \<open>k \<ge> 0\<close>
+  using that by (simp add: take_bit_eq_mod nat_mod_distrib nat_power_eq)
+
+lemma nat_take_bit_eq:
+  \<open>nat (take_bit n k) = take_bit n (nat k)\<close>
+  if \<open>k \<ge> 0\<close>
+  using that by (simp add: take_bit_eq_mod nat_mod_distrib nat_power_eq)
+
+lemma not_exp_less_eq_0_int [simp]:
+  \<open>\<not> 2 ^ n \<le> (0::int)\<close>
+  by (simp add: power_le_zero_eq)
+
+lemma half_nonnegative_int_iff [simp]:
+  \<open>k div 2 \<ge> 0 \<longleftrightarrow> k \<ge> 0\<close> for k :: int
+proof (cases \<open>k \<ge> 0\<close>)
+  case True
+  then show ?thesis
+    by (auto simp add: divide_int_def sgn_1_pos)
+next
+  case False
+  then show ?thesis
+    by (auto simp add: divide_int_def not_le elim!: evenE)
+qed
+
+lemma half_negative_int_iff [simp]:
+  \<open>k div 2 < 0 \<longleftrightarrow> k < 0\<close> for k :: int
+  by (subst Not_eq_iff [symmetric]) (simp add: not_less)
+
+lemma push_bit_of_Suc_0 [simp]:
+  "push_bit n (Suc 0) = 2 ^ n"
+  using push_bit_of_1 [where ?'a = nat] by simp
+
+lemma take_bit_of_Suc_0 [simp]:
+  "take_bit n (Suc 0) = of_bool (0 < n)"
+  using take_bit_of_1 [where ?'a = nat] by simp
+
+lemma drop_bit_of_Suc_0 [simp]:
+  "drop_bit n (Suc 0) = of_bool (n = 0)"
+  using drop_bit_of_1 [where ?'a = nat] by simp
+
+lemma int_bit_bound:
+  fixes k :: int
+  obtains n where \<open>\<And>m. n \<le> m \<Longrightarrow> bit k m \<longleftrightarrow> bit k n\<close>
+    and \<open>n > 0 \<Longrightarrow> bit k (n - 1) \<noteq> bit k n\<close>
+proof -
+  obtain q where *: \<open>\<And>m. q \<le> m \<Longrightarrow> bit k m \<longleftrightarrow> bit k q\<close>
+  proof (cases \<open>k \<ge> 0\<close>)
+    case True
+    moreover from power_gt_expt [of 2 \<open>nat k\<close>]
+    have \<open>nat k < 2 ^ nat k\<close>
+      by simp
+    then have \<open>int (nat k) < int (2 ^ nat k)\<close>
+      by (simp only: of_nat_less_iff)
+    ultimately have *: \<open>k div 2 ^ nat k = 0\<close>
+      by simp
+    show thesis
+    proof (rule that [of \<open>nat k\<close>])
+      fix m
+      assume \<open>nat k \<le> m\<close>
+      then show \<open>bit k m \<longleftrightarrow> bit k (nat k)\<close>
+        by (auto simp add: * bit_iff_odd power_add zdiv_zmult2_eq dest!: le_Suc_ex)
+    qed
+  next
+    case False
+    moreover from power_gt_expt [of 2 \<open>nat (- k)\<close>]
+    have \<open>nat (- k) < 2 ^ nat (- k)\<close>
+      by simp
+    then have \<open>int (nat (- k)) < int (2 ^ nat (- k))\<close>
+      by (simp only: of_nat_less_iff)
+    ultimately have \<open>- k div - (2 ^ nat (- k)) = - 1\<close>
+      by (subst div_pos_neg_trivial) simp_all
+    then have *: \<open>k div 2 ^ nat (- k) = - 1\<close>
+      by simp
+    show thesis
+    proof (rule that [of \<open>nat (- k)\<close>])
+      fix m
+      assume \<open>nat (- k) \<le> m\<close>
+      then show \<open>bit k m \<longleftrightarrow> bit k (nat (- k))\<close>
+        by (auto simp add: * bit_iff_odd power_add zdiv_zmult2_eq minus_1_div_exp_eq_int dest!: le_Suc_ex)
+    qed
+  qed
+  show thesis
+  proof (cases \<open>\<forall>m. bit k m \<longleftrightarrow> bit k q\<close>)
+    case True
+    then have \<open>bit k 0 \<longleftrightarrow> bit k q\<close>
+      by blast
+    with True that [of 0] show thesis
+      by simp
+  next
+    case False
+    then obtain r where **: \<open>bit k r \<noteq> bit k q\<close>
+      by blast
+    have \<open>r < q\<close>
+      by (rule ccontr) (use * [of r] ** in simp)
+    define N where \<open>N = {n. n < q \<and> bit k n \<noteq> bit k q}\<close>
+    moreover have \<open>finite N\<close> \<open>r \<in> N\<close>
+      using ** N_def \<open>r < q\<close> by auto
+    moreover define n where \<open>n = Suc (Max N)\<close>
+    ultimately have \<open>\<And>m. n \<le> m \<Longrightarrow> bit k m \<longleftrightarrow> bit k n\<close>
+      apply auto
+         apply (metis (full_types, lifting) "*" Max_ge_iff Suc_n_not_le_n \<open>finite N\<close> all_not_in_conv mem_Collect_eq not_le)
+        apply (metis "*" Max_ge Suc_n_not_le_n \<open>finite N\<close> linorder_not_less mem_Collect_eq)
+        apply (metis "*" Max_ge Suc_n_not_le_n \<open>finite N\<close> linorder_not_less mem_Collect_eq)
+      apply (metis (full_types, lifting) "*" Max_ge_iff Suc_n_not_le_n \<open>finite N\<close> all_not_in_conv mem_Collect_eq not_le)
+      done
+    have \<open>bit k (Max N) \<noteq> bit k n\<close>
+      by (metis (mono_tags, lifting) "*" Max_in N_def \<open>\<And>m. n \<le> m \<Longrightarrow> bit k m = bit k n\<close> \<open>finite N\<close> \<open>r \<in> N\<close> empty_iff le_cases mem_Collect_eq)
+    show thesis apply (rule that [of n])
+      using \<open>\<And>m. n \<le> m \<Longrightarrow> bit k m = bit k n\<close> apply blast
+      using \<open>bit k (Max N) \<noteq> bit k n\<close> n_def by auto
+  qed
+qed
+
+context semiring_bit_operations
+begin
+
+lemma of_nat_and_eq:
+  \<open>of_nat (m AND n) = of_nat m AND of_nat n\<close>
+  by (rule bit_eqI) (simp add: bit_of_nat_iff bit_and_iff Bit_Operations.bit_and_iff)
+
+lemma of_nat_or_eq:
+  \<open>of_nat (m OR n) = of_nat m OR of_nat n\<close>
+  by (rule bit_eqI) (simp add: bit_of_nat_iff bit_or_iff Bit_Operations.bit_or_iff)
+
+lemma of_nat_xor_eq:
+  \<open>of_nat (m XOR n) = of_nat m XOR of_nat n\<close>
+  by (rule bit_eqI) (simp add: bit_of_nat_iff bit_xor_iff Bit_Operations.bit_xor_iff)
+
+end
+
+context ring_bit_operations
+begin
+
+lemma of_nat_mask_eq:
+  \<open>of_nat (mask n) = mask n\<close>
+  by (induction n) (simp_all add: mask_Suc_double Bit_Operations.mask_Suc_double of_nat_or_eq)
+
+end
+
+lemma Suc_mask_eq_exp:
+  \<open>Suc (mask n) = 2 ^ n\<close>
+  by (simp add: mask_eq_exp_minus_1)
+
+lemma less_eq_mask:
+  \<open>n \<le> mask n\<close>
+  by (simp add: mask_eq_exp_minus_1 le_diff_conv2)
+    (metis Suc_mask_eq_exp diff_Suc_1 diff_le_diff_pow diff_zero le_refl not_less_eq_eq power_0)
+
+lemma less_mask:
+  \<open>n < mask n\<close> if \<open>Suc 0 < n\<close>
+proof -
+  define m where \<open>m = n - 2\<close>
+  with that have *: \<open>n = m + 2\<close>
+    by simp
+  have \<open>Suc (Suc (Suc m)) < 4 * 2 ^ m\<close>
+    by (induction m) simp_all
+  then have \<open>Suc (m + 2) < Suc (mask (m + 2))\<close>
+    by (simp add: Suc_mask_eq_exp)
+  then have \<open>m + 2 < mask (m + 2)\<close>
+    by (simp add: less_le)
+  with * show ?thesis
+    by simp
+qed
+
+
+subsection \<open>Bit concatenation\<close>
+
+definition concat_bit :: \<open>nat \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int\<close>
+  where \<open>concat_bit n k l = take_bit n k OR push_bit n l\<close>
+
+lemma bit_concat_bit_iff [bit_simps]:
+  \<open>bit (concat_bit m k l) n \<longleftrightarrow> n < m \<and> bit k n \<or> m \<le> n \<and> bit l (n - m)\<close>
+  by (simp add: concat_bit_def bit_or_iff bit_and_iff bit_take_bit_iff bit_push_bit_iff ac_simps)
+
+lemma concat_bit_eq:
+  \<open>concat_bit n k l = take_bit n k + push_bit n l\<close>
+  by (simp add: concat_bit_def take_bit_eq_mask
+    bit_and_iff bit_mask_iff bit_push_bit_iff disjunctive_add)
+
+lemma concat_bit_0 [simp]:
+  \<open>concat_bit 0 k l = l\<close>
+  by (simp add: concat_bit_def)
+
+lemma concat_bit_Suc:
+  \<open>concat_bit (Suc n) k l = k mod 2 + 2 * concat_bit n (k div 2) l\<close>
+  by (simp add: concat_bit_eq take_bit_Suc push_bit_double)
+
+lemma concat_bit_of_zero_1 [simp]:
+  \<open>concat_bit n 0 l = push_bit n l\<close>
+  by (simp add: concat_bit_def)
+
+lemma concat_bit_of_zero_2 [simp]:
+  \<open>concat_bit n k 0 = take_bit n k\<close>
+  by (simp add: concat_bit_def take_bit_eq_mask)
+
+lemma concat_bit_nonnegative_iff [simp]:
+  \<open>concat_bit n k l \<ge> 0 \<longleftrightarrow> l \<ge> 0\<close>
+  by (simp add: concat_bit_def)
+
+lemma concat_bit_negative_iff [simp]:
+  \<open>concat_bit n k l < 0 \<longleftrightarrow> l < 0\<close>
+  by (simp add: concat_bit_def)
+
+lemma concat_bit_assoc:
+  \<open>concat_bit n k (concat_bit m l r) = concat_bit (m + n) (concat_bit n k l) r\<close>
+  by (rule bit_eqI) (auto simp add: bit_concat_bit_iff ac_simps)
+
+lemma concat_bit_assoc_sym:
+  \<open>concat_bit m (concat_bit n k l) r = concat_bit (min m n) k (concat_bit (m - n) l r)\<close>
+  by (rule bit_eqI) (auto simp add: bit_concat_bit_iff ac_simps min_def)
+
+lemma concat_bit_eq_iff:
+  \<open>concat_bit n k l = concat_bit n r s
+    \<longleftrightarrow> take_bit n k = take_bit n r \<and> l = s\<close> (is \<open>?P \<longleftrightarrow> ?Q\<close>)
+proof
+  assume ?Q
+  then show ?P
+    by (simp add: concat_bit_def)
+next
+  assume ?P
+  then have *: \<open>bit (concat_bit n k l) m = bit (concat_bit n r s) m\<close> for m
+    by (simp add: bit_eq_iff)
+  have \<open>take_bit n k = take_bit n r\<close>
+  proof (rule bit_eqI)
+    fix m
+    from * [of m]
+    show \<open>bit (take_bit n k) m \<longleftrightarrow> bit (take_bit n r) m\<close>
+      by (auto simp add: bit_take_bit_iff bit_concat_bit_iff)
+  qed
+  moreover have \<open>push_bit n l = push_bit n s\<close>
+  proof (rule bit_eqI)
+    fix m
+    from * [of m]
+    show \<open>bit (push_bit n l) m \<longleftrightarrow> bit (push_bit n s) m\<close>
+      by (auto simp add: bit_push_bit_iff bit_concat_bit_iff)
+  qed
+  then have \<open>l = s\<close>
+    by (simp add: push_bit_eq_mult)
+  ultimately show ?Q
+    by (simp add: concat_bit_def)
+qed
+
+lemma take_bit_concat_bit_eq:
+  \<open>take_bit m (concat_bit n k l) = concat_bit (min m n) k (take_bit (m - n) l)\<close>
+  by (rule bit_eqI)
+    (auto simp add: bit_take_bit_iff bit_concat_bit_iff min_def)  
+
+lemma concat_bit_take_bit_eq:
+  \<open>concat_bit n (take_bit n b) = concat_bit n b\<close>
+  by (simp add: concat_bit_def [abs_def])
+
+
+subsection \<open>Taking bits with sign propagation\<close>
+
+context ring_bit_operations
+begin
+
+definition signed_take_bit :: \<open>nat \<Rightarrow> 'a \<Rightarrow> 'a\<close>
+  where \<open>signed_take_bit n a = take_bit n a OR (of_bool (bit a n) * NOT (mask n))\<close>
+
+lemma signed_take_bit_eq_if_positive:
+  \<open>signed_take_bit n a = take_bit n a\<close> if \<open>\<not> bit a n\<close>
+  using that by (simp add: signed_take_bit_def)
+
+lemma signed_take_bit_eq_if_negative:
+  \<open>signed_take_bit n a = take_bit n a OR NOT (mask n)\<close> if \<open>bit a n\<close>
+  using that by (simp add: signed_take_bit_def)
+
+lemma even_signed_take_bit_iff:
+  \<open>even (signed_take_bit m a) \<longleftrightarrow> even a\<close>
+  by (auto simp add: signed_take_bit_def even_or_iff even_mask_iff bit_double_iff)
+
+lemma bit_signed_take_bit_iff [bit_simps]:
+  \<open>bit (signed_take_bit m a) n \<longleftrightarrow> 2 ^ n \<noteq> 0 \<and> bit a (min m n)\<close>
+  by (simp add: signed_take_bit_def bit_take_bit_iff bit_or_iff bit_not_iff bit_mask_iff min_def not_le)
+    (use exp_eq_0_imp_not_bit in blast)
+
+lemma signed_take_bit_0 [simp]:
+  \<open>signed_take_bit 0 a = - (a mod 2)\<close>
+  by (simp add: signed_take_bit_def odd_iff_mod_2_eq_one)
+
+lemma signed_take_bit_Suc:
+  \<open>signed_take_bit (Suc n) a = a mod 2 + 2 * signed_take_bit n (a div 2)\<close>
+proof (rule bit_eqI)
+  fix m
+  assume *: \<open>2 ^ m \<noteq> 0\<close>
+  show \<open>bit (signed_take_bit (Suc n) a) m \<longleftrightarrow>
+    bit (a mod 2 + 2 * signed_take_bit n (a div 2)) m\<close>
+  proof (cases m)
+    case 0
+    then show ?thesis
+      by (simp add: even_signed_take_bit_iff)
+  next
+    case (Suc m)
+    with * have \<open>2 ^ m \<noteq> 0\<close>
+      by (metis mult_not_zero power_Suc)
+    with Suc show ?thesis
+      by (simp add: bit_signed_take_bit_iff mod2_eq_if bit_double_iff even_bit_succ_iff
+        ac_simps flip: bit_Suc)
+  qed
+qed
+
+lemma signed_take_bit_of_0 [simp]:
+  \<open>signed_take_bit n 0 = 0\<close>
+  by (simp add: signed_take_bit_def)
+
+lemma signed_take_bit_of_minus_1 [simp]:
+  \<open>signed_take_bit n (- 1) = - 1\<close>
+  by (simp add: signed_take_bit_def take_bit_minus_one_eq_mask mask_eq_exp_minus_1)
+
+lemma signed_take_bit_Suc_1 [simp]:
+  \<open>signed_take_bit (Suc n) 1 = 1\<close>
+  by (simp add: signed_take_bit_Suc)
+
+lemma signed_take_bit_rec:
+  \<open>signed_take_bit n a = (if n = 0 then - (a mod 2) else a mod 2 + 2 * signed_take_bit (n - 1) (a div 2))\<close>
+  by (cases n) (simp_all add: signed_take_bit_Suc)
+
+lemma signed_take_bit_eq_iff_take_bit_eq:
+  \<open>signed_take_bit n a = signed_take_bit n b \<longleftrightarrow> take_bit (Suc n) a = take_bit (Suc n) b\<close>
+proof -
+  have \<open>bit (signed_take_bit n a) = bit (signed_take_bit n b) \<longleftrightarrow> bit (take_bit (Suc n) a) = bit (take_bit (Suc n) b)\<close>
+    by (simp add: fun_eq_iff bit_signed_take_bit_iff bit_take_bit_iff not_le less_Suc_eq_le min_def)
+      (use exp_eq_0_imp_not_bit in fastforce)
+  then show ?thesis
+    by (simp add: bit_eq_iff fun_eq_iff)
+qed
+
+lemma signed_take_bit_signed_take_bit [simp]:
+  \<open>signed_take_bit m (signed_take_bit n a) = signed_take_bit (min m n) a\<close>
+proof (rule bit_eqI)
+  fix q
+  show \<open>bit (signed_take_bit m (signed_take_bit n a)) q \<longleftrightarrow>
+    bit (signed_take_bit (min m n) a) q\<close>
+    by (simp add: bit_signed_take_bit_iff min_def bit_or_iff bit_not_iff bit_mask_iff bit_take_bit_iff)
+      (use le_Suc_ex exp_add_not_zero_imp in blast)
+qed
+
+lemma signed_take_bit_take_bit:
+  \<open>signed_take_bit m (take_bit n a) = (if n \<le> m then take_bit n else signed_take_bit m) a\<close>
+  by (rule bit_eqI) (auto simp add: bit_signed_take_bit_iff min_def bit_take_bit_iff)
+
+lemma take_bit_signed_take_bit:
+  \<open>take_bit m (signed_take_bit n a) = take_bit m a\<close> if \<open>m \<le> Suc n\<close>
+  using that by (rule le_SucE; intro bit_eqI)
+   (auto simp add: bit_take_bit_iff bit_signed_take_bit_iff min_def less_Suc_eq)
+
+end
+
+text \<open>Modulus centered around 0\<close>
+
+lemma signed_take_bit_eq_concat_bit:
+  \<open>signed_take_bit n k = concat_bit n k (- of_bool (bit k n))\<close>
+  by (simp add: concat_bit_def signed_take_bit_def push_bit_minus_one_eq_not_mask)
+
+lemma signed_take_bit_add:
+  \<open>signed_take_bit n (signed_take_bit n k + signed_take_bit n l) = signed_take_bit n (k + l)\<close>
+  for k l :: int
+proof -
+  have \<open>take_bit (Suc n)
+     (take_bit (Suc n) (signed_take_bit n k) +
+      take_bit (Suc n) (signed_take_bit n l)) =
+    take_bit (Suc n) (k + l)\<close>
+    by (simp add: take_bit_signed_take_bit take_bit_add)
+  then show ?thesis
+    by (simp only: signed_take_bit_eq_iff_take_bit_eq take_bit_add)
+qed
+
+lemma signed_take_bit_diff:
+  \<open>signed_take_bit n (signed_take_bit n k - signed_take_bit n l) = signed_take_bit n (k - l)\<close>
+  for k l :: int
+proof -
+  have \<open>take_bit (Suc n)
+     (take_bit (Suc n) (signed_take_bit n k) -
+      take_bit (Suc n) (signed_take_bit n l)) =
+    take_bit (Suc n) (k - l)\<close>
+    by (simp add: take_bit_signed_take_bit take_bit_diff)
+  then show ?thesis
+    by (simp only: signed_take_bit_eq_iff_take_bit_eq take_bit_diff)
+qed
+
+lemma signed_take_bit_minus:
+  \<open>signed_take_bit n (- signed_take_bit n k) = signed_take_bit n (- k)\<close>
+  for k :: int
+proof -
+  have \<open>take_bit (Suc n)
+     (- take_bit (Suc n) (signed_take_bit n k)) =
+    take_bit (Suc n) (- k)\<close>
+    by (simp add: take_bit_signed_take_bit take_bit_minus)
+  then show ?thesis
+    by (simp only: signed_take_bit_eq_iff_take_bit_eq take_bit_minus)
+qed
+
+lemma signed_take_bit_mult:
+  \<open>signed_take_bit n (signed_take_bit n k * signed_take_bit n l) = signed_take_bit n (k * l)\<close>
+  for k l :: int
+proof -
+  have \<open>take_bit (Suc n)
+     (take_bit (Suc n) (signed_take_bit n k) *
+      take_bit (Suc n) (signed_take_bit n l)) =
+    take_bit (Suc n) (k * l)\<close>
+    by (simp add: take_bit_signed_take_bit take_bit_mult)
+  then show ?thesis
+    by (simp only: signed_take_bit_eq_iff_take_bit_eq take_bit_mult)
+qed
+
+lemma signed_take_bit_eq_take_bit_minus:
+  \<open>signed_take_bit n k = take_bit (Suc n) k - 2 ^ Suc n * of_bool (bit k n)\<close>
+  for k :: int
+proof (cases \<open>bit k n\<close>)
+  case True
+  have \<open>signed_take_bit n k = take_bit (Suc n) k OR NOT (mask (Suc n))\<close>
+    by (rule bit_eqI) (auto simp add: bit_signed_take_bit_iff min_def bit_take_bit_iff bit_or_iff bit_not_iff bit_mask_iff less_Suc_eq True)
+  then have \<open>signed_take_bit n k = take_bit (Suc n) k + NOT (mask (Suc n))\<close>
+    by (simp add: disjunctive_add bit_take_bit_iff bit_not_iff bit_mask_iff)
+  with True show ?thesis
+    by (simp flip: minus_exp_eq_not_mask)
+next
+  case False
+  show ?thesis
+    by (rule bit_eqI) (simp add: False bit_signed_take_bit_iff bit_take_bit_iff min_def less_Suc_eq)
+qed
+
+lemma signed_take_bit_eq_take_bit_shift:
+  \<open>signed_take_bit n k = take_bit (Suc n) (k + 2 ^ n) - 2 ^ n\<close>
+  for k :: int
+proof -
+  have *: \<open>take_bit n k OR 2 ^ n = take_bit n k + 2 ^ n\<close>
+    by (simp add: disjunctive_add bit_exp_iff bit_take_bit_iff)
+  have \<open>take_bit n k - 2 ^ n = take_bit n k + NOT (mask n)\<close>
+    by (simp add: minus_exp_eq_not_mask)
+  also have \<open>\<dots> = take_bit n k OR NOT (mask n)\<close>
+    by (rule disjunctive_add)
+      (simp add: bit_exp_iff bit_take_bit_iff bit_not_iff bit_mask_iff)
+  finally have **: \<open>take_bit n k - 2 ^ n = take_bit n k OR NOT (mask n)\<close> .
+  have \<open>take_bit (Suc n) (k + 2 ^ n) = take_bit (Suc n) (take_bit (Suc n) k + take_bit (Suc n) (2 ^ n))\<close>
+    by (simp only: take_bit_add)
+  also have \<open>take_bit (Suc n) k = 2 ^ n * of_bool (bit k n) + take_bit n k\<close>
+    by (simp add: take_bit_Suc_from_most)
+  finally have \<open>take_bit (Suc n) (k + 2 ^ n) = take_bit (Suc n) (2 ^ (n + of_bool (bit k n)) + take_bit n k)\<close>
+    by (simp add: ac_simps)
+  also have \<open>2 ^ (n + of_bool (bit k n)) + take_bit n k = 2 ^ (n + of_bool (bit k n)) OR take_bit n k\<close>
+    by (rule disjunctive_add)
+      (auto simp add: disjunctive_add bit_take_bit_iff bit_double_iff bit_exp_iff)
+  finally show ?thesis
+    using * ** by (simp add: signed_take_bit_def concat_bit_Suc min_def ac_simps)
+qed
+
+lemma signed_take_bit_nonnegative_iff [simp]:
+  \<open>0 \<le> signed_take_bit n k \<longleftrightarrow> \<not> bit k n\<close>
+  for k :: int
+  by (simp add: signed_take_bit_def not_less concat_bit_def)
+
+lemma signed_take_bit_negative_iff [simp]:
+  \<open>signed_take_bit n k < 0 \<longleftrightarrow> bit k n\<close>
+  for k :: int
+  by (simp add: signed_take_bit_def not_less concat_bit_def)
+
+lemma signed_take_bit_int_greater_eq_minus_exp [simp]:
+  \<open>- (2 ^ n) \<le> signed_take_bit n k\<close>
+  for k :: int
+  by (simp add: signed_take_bit_eq_take_bit_shift)
+
+lemma signed_take_bit_int_less_exp [simp]:
+  \<open>signed_take_bit n k < 2 ^ n\<close>
+  for k :: int
+  using take_bit_int_less_exp [of \<open>Suc n\<close>]
+  by (simp add: signed_take_bit_eq_take_bit_shift)
+
+lemma signed_take_bit_int_eq_self_iff:
+  \<open>signed_take_bit n k = k \<longleftrightarrow> - (2 ^ n) \<le> k \<and> k < 2 ^ n\<close>
+  for k :: int
+  by (auto simp add: signed_take_bit_eq_take_bit_shift take_bit_int_eq_self_iff algebra_simps)
+
+lemma signed_take_bit_int_eq_self:
+  \<open>signed_take_bit n k = k\<close> if \<open>- (2 ^ n) \<le> k\<close> \<open>k < 2 ^ n\<close>
+  for k :: int
+  using that by (simp add: signed_take_bit_int_eq_self_iff)
+
+lemma signed_take_bit_int_less_eq_self_iff:
+  \<open>signed_take_bit n k \<le> k \<longleftrightarrow> - (2 ^ n) \<le> k\<close>
+  for k :: int
+  by (simp add: signed_take_bit_eq_take_bit_shift take_bit_int_less_eq_self_iff algebra_simps)
+    linarith
+
+lemma signed_take_bit_int_less_self_iff:
+  \<open>signed_take_bit n k < k \<longleftrightarrow> 2 ^ n \<le> k\<close>
+  for k :: int
+  by (simp add: signed_take_bit_eq_take_bit_shift take_bit_int_less_self_iff algebra_simps)
+
+lemma signed_take_bit_int_greater_self_iff:
+  \<open>k < signed_take_bit n k \<longleftrightarrow> k < - (2 ^ n)\<close>
+  for k :: int
+  by (simp add: signed_take_bit_eq_take_bit_shift take_bit_int_greater_self_iff algebra_simps)
+    linarith
+
+lemma signed_take_bit_int_greater_eq_self_iff:
+  \<open>k \<le> signed_take_bit n k \<longleftrightarrow> k < 2 ^ n\<close>
+  for k :: int
+  by (simp add: signed_take_bit_eq_take_bit_shift take_bit_int_greater_eq_self_iff algebra_simps)
+
+lemma signed_take_bit_int_greater_eq:
+  \<open>k + 2 ^ Suc n \<le> signed_take_bit n k\<close> if \<open>k < - (2 ^ n)\<close>
+  for k :: int
+  using that take_bit_int_greater_eq [of \<open>k + 2 ^ n\<close> \<open>Suc n\<close>]
+  by (simp add: signed_take_bit_eq_take_bit_shift)
+
+lemma signed_take_bit_int_less_eq:
+  \<open>signed_take_bit n k \<le> k - 2 ^ Suc n\<close> if \<open>k \<ge> 2 ^ n\<close>
+  for k :: int
+  using that take_bit_int_less_eq [of \<open>Suc n\<close> \<open>k + 2 ^ n\<close>]
+  by (simp add: signed_take_bit_eq_take_bit_shift)
+
+lemma signed_take_bit_Suc_bit0 [simp]:
+  \<open>signed_take_bit (Suc n) (numeral (Num.Bit0 k)) = signed_take_bit n (numeral k) * (2 :: int)\<close>
+  by (simp add: signed_take_bit_Suc)
+
+lemma signed_take_bit_Suc_bit1 [simp]:
+  \<open>signed_take_bit (Suc n) (numeral (Num.Bit1 k)) = signed_take_bit n (numeral k) * 2 + (1 :: int)\<close>
+  by (simp add: signed_take_bit_Suc)
+
+lemma signed_take_bit_Suc_minus_bit0 [simp]:
+  \<open>signed_take_bit (Suc n) (- numeral (Num.Bit0 k)) = signed_take_bit n (- numeral k) * (2 :: int)\<close>
+  by (simp add: signed_take_bit_Suc)
+
+lemma signed_take_bit_Suc_minus_bit1 [simp]:
+  \<open>signed_take_bit (Suc n) (- numeral (Num.Bit1 k)) = signed_take_bit n (- numeral k - 1) * 2 + (1 :: int)\<close>
+  by (simp add: signed_take_bit_Suc)
+
+lemma signed_take_bit_numeral_bit0 [simp]:
+  \<open>signed_take_bit (numeral l) (numeral (Num.Bit0 k)) = signed_take_bit (pred_numeral l) (numeral k) * (2 :: int)\<close>
+  by (simp add: signed_take_bit_rec)
+
+lemma signed_take_bit_numeral_bit1 [simp]:
+  \<open>signed_take_bit (numeral l) (numeral (Num.Bit1 k)) = signed_take_bit (pred_numeral l) (numeral k) * 2 + (1 :: int)\<close>
+  by (simp add: signed_take_bit_rec)
+
+lemma signed_take_bit_numeral_minus_bit0 [simp]:
+  \<open>signed_take_bit (numeral l) (- numeral (Num.Bit0 k)) = signed_take_bit (pred_numeral l) (- numeral k) * (2 :: int)\<close>
+  by (simp add: signed_take_bit_rec)
+
+lemma signed_take_bit_numeral_minus_bit1 [simp]:
+  \<open>signed_take_bit (numeral l) (- numeral (Num.Bit1 k)) = signed_take_bit (pred_numeral l) (- numeral k - 1) * 2 + (1 :: int)\<close>
+  by (simp add: signed_take_bit_rec)
+
+lemma signed_take_bit_code [code]:
+  \<open>signed_take_bit n a =
+  (let l = take_bit (Suc n) a
+   in if bit l n then l + push_bit (Suc n) (- 1) else l)\<close>
+proof -
+  have *: \<open>take_bit (Suc n) a + push_bit n (- 2) =
+    take_bit (Suc n) a OR NOT (mask (Suc n))\<close>
+    by (auto simp add: bit_take_bit_iff bit_push_bit_iff bit_not_iff bit_mask_iff disjunctive_add
+       simp flip: push_bit_minus_one_eq_not_mask)
+  show ?thesis
+    by (rule bit_eqI)
+      (auto simp add: Let_def * bit_signed_take_bit_iff bit_take_bit_iff min_def less_Suc_eq bit_not_iff bit_mask_iff bit_or_iff)
+qed
+
+
+subsection \<open>Horner sums\<close>
+
+context semiring_bit_operations
+begin
+
+lemma horner_sum_bit_eq_take_bit:
+  \<open>horner_sum of_bool 2 (map (bit a) [0..<n]) = take_bit n a\<close>
+proof (induction a arbitrary: n rule: bits_induct)
+  case (stable a)
+  moreover have \<open>bit a = (\<lambda>_. odd a)\<close>
+    using stable by (simp add: stable_imp_bit_iff_odd fun_eq_iff)
+  moreover have \<open>{q. q < n} = {0..<n}\<close>
+    by auto
+  ultimately show ?case
+    by (simp add: stable_imp_take_bit_eq horner_sum_eq_sum mask_eq_sum_exp)
+next
+  case (rec a b)
+  show ?case
+  proof (cases n)
+    case 0
+    then show ?thesis
+      by simp
+  next
+    case (Suc m)
+    have \<open>map (bit (of_bool b + 2 * a)) [0..<Suc m] = b # map (bit (of_bool b + 2 * a)) [Suc 0..<Suc m]\<close>
+      by (simp only: upt_conv_Cons) simp
+    also have \<open>\<dots> = b # map (bit a) [0..<m]\<close>
+      by (simp only: flip: map_Suc_upt) (simp add: bit_Suc rec.hyps)
+    finally show ?thesis
+      using Suc rec.IH [of m] by (simp add: take_bit_Suc rec.hyps)
+        (simp_all add: ac_simps mod_2_eq_odd)
+  qed
+qed
+
+end
+
+context unique_euclidean_semiring_with_bit_operations
+begin
+
+lemma bit_horner_sum_bit_iff [bit_simps]:
+  \<open>bit (horner_sum of_bool 2 bs) n \<longleftrightarrow> n < length bs \<and> bs ! n\<close>
+proof (induction bs arbitrary: n)
+  case Nil
+  then show ?case
+    by simp
+next
+  case (Cons b bs)
+  show ?case
+  proof (cases n)
+    case 0
+    then show ?thesis
+      by simp
+  next
+    case (Suc m)
+    with bit_rec [of _ n] Cons.prems Cons.IH [of m]
+    show ?thesis by simp
+  qed
+qed
+
+lemma take_bit_horner_sum_bit_eq:
+  \<open>take_bit n (horner_sum of_bool 2 bs) = horner_sum of_bool 2 (take n bs)\<close>
+  by (auto simp add: bit_eq_iff bit_take_bit_iff bit_horner_sum_bit_iff)
+
+end
+
+lemma horner_sum_of_bool_2_less:
+  \<open>(horner_sum of_bool 2 bs :: int) < 2 ^ length bs\<close>
+proof -
+  have \<open>(\<Sum>n = 0..<length bs. of_bool (bs ! n) * (2::int) ^ n) \<le> (\<Sum>n = 0..<length bs. 2 ^ n)\<close>
+    by (rule sum_mono) simp
+  also have \<open>\<dots> = 2 ^ length bs - 1\<close>
+    by (induction bs) simp_all
+  finally show ?thesis
+    by (simp add: horner_sum_eq_sum)
+qed
+
+
+subsection \<open>Symbolic computations on numeral expressions\<close> \<^marker>\<open>contributor \<open>Andreas Lochbihler\<close>\<close>
+
+fun and_num :: \<open>num \<Rightarrow> num \<Rightarrow> num option\<close>
+where
+  \<open>and_num num.One num.One = Some num.One\<close>
+| \<open>and_num num.One (num.Bit0 n) = None\<close>
+| \<open>and_num num.One (num.Bit1 n) = Some num.One\<close>
+| \<open>and_num (num.Bit0 m) num.One = None\<close>
+| \<open>and_num (num.Bit0 m) (num.Bit0 n) = map_option num.Bit0 (and_num m n)\<close>
+| \<open>and_num (num.Bit0 m) (num.Bit1 n) = map_option num.Bit0 (and_num m n)\<close>
+| \<open>and_num (num.Bit1 m) num.One = Some num.One\<close>
+| \<open>and_num (num.Bit1 m) (num.Bit0 n) = map_option num.Bit0 (and_num m n)\<close>
+| \<open>and_num (num.Bit1 m) (num.Bit1 n) = (case and_num m n of None \<Rightarrow> Some num.One | Some n' \<Rightarrow> Some (num.Bit1 n'))\<close>
+
+fun and_not_num :: \<open>num \<Rightarrow> num \<Rightarrow> num option\<close>
+where
+  \<open>and_not_num num.One num.One = None\<close>
+| \<open>and_not_num num.One (num.Bit0 n) = Some num.One\<close>
+| \<open>and_not_num num.One (num.Bit1 n) = None\<close>
+| \<open>and_not_num (num.Bit0 m) num.One = Some (num.Bit0 m)\<close>
+| \<open>and_not_num (num.Bit0 m) (num.Bit0 n) = map_option num.Bit0 (and_not_num m n)\<close>
+| \<open>and_not_num (num.Bit0 m) (num.Bit1 n) = map_option num.Bit0 (and_not_num m n)\<close>
+| \<open>and_not_num (num.Bit1 m) num.One = Some (num.Bit0 m)\<close>
+| \<open>and_not_num (num.Bit1 m) (num.Bit0 n) = (case and_not_num m n of None \<Rightarrow> Some num.One | Some n' \<Rightarrow> Some (num.Bit1 n'))\<close>
+| \<open>and_not_num (num.Bit1 m) (num.Bit1 n) = map_option num.Bit0 (and_not_num m n)\<close>
+
+fun or_num :: \<open>num \<Rightarrow> num \<Rightarrow> num\<close>
+where
+  \<open>or_num num.One num.One = num.One\<close>
+| \<open>or_num num.One (num.Bit0 n) = num.Bit1 n\<close>
+| \<open>or_num num.One (num.Bit1 n) = num.Bit1 n\<close>
+| \<open>or_num (num.Bit0 m) num.One = num.Bit1 m\<close>
+| \<open>or_num (num.Bit0 m) (num.Bit0 n) = num.Bit0 (or_num m n)\<close>
+| \<open>or_num (num.Bit0 m) (num.Bit1 n) = num.Bit1 (or_num m n)\<close>
+| \<open>or_num (num.Bit1 m) num.One = num.Bit1 m\<close>
+| \<open>or_num (num.Bit1 m) (num.Bit0 n) = num.Bit1 (or_num m n)\<close>
+| \<open>or_num (num.Bit1 m) (num.Bit1 n) = num.Bit1 (or_num m n)\<close>
+
+fun or_not_num_neg :: \<open>num \<Rightarrow> num \<Rightarrow> num\<close>
+where
+  \<open>or_not_num_neg num.One num.One = num.One\<close>
+| \<open>or_not_num_neg num.One (num.Bit0 m) = num.Bit1 m\<close>
+| \<open>or_not_num_neg num.One (num.Bit1 m) = num.Bit1 m\<close>
+| \<open>or_not_num_neg (num.Bit0 n) num.One = num.Bit0 num.One\<close>
+| \<open>or_not_num_neg (num.Bit0 n) (num.Bit0 m) = Num.BitM (or_not_num_neg n m)\<close>
+| \<open>or_not_num_neg (num.Bit0 n) (num.Bit1 m) = num.Bit0 (or_not_num_neg n m)\<close>
+| \<open>or_not_num_neg (num.Bit1 n) num.One = num.One\<close>
+| \<open>or_not_num_neg (num.Bit1 n) (num.Bit0 m) = Num.BitM (or_not_num_neg n m)\<close>
+| \<open>or_not_num_neg (num.Bit1 n) (num.Bit1 m) = Num.BitM (or_not_num_neg n m)\<close>
+
+fun xor_num :: \<open>num \<Rightarrow> num \<Rightarrow> num option\<close>
+where
+  \<open>xor_num num.One num.One = None\<close>
+| \<open>xor_num num.One (num.Bit0 n) = Some (num.Bit1 n)\<close>
+| \<open>xor_num num.One (num.Bit1 n) = Some (num.Bit0 n)\<close>
+| \<open>xor_num (num.Bit0 m) num.One = Some (num.Bit1 m)\<close>
+| \<open>xor_num (num.Bit0 m) (num.Bit0 n) = map_option num.Bit0 (xor_num m n)\<close>
+| \<open>xor_num (num.Bit0 m) (num.Bit1 n) = Some (case xor_num m n of None \<Rightarrow> num.One | Some n' \<Rightarrow> num.Bit1 n')\<close>
+| \<open>xor_num (num.Bit1 m) num.One = Some (num.Bit0 m)\<close>
+| \<open>xor_num (num.Bit1 m) (num.Bit0 n) = Some (case xor_num m n of None \<Rightarrow> num.One | Some n' \<Rightarrow> num.Bit1 n')\<close>
+| \<open>xor_num (num.Bit1 m) (num.Bit1 n) = map_option num.Bit0 (xor_num m n)\<close>
+
+lemma int_numeral_and_num:
+  \<open>numeral m AND numeral n = (case and_num m n of None \<Rightarrow> 0 :: int | Some n' \<Rightarrow> numeral n')\<close>
+  by (induction m n rule: and_num.induct) (simp_all split: option.split)
+
+lemma and_num_eq_None_iff:
+  \<open>and_num m n = None \<longleftrightarrow> numeral m AND numeral n = (0::int)\<close>
+  by (simp add: int_numeral_and_num split: option.split)
+
+lemma and_num_eq_Some_iff:
+  \<open>and_num m n = Some q \<longleftrightarrow> numeral m AND numeral n = (numeral q :: int)\<close>
+  by (simp add: int_numeral_and_num split: option.split)
+
+lemma int_numeral_and_not_num:
+  \<open>numeral m AND NOT (numeral n) = (case and_not_num m n of None \<Rightarrow> 0 :: int | Some n' \<Rightarrow> numeral n')\<close>
+  by (induction m n rule: and_not_num.induct) (simp_all add: add_One BitM_inc_eq not_int_def split: option.split)
+
+lemma int_numeral_not_and_num:
+  \<open>NOT (numeral m) AND numeral n = (case and_not_num n m of None \<Rightarrow> 0 :: int | Some n' \<Rightarrow> numeral n')\<close>
+  using int_numeral_and_not_num [of n m] by (simp add: ac_simps)
+
+lemma and_not_num_eq_None_iff:
+  \<open>and_not_num m n = None \<longleftrightarrow> numeral m AND NOT (numeral n) = (0::int)\<close>
+  by (simp add: int_numeral_and_not_num split: option.split)
+
+lemma and_not_num_eq_Some_iff:
+  \<open>and_not_num m n = Some q \<longleftrightarrow> numeral m AND NOT (numeral n) = (numeral q :: int)\<close>
+  by (simp add: int_numeral_and_not_num split: option.split)
+
+lemma int_numeral_or_num:
+  \<open>numeral m OR numeral n = (numeral (or_num m n) :: int)\<close>
+  by (induction m n rule: or_num.induct) simp_all
+
+lemma numeral_or_num_eq:
+  \<open>numeral (or_num m n) = (numeral m OR numeral n :: int)\<close>
+  by (simp add: int_numeral_or_num)
+
+lemma int_numeral_or_not_num_neg:
+  \<open>numeral m OR NOT (numeral n :: int) = - numeral (or_not_num_neg m n)\<close>
+  by (induction m n rule: or_not_num_neg.induct) (simp_all add: add_One BitM_inc_eq not_int_def)
+
+lemma int_numeral_not_or_num_neg:
+  \<open>NOT (numeral m) OR (numeral n :: int) = - numeral (or_not_num_neg n m)\<close>
+  using int_numeral_or_not_num_neg [of n m] by (simp add: ac_simps)
+
+lemma numeral_or_not_num_eq:
+  \<open>numeral (or_not_num_neg m n) = - (numeral m OR NOT (numeral n :: int))\<close>
+  using int_numeral_or_not_num_neg [of m n] by simp
+
+lemma int_numeral_xor_num:
+  \<open>numeral m XOR numeral n = (case xor_num m n of None \<Rightarrow> 0 :: int | Some n' \<Rightarrow> numeral n')\<close>
+  by (induction m n rule: xor_num.induct) (simp_all split: option.split)
+
+lemma xor_num_eq_None_iff:
+  \<open>xor_num m n = None \<longleftrightarrow> numeral m XOR numeral n = (0::int)\<close>
+  by (simp add: int_numeral_xor_num split: option.split)
+
+lemma xor_num_eq_Some_iff:
+  \<open>xor_num m n = Some q \<longleftrightarrow> numeral m XOR numeral n = (numeral q :: int)\<close>
+  by (simp add: int_numeral_xor_num split: option.split)
+
+
+subsection \<open>Key ideas of bit operations\<close>
+
+text \<open>
+  When formalizing bit operations, it is tempting to represent