3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-07 06:33:23 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2021-05-03 12:41:14 -07:00
commit dc879dc3fb
74 changed files with 585 additions and 259 deletions

View file

@ -1,15 +1,6 @@
# Enforce some CMake policies # Enforce some CMake policies
cmake_minimum_required(VERSION 3.4) cmake_minimum_required(VERSION 3.4)
if (POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
if (POLICY CMP0042)
# Enable `MACOSX_RPATH` by default.
cmake_policy(SET CMP0042 NEW)
endif()
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake") set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake")
project(Z3 VERSION 4.8.11.0 LANGUAGES CXX) project(Z3 VERSION 4.8.11.0 LANGUAGES CXX)
@ -42,7 +33,7 @@ set(z3_polluted_tree_msg
################################################################################ ################################################################################
# Sanity check - Disallow building in source # Sanity check - Disallow building in source
################################################################################ ################################################################################
if ("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
message(FATAL_ERROR "In source builds are not allowed. You should invoke " message(FATAL_ERROR "In source builds are not allowed. You should invoke "
"CMake from a different directory.") "CMake from a different directory.")
endif() endif()
@ -194,28 +185,28 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
################################################################################ ################################################################################
# Platform detection # Platform detection
################################################################################ ################################################################################
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(STATUS "Platform: Linux") message(STATUS "Platform: Linux")
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_LINUX_") list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_LINUX_")
if ("${TARGET_ARCHITECTURE}" STREQUAL "x86_64") if (TARGET_ARCHITECTURE STREQUAL "x86_64")
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_USE_THREAD_LOCAL") list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_USE_THREAD_LOCAL")
endif() endif()
elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Android") elseif (CMAKE_SYSTEM_NAME STREQUAL "Android")
message(STATUS "Platform: Android") message(STATUS "Platform: Android")
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_ANDROID_") list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_ANDROID_")
elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "GNU") elseif (CMAKE_SYSTEM_NAME MATCHES "GNU")
message(STATUS "Platform: GNU/Hurd") message(STATUS "Platform: GNU/Hurd")
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_HURD_") list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_HURD_")
elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# Does macOS really not need any special flags? # Does macOS really not need any special flags?
message(STATUS "Platform: Darwin") message(STATUS "Platform: Darwin")
elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD") elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
message(STATUS "Platform: FreeBSD") message(STATUS "Platform: FreeBSD")
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_FREEBSD_") list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_FREEBSD_")
elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "NetBSD") elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
message(STATUS "Platform: NetBSD") message(STATUS "Platform: NetBSD")
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_NetBSD_") list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_NetBSD_")
elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD") elseif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
message(STATUS "Platform: OpenBSD") message(STATUS "Platform: OpenBSD")
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_OPENBSD_") list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_OPENBSD_")
elseif (CYGWIN) elseif (CYGWIN)
@ -251,8 +242,7 @@ if (Z3_USE_LIB_GMP)
# can't be found # can't be found
find_package(GMP REQUIRED) find_package(GMP REQUIRED)
message(STATUS "Using libgmp") message(STATUS "Using libgmp")
list(APPEND Z3_DEPENDENT_LIBS ${GMP_C_LIBRARIES}) list(APPEND Z3_DEPENDENT_LIBS GMP::GMP)
list(APPEND Z3_COMPONENT_EXTRA_INCLUDE_DIRS ${GMP_INCLUDE_DIRS})
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_MP_GMP") list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_MP_GMP")
else() else()
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_MP_INTERNAL") list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_MP_INTERNAL")
@ -292,18 +282,18 @@ endif()
# FP math # FP math
################################################################################ ################################################################################
# FIXME: Support ARM "-mfpu=vfp -mfloat-abi=hard" # FIXME: Support ARM "-mfpu=vfp -mfloat-abi=hard"
if (("${TARGET_ARCHITECTURE}" STREQUAL "x86_64") OR ("${TARGET_ARCHITECTURE}" STREQUAL "i686")) if ((TARGET_ARCHITECTURE STREQUAL "x86_64") OR (TARGET_ARCHITECTURE STREQUAL "i686"))
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")) if ((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Intel"))
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel") if (CMAKE_CXX_COMPILER_ID MATCHES "Intel")
# Intel's compiler requires linking with libiomp5 # Intel's compiler requires linking with libiomp5
list(APPEND Z3_DEPENDENT_LIBS "iomp5") list(APPEND Z3_DEPENDENT_LIBS "iomp5")
endif() endif()
set(SSE_FLAGS "-mfpmath=sse" "-msse" "-msse2") set(SSE_FLAGS "-mfpmath=sse" "-msse" "-msse2")
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Intel")
set(SSE_FLAGS "-mfpmath=sse" "-msse" "-msse2") set(SSE_FLAGS "-mfpmath=sse" "-msse" "-msse2")
# Intel's compiler requires linking with libiomp5 # Intel's compiler requires linking with libiomp5
list(APPEND Z3_DEPENDENT_LIBS "iomp5") list(APPEND Z3_DEPENDENT_LIBS "iomp5")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(SSE_FLAGS "/arch:SSE2") set(SSE_FLAGS "/arch:SSE2")
else() else()
message(FATAL_ERROR "Unknown compiler ${CMAKE_CXX_COMPILER_ID}") message(FATAL_ERROR "Unknown compiler ${CMAKE_CXX_COMPILER_ID}")
@ -320,7 +310,7 @@ endif()
################################################################################ ################################################################################
set(THREADS_PREFER_PTHREAD_FLAG TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads) find_package(Threads)
list(APPEND Z3_DEPENDENT_LIBS ${CMAKE_THREAD_LIBS_INIT}) list(APPEND Z3_DEPENDENT_LIBS Threads::Threads)
################################################################################ ################################################################################
# Compiler warnings # Compiler warnings
@ -411,7 +401,7 @@ if (Z3_ENABLE_CFI)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
z3_add_cxx_flag("-fsanitize=cfi" REQUIRED) z3_add_cxx_flag("-fsanitize=cfi" REQUIRED)
z3_add_cxx_flag("-fsanitize-cfi-cross-dso" REQUIRED) z3_add_cxx_flag("-fsanitize-cfi-cross-dso" REQUIRED)
elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
z3_add_cxx_flag("/guard:cf" REQUIRED) z3_add_cxx_flag("/guard:cf" REQUIRED)
message(STATUS "Enabling CFI for MSVC") message(STATUS "Enabling CFI for MSVC")
foreach (_build_type ${build_types_with_cfi}) foreach (_build_type ${build_types_with_cfi})
@ -428,14 +418,14 @@ endif()
################################################################################ ################################################################################
# MSVC specific flags inherited from old build system # MSVC specific flags inherited from old build system
################################################################################ ################################################################################
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
include(${PROJECT_SOURCE_DIR}/cmake/msvc_legacy_quirks.cmake) include(${PROJECT_SOURCE_DIR}/cmake/msvc_legacy_quirks.cmake)
endif() endif()
################################################################################ ################################################################################
# Pass /RELEASE to the linker so that checksums in PE files are calculated. # Pass /RELEASE to the linker so that checksums in PE files are calculated.
################################################################################ ################################################################################
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
string(APPEND CMAKE_EXE_LINKER_FLAGS " /RELEASE") string(APPEND CMAKE_EXE_LINKER_FLAGS " /RELEASE")
string(APPEND CMAKE_SHARED_LINKER_FLAGS " /RELEASE") string(APPEND CMAKE_SHARED_LINKER_FLAGS " /RELEASE")
endif() endif()

View file

@ -18,11 +18,11 @@ if (Z3_LINK_TIME_OPTIMIZATION)
set(_lto_compiler_flag "") set(_lto_compiler_flag "")
set(_lto_linker_flag "") set(_lto_linker_flag "")
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR if ((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR
("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")) (CMAKE_CXX_COMPILER_ID MATCHES "GNU"))
set(_lto_compiler_flag "-flto") set(_lto_compiler_flag "-flto")
set(_lto_linker_flag "-flto") set(_lto_linker_flag "-flto")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(_lto_compiler_flag "/GL") set(_lto_compiler_flag "/GL")
set(_lto_linker_flag "/LTCG") set(_lto_linker_flag "/LTCG")
else() else()

View file

@ -46,22 +46,22 @@ set(CLANG_WARNINGS_AS_ERRORS
################################################################################ ################################################################################
set(WARNING_FLAGS_TO_CHECK "") set(WARNING_FLAGS_TO_CHECK "")
set(WARNING_AS_ERROR_FLAGS_TO_CHECK "") set(WARNING_AS_ERROR_FLAGS_TO_CHECK "")
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS}) list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS})
list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_ONLY_WARNINGS}) list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_ONLY_WARNINGS})
list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS}) list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS})
list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_WARNINGS_AS_ERRORS}) list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_WARNINGS_AS_ERRORS})
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS}) list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS})
list(APPEND WARNING_FLAGS_TO_CHECK ${CLANG_ONLY_WARNINGS}) list(APPEND WARNING_FLAGS_TO_CHECK ${CLANG_ONLY_WARNINGS})
list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS}) list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS})
list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${CLANG_WARNINGS_AS_ERRORS}) list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${CLANG_WARNINGS_AS_ERRORS})
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
list(APPEND WARNING_FLAGS_TO_CHECK ${MSVC_WARNINGS}) list(APPEND WARNING_FLAGS_TO_CHECK ${MSVC_WARNINGS})
# CMake's default flags include /W3 already so remove them if # CMake's default flags include /W3 already so remove them if
# they already exist. # they already exist.
if ("${CMAKE_CXX_FLAGS}" MATCHES "/W3") if (CMAKE_CXX_FLAGS MATCHES "/W3")
string(REPLACE "/W3" "" _cmake_cxx_flags_remove_w3 "${CMAKE_CXX_FLAGS}") string(REPLACE "/W3" "" _cmake_cxx_flags_remove_w3 "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${_cmake_cxx_flags_remove_w3}" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS "${_cmake_cxx_flags_remove_w3}" CACHE STRING "" FORCE)
endif() endif()
@ -84,7 +84,7 @@ get_property(
PROPERTY PROPERTY
TYPE TYPE
) )
if ("${WARNINGS_AS_ERRORS_CACHE_VAR_TYPE}" STREQUAL "BOOL") if (WARNINGS_AS_ERRORS_CACHE_VAR_TYPE STREQUAL "BOOL")
message(WARNING "Detected legacy WARNINGS_AS_ERRORS option. Upgrading") message(WARNING "Detected legacy WARNINGS_AS_ERRORS option. Upgrading")
set(WARNINGS_AS_ERRORS_DEFAULT "${WARNINGS_AS_ERRORS}") set(WARNINGS_AS_ERRORS_DEFAULT "${WARNINGS_AS_ERRORS}")
# Delete old entry # Delete old entry
@ -106,25 +106,25 @@ set_property(
"ON;OFF;SERIOUS_ONLY" "ON;OFF;SERIOUS_ONLY"
) )
if ("${WARNINGS_AS_ERRORS}" STREQUAL "ON") if (WARNINGS_AS_ERRORS STREQUAL "ON")
message(STATUS "Treating compiler warnings as errors") message(STATUS "Treating compiler warnings as errors")
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")) if ((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "GNU"))
list(APPEND Z3_COMPONENT_CXX_FLAGS "-Werror") list(APPEND Z3_COMPONENT_CXX_FLAGS "-Werror")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
list(APPEND Z3_COMPONENT_CXX_FLAGS "/WX") list(APPEND Z3_COMPONENT_CXX_FLAGS "/WX")
else() else()
message(AUTHOR_WARNING "Unknown compiler") message(AUTHOR_WARNING "Unknown compiler")
endif() endif()
elseif ("${WARNINGS_AS_ERRORS}" STREQUAL "SERIOUS_ONLY") elseif (WARNINGS_AS_ERRORS STREQUAL "SERIOUS_ONLY")
message(STATUS "Treating only serious compiler warnings as errors") message(STATUS "Treating only serious compiler warnings as errors")
# Loop through the flags # Loop through the flags
foreach (flag ${WARNING_AS_ERROR_FLAGS_TO_CHECK}) foreach (flag ${WARNING_AS_ERROR_FLAGS_TO_CHECK})
# Add globally because some flags need to be passed at link time. # Add globally because some flags need to be passed at link time.
z3_add_cxx_flag("${flag}" GLOBAL) z3_add_cxx_flag("${flag}" GLOBAL)
endforeach() endforeach()
elseif ("${WARNINGS_AS_ERRORS}" STREQUAL "OFF") elseif (WARNINGS_AS_ERRORS STREQUAL "OFF")
message(STATUS "Not treating compiler warnings as errors") message(STATUS "Not treating compiler warnings as errors")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# Warnings as errors is off by default for MSVC so setting this # Warnings as errors is off by default for MSVC so setting this
# is not necessary but this duplicates the behaviour of the old # is not necessary but this duplicates the behaviour of the old
# build system. # build system.

View file

@ -26,7 +26,7 @@ function(add_git_dir_dependency GIT_DOT_FILE SUCCESS_VAR)
# git directory # git directory
file(READ "${GIT_DOT_FILE}" GIT_DOT_FILE_DATA LIMIT 512) file(READ "${GIT_DOT_FILE}" GIT_DOT_FILE_DATA LIMIT 512)
string(STRIP "${GIT_DOT_FILE_DATA}" GIT_DOT_FILE_DATA_STRIPPED) string(STRIP "${GIT_DOT_FILE_DATA}" GIT_DOT_FILE_DATA_STRIPPED)
if ("${GIT_DOT_FILE_DATA_STRIPPED}" MATCHES "^gitdir:[ ]*(.+)$") if (GIT_DOT_FILE_DATA_STRIPPED MATCHES "^gitdir:[ ]*(.+)$")
# Git worktree # Git worktree
message(STATUS "Found git worktree") message(STATUS "Found git worktree")
set(GIT_WORKTREE_DIR "${CMAKE_MATCH_1}") set(GIT_WORKTREE_DIR "${CMAKE_MATCH_1}")
@ -75,7 +75,7 @@ function(add_git_dir_dependency GIT_DOT_FILE SUCCESS_VAR)
file(READ "${GIT_HEAD_FILE}" GIT_HEAD_DATA LIMIT 128) file(READ "${GIT_HEAD_FILE}" GIT_HEAD_DATA LIMIT 128)
string(STRIP "${GIT_HEAD_DATA}" GIT_HEAD_DATA_STRIPPED) string(STRIP "${GIT_HEAD_DATA}" GIT_HEAD_DATA_STRIPPED)
if ("${GIT_HEAD_DATA_STRIPPED}" MATCHES "^ref:[ ]*(.+)$") if (GIT_HEAD_DATA_STRIPPED MATCHES "^ref:[ ]*(.+)$")
# HEAD points at a reference. # HEAD points at a reference.
set(GIT_REF "${CMAKE_MATCH_1}") set(GIT_REF "${CMAKE_MATCH_1}")
if (EXISTS "${GIT_DIR}/${GIT_REF}") if (EXISTS "${GIT_DIR}/${GIT_REF}")

View file

@ -13,52 +13,37 @@ find_library(GMP_C_LIBRARIES
NAMES gmp NAMES gmp
DOC "GMP C libraries" DOC "GMP C libraries"
) )
if (GMP_C_LIBRARIES)
message(STATUS "Found GMP C library: \"${GMP_C_LIBRARIES}\"")
else()
message(STATUS "Could not find GMP C library")
endif()
find_library(GMP_CXX_LIBRARIES find_library(GMP_CXX_LIBRARIES
NAMES gmpxx NAMES gmpxx
DOC "GMP C++ libraries" DOC "GMP C++ libraries"
) )
if (GMP_CXX_LIBRARIES)
message(STATUS "Found GMP C++ library: \"${GMP_CXX_LIBRARIES}\"")
else()
message(STATUS "Could not find GMP C++ library")
endif()
# Try to find headers # Try to find headers
find_path(GMP_C_INCLUDES find_path(GMP_C_INCLUDES
NAMES gmp.h NAMES gmp.h
DOC "GMP C header" DOC "GMP C header"
) )
if (GMP_C_INCLUDES)
message(STATUS "Found GMP C include path: \"${GMP_C_INCLUDES}\"")
else()
message(STATUS "Could not find GMP C include path")
endif()
find_path(GMP_CXX_INCLUDES find_path(GMP_CXX_INCLUDES
NAMES gmpxx.h NAMES gmpxx.h
DOC "GMP C++ header" DOC "GMP C++ header"
) )
if (GMP_CXX_INCLUDES)
message(STATUS "Found GMP C++ include path: \"${GMP_CXX_INCLUDES}\"")
else()
message(STATUS "Could not find GMP C++ include path")
endif()
if (GMP_C_LIBRARIES AND GMP_CXX_LIBRARIES AND GMP_C_INCLUDES AND GMP_CXX_INCLUDES)
set(GMP_INCLUDE_DIRS "${GMP_C_INCLUDES}" "${GMP_CXX_INCLUDES}")
list(REMOVE_DUPLICATES GMP_INCLUDE_DIRS)
message(STATUS "Found GMP")
else()
message(STATUS "Could not find GMP")
endif()
# TODO: We should check we can link some simple code against libgmp and libgmpxx # TODO: We should check we can link some simple code against libgmp and libgmpxx
# Handle QUIET and REQUIRED and check the necessary variables were set and if so # Handle QUIET and REQUIRED and check the necessary variables were set and if so
# set ``GMP_FOUND`` # set ``GMP_FOUND``
find_package_handle_standard_args(GMP DEFAULT_MSG GMP_INCLUDE_DIRS GMP_C_LIBRARIES GMP_CXX_LIBRARIES) find_package_handle_standard_args(GMP
REQUIRED_VARS GMP_C_LIBRARIES GMP_C_INCLUDES GMP_CXX_LIBRARIES GMP_CXX_INCLUDES)
if (GMP_FOUND)
set(GMP_INCLUDE_DIRS "${GMP_C_INCLUDES}" "${GMP_CXX_INCLUDES}")
list(REMOVE_DUPLICATES GMP_INCLUDE_DIRS)
if (NOT TARGET GMP::GMP)
add_library(GMP::GMP UNKNOWN IMPORTED)
set_target_properties(GMP::GMP PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${GMP_C_INCLUDES}"
IMPORTED_LOCATION "${GMP_C_LIBRARIES}")
endif()
endif()

View file

@ -22,7 +22,7 @@ set(Z3_MSVC_LEGACY_DEFINES
_UNICODE _UNICODE
) )
if ("${TARGET_ARCHITECTURE}" STREQUAL "x86_64") if (TARGET_ARCHITECTURE STREQUAL "x86_64")
list(APPEND Z3_MSVC_LEGACY_DEFINES "" list(APPEND Z3_MSVC_LEGACY_DEFINES ""
# Don't set `_LIB`. The old build system sets this for x86_64 release # Don't set `_LIB`. The old build system sets this for x86_64 release
# build. This flag doesn't seem to be documented but a stackoverflow # build. This flag doesn't seem to be documented but a stackoverflow
@ -57,10 +57,10 @@ endif()
# Note we don't set WIN32 or _WINDOWS because # Note we don't set WIN32 or _WINDOWS because
# CMake provides that for us. As a sanity check make sure the option # CMake provides that for us. As a sanity check make sure the option
# is present. # is present.
if (NOT "${CMAKE_CXX_FLAGS}" MATCHES "[-/]D[ ]*WIN32") if (NOT CMAKE_CXX_FLAGS MATCHES "[-/]D[ ]*WIN32")
message(FATAL_ERROR "\"/D WIN32\" is missing") message(FATAL_ERROR "\"/D WIN32\" is missing")
endif() endif()
if (NOT "${CMAKE_CXX_FLAGS}" MATCHES "[-/]D[ ]*_WINDOWS") if (NOT CMAKE_CXX_FLAGS MATCHES "[-/]D[ ]*_WINDOWS")
message(FATAL_ERROR "\"/D _WINDOWS\" is missing") message(FATAL_ERROR "\"/D _WINDOWS\" is missing")
endif() endif()
@ -82,7 +82,7 @@ endif()
# build system kept the frame pointer for all configurations # build system kept the frame pointer for all configurations
# except x86_64 release (I don't know why the frame pointer # except x86_64 release (I don't know why the frame pointer
# is kept for i686 release). # is kept for i686 release).
if ("${TARGET_ARCHITECTURE}" STREQUAL "x86_64") if (TARGET_ARCHITECTURE STREQUAL "x86_64")
list(APPEND Z3_COMPONENT_CXX_FLAGS list(APPEND Z3_COMPONENT_CXX_FLAGS
$<$<CONFIG:Debug>:${NO_OMIT_FRAME_POINTER_MSVC_FLAG}> $<$<CONFIG:Debug>:${NO_OMIT_FRAME_POINTER_MSVC_FLAG}>
$<$<CONFIG:MinSizeRel>:${NO_OMIT_FRAME_POINTER_MSVC_FLAG}> $<$<CONFIG:MinSizeRel>:${NO_OMIT_FRAME_POINTER_MSVC_FLAG}>
@ -91,7 +91,7 @@ else()
list(APPEND Z3_COMPONENT_CXX_FLAGS ${NO_OMIT_FRAME_POINTER_MSVC_FLAG}) list(APPEND Z3_COMPONENT_CXX_FLAGS ${NO_OMIT_FRAME_POINTER_MSVC_FLAG})
endif() endif()
if (("${TARGET_ARCHITECTURE}" STREQUAL "x86_64") OR ("${TARGET_ARCHITECTURE}" STREQUAL "i686")) if ((TARGET_ARCHITECTURE STREQUAL "x86_64") OR (TARGET_ARCHITECTURE STREQUAL "i686"))
# Use __cdecl calling convention. Apparently this is MSVC's default # Use __cdecl calling convention. Apparently this is MSVC's default
# but the old build system set it so for completeness set it too. # but the old build system set it so for completeness set it too.
# See https://msdn.microsoft.com/en-us/library/46t77ak2.aspx # See https://msdn.microsoft.com/en-us/library/46t77ak2.aspx
@ -153,9 +153,9 @@ string(APPEND CMAKE_SHARED_LINKER_FLAGS " /SUBSYSTEM:WINDOWS")
# in the old build system except release x86_64. We try to emulate this here but # in the old build system except release x86_64. We try to emulate this here but
# this is likely the wrong thing to do. # this is likely the wrong thing to do.
foreach (_build_type ${_build_types_as_upper}) foreach (_build_type ${_build_types_as_upper})
if ("${TARGET_ARCHITECTURE}" STREQUAL "x86_64" AND if (TARGET_ARCHITECTURE STREQUAL "x86_64" AND
("${_build_type}" STREQUAL "RELEASE" OR (_build_type STREQUAL "RELEASE" OR
"${_build_type}" STREQUAL "RELWITHDEBINFO") _build_type STREQUAL "RELWITHDEBINFO")
) )
message(AUTHOR_WARNING "Skipping legacy linker MSVC options for x86_64 ${_build_type}") message(AUTHOR_WARNING "Skipping legacy linker MSVC options for x86_64 ${_build_type}")
else() else()

View file

@ -28,7 +28,7 @@ add_executable(cpp_example example.cpp)
target_include_directories(cpp_example PRIVATE ${Z3_CXX_INCLUDE_DIRS}) target_include_directories(cpp_example PRIVATE ${Z3_CXX_INCLUDE_DIRS})
target_link_libraries(cpp_example PRIVATE ${Z3_LIBRARIES}) target_link_libraries(cpp_example PRIVATE ${Z3_LIBRARIES})
if ("${CMAKE_SYSTEM_NAME}" MATCHES "[Ww]indows") if (CMAKE_SYSTEM_NAME MATCHES "[Ww]indows")
# On Windows we need to copy the Z3 libraries # On Windows we need to copy the Z3 libraries
# into the same directory as the executable # into the same directory as the executable
# so that they can be found. # so that they can be found.

View file

@ -40,7 +40,7 @@ endif()
target_include_directories(c_example PRIVATE ${Z3_C_INCLUDE_DIRS}) target_include_directories(c_example PRIVATE ${Z3_C_INCLUDE_DIRS})
target_link_libraries(c_example PRIVATE ${Z3_LIBRARIES}) target_link_libraries(c_example PRIVATE ${Z3_LIBRARIES})
if ("${CMAKE_SYSTEM_NAME}" MATCHES "[Ww]indows") if (CMAKE_SYSTEM_NAME MATCHES "[Ww]indows")
# On Windows we need to copy the Z3 libraries # On Windows we need to copy the Z3 libraries
# into the same directory as the executable # into the same directory as the executable
# so that they can be found. # so that they can be found.

View file

@ -1,6 +1,6 @@
find_package(Dotnet REQUIRED) find_package(Dotnet REQUIRED)
if("${TARGET_ARCHITECTURE}" STREQUAL "i686") if(TARGET_ARCHITECTURE STREQUAL "i686")
set(Z3_DOTNET_PLATFORM "x86") set(Z3_DOTNET_PLATFORM "x86")
else() else()
set(Z3_DOTNET_PLATFORM "AnyCPU") set(Z3_DOTNET_PLATFORM "AnyCPU")

View file

@ -35,7 +35,7 @@ if (FORCE_CXX_LINKER)
) )
endif() endif()
if ("${CMAKE_SYSTEM_NAME}" MATCHES "[Ww]indows") if (CMAKE_SYSTEM_NAME MATCHES "[Ww]indows")
# On Windows we need to copy the Z3 libraries # On Windows we need to copy the Z3 libraries
# into the same directory as the executable # into the same directory as the executable
# so that they can be found. # so that they can be found.

View file

@ -177,6 +177,7 @@ def enumerate_sets(csolver, map):
yield ("MSS", csolver.to_c_lits(MSS)) yield ("MSS", csolver.to_c_lits(MSS))
map.block_down(MSS) map.block_down(MSS)
else: else:
seed = csolver.seed_from_core()
MUS = csolver.shrink(seed) MUS = csolver.shrink(seed)
yield ("MUS", csolver.to_c_lits(MUS)) yield ("MUS", csolver.to_c_lits(MUS))
map.block_up(MUS) map.block_up(MUS)

View file

@ -1,5 +1,5 @@
# Jupyter version of the Z3 Python Tutorial. # Jupyter version of the Z3 Python Tutorial.
Thanks to Peter Gragert, the Z3 tutorial guide is now available in the Jupyter notebook format. You can try it directly online from: Thanks to Peter Gragert, the Z3 tutorial guide is now available in the Jupyter notebook format.
https://z3examples-nbjorner.notebooks.azure.com/j/notebooks/guide.ipynb An online tutorial is available from https://github.com/philzook58/z3_tutorial

View file

@ -28,7 +28,7 @@ add_executable(z3_tptp5 tptp5.cpp tptp5.lex.cpp)
target_include_directories(z3_tptp5 PRIVATE ${Z3_CXX_INCLUDE_DIRS}) target_include_directories(z3_tptp5 PRIVATE ${Z3_CXX_INCLUDE_DIRS})
target_link_libraries(z3_tptp5 PRIVATE ${Z3_LIBRARIES}) target_link_libraries(z3_tptp5 PRIVATE ${Z3_LIBRARIES})
if ("${CMAKE_SYSTEM_NAME}" MATCHES "[Ww]indows") if (CMAKE_SYSTEM_NAME MATCHES "[Ww]indows")
# On Windows we need to copy the Z3 libraries # On Windows we need to copy the Z3 libraries
# into the same directory as the executable # into the same directory as the executable
# so that they can be found. # so that they can be found.

View file

@ -335,6 +335,7 @@ namespace z3 {
expr bool_const(char const * name); expr bool_const(char const * name);
expr int_const(char const * name); expr int_const(char const * name);
expr real_const(char const * name); expr real_const(char const * name);
expr string_const(char const * name);
expr bv_const(char const * name, unsigned sz); expr bv_const(char const * name, unsigned sz);
expr fpa_const(char const * name, unsigned ebits, unsigned sbits); expr fpa_const(char const * name, unsigned ebits, unsigned sbits);
@ -497,6 +498,7 @@ namespace z3 {
ast(context & c):object(c), m_ast(0) {} ast(context & c):object(c), m_ast(0) {}
ast(context & c, Z3_ast n):object(c), m_ast(n) { Z3_inc_ref(ctx(), m_ast); } ast(context & c, Z3_ast n):object(c), m_ast(n) { Z3_inc_ref(ctx(), m_ast); }
ast(ast const & s):object(s), m_ast(s.m_ast) { Z3_inc_ref(ctx(), m_ast); } ast(ast const & s):object(s), m_ast(s.m_ast) { Z3_inc_ref(ctx(), m_ast); }
ast(ast && s) noexcept : object(std::forward<object>(s)), m_ast(s.m_ast) { s.m_ast = nullptr; }
~ast() { if (m_ast) Z3_dec_ref(*m_ctx, m_ast); } ~ast() { if (m_ast) Z3_dec_ref(*m_ctx, m_ast); }
operator Z3_ast() const { return m_ast; } operator Z3_ast() const { return m_ast; }
operator bool() const { return m_ast != 0; } operator bool() const { return m_ast != 0; }
@ -508,6 +510,12 @@ namespace z3 {
m_ast = s.m_ast; m_ast = s.m_ast;
return *this; return *this;
} }
ast & operator=(ast && s) noexcept {
object::operator=(std::forward<object>(s));
m_ast = s.m_ast;
s.m_ast = nullptr;
return *this;
}
Z3_ast_kind kind() const { Z3_ast_kind r = Z3_get_ast_kind(ctx(), m_ast); check_error(); return r; } Z3_ast_kind kind() const { Z3_ast_kind r = Z3_get_ast_kind(ctx(), m_ast); check_error(); return r; }
unsigned hash() const { unsigned r = Z3_get_ast_hash(ctx(), m_ast); check_error(); return r; } unsigned hash() const { unsigned r = Z3_get_ast_hash(ctx(), m_ast); check_error(); return r; }
friend std::ostream & operator<<(std::ostream & out, ast const & n); friend std::ostream & operator<<(std::ostream & out, ast const & n);
@ -568,7 +576,6 @@ namespace z3 {
unsigned m_index; unsigned m_index;
public: public:
iterator(ast_vector_tpl const* v, unsigned i): m_vector(v), m_index(i) {} iterator(ast_vector_tpl const* v, unsigned i): m_vector(v), m_index(i) {}
iterator(iterator const& other): m_vector(other.m_vector), m_index(other.m_index) {}
bool operator==(iterator const& other) const noexcept { bool operator==(iterator const& other) const noexcept {
return other.m_index == m_index; return other.m_index == m_index;
@ -864,6 +871,36 @@ namespace z3 {
*/ */
bool is_well_sorted() const { bool r = Z3_is_well_sorted(ctx(), m_ast); check_error(); return r; } bool is_well_sorted() const { bool r = Z3_is_well_sorted(ctx(), m_ast); check_error(); return r; }
/**
\brief Return Boolean expression to test whether expression is inf
*/
expr mk_is_inf() const {
assert(is_fpa());
Z3_ast r = Z3_mk_fpa_is_infinite(ctx(), m_ast);
check_error();
return expr(ctx(), r);
}
/**
\brief Return Boolean expression to test for whether expression is a NaN
*/
expr mk_is_nan() const {
assert(is_fpa());
Z3_ast r = Z3_mk_fpa_is_nan(ctx(), m_ast);
check_error();
return expr(ctx(), r);
}
/**
\brief Convert this fpa into an IEEE BV
*/
expr mk_to_ieee_bv() const {
assert(is_fpa());
Z3_ast r = Z3_mk_fpa_to_ieee_bv(ctx(), m_ast);
check_error();
return expr(ctx(), r);
}
/** /**
\brief Return string representation of numeral or algebraic number \brief Return string representation of numeral or algebraic number
This method assumes the expression is numeral or algebraic This method assumes the expression is numeral or algebraic
@ -1271,6 +1308,21 @@ namespace z3 {
*/ */
friend expr fma(expr const& a, expr const& b, expr const& c, expr const& rm); friend expr fma(expr const& a, expr const& b, expr const& c, expr const& rm);
/**
\brief Create an expression of FloatingPoint sort from three bit-vector expressions
*/
friend expr fpa_fp(expr const& sgn, expr const& exp, expr const& sig);
/**
\brief Conversion of a floating-point term into a signed bit-vector.
*/
friend expr fpa_to_sbv(expr const& t, unsigned sz);
/**
\brief Conversion of a floating-point term into an unsigned bit-vector.
*/
friend expr fpa_to_ubv(expr const& t, unsigned sz);
/** /**
\brief sequence and regular expression operations. \brief sequence and regular expression operations.
+ is overloaded as sequence concatenation and regular expression union. + is overloaded as sequence concatenation and regular expression union.
@ -1291,7 +1343,7 @@ namespace z3 {
check_error(); check_error();
return expr(ctx(), r); return expr(ctx(), r);
} }
expr contains(expr const& s) { expr contains(expr const& s) const {
check_context(*this, s); check_context(*this, s);
Z3_ast r = Z3_mk_seq_contains(ctx(), *this, s); Z3_ast r = Z3_mk_seq_contains(ctx(), *this, s);
check_error(); check_error();
@ -1768,6 +1820,27 @@ namespace z3 {
return expr(a.ctx(), r); return expr(a.ctx(), r);
} }
inline expr fpa_fp(expr const& sgn, expr const& exp, expr const& sig) {
check_context(sgn, exp); check_context(exp, sig);
assert(sgn.is_bv() && exp.is_bv() && sig.is_bv());
Z3_ast r = Z3_mk_fpa_fp(sgn.ctx(), sgn, exp, sig);
sgn.check_error();
return expr(sgn.ctx(), r);
}
inline expr fpa_to_sbv(expr const& t, unsigned sz) {
assert(t.is_fpa());
Z3_ast r = Z3_mk_fpa_to_sbv(t.ctx(), t.ctx().fpa_rounding_mode(), t, sz);
t.check_error();
return expr(t.ctx(), r);
}
inline expr fpa_to_ubv(expr const& t, unsigned sz) {
assert(t.is_fpa());
Z3_ast r = Z3_mk_fpa_to_ubv(t.ctx(), t.ctx().fpa_rounding_mode(), t, sz);
t.check_error();
return expr(t.ctx(), r);
}
/** /**
\brief Create the if-then-else expression <tt>ite(c, t, e)</tt> \brief Create the if-then-else expression <tt>ite(c, t, e)</tt>
@ -1818,6 +1891,18 @@ namespace z3 {
inline expr slt(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvslt(a.ctx(), a, b)); } inline expr slt(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvslt(a.ctx(), a, b)); }
inline expr slt(expr const & a, int b) { return slt(a, a.ctx().num_val(b, a.get_sort())); } inline expr slt(expr const & a, int b) { return slt(a, a.ctx().num_val(b, a.get_sort())); }
inline expr slt(int a, expr const & b) { return slt(b.ctx().num_val(a, b.get_sort()), b); } inline expr slt(int a, expr const & b) { return slt(b.ctx().num_val(a, b.get_sort()), b); }
/**
\brief signed greater than or equal to operator for bitvectors.
*/
inline expr sge(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvsge(a.ctx(), a, b)); }
inline expr sge(expr const & a, int b) { return sge(a, a.ctx().num_val(b, a.get_sort())); }
inline expr sge(int a, expr const & b) { return sge(b.ctx().num_val(a, b.get_sort()), b); }
/**
\brief signed greater than operator for bitvectors.
*/
inline expr sgt(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvsgt(a.ctx(), a, b)); }
inline expr sgt(expr const & a, int b) { return sgt(a, a.ctx().num_val(b, a.get_sort())); }
inline expr sgt(int a, expr const & b) { return sgt(b.ctx().num_val(a, b.get_sort()), b); }
/** /**
@ -1985,8 +2070,7 @@ namespace z3 {
template<typename T> template<typename T>
template<typename T2> template<typename T2>
array<T>::array(ast_vector_tpl<T2> const & v):m_array(new T[v.size()]) { array<T>::array(ast_vector_tpl<T2> const & v):m_array(new T[v.size()]), m_size(v.size()) {
m_size = v.size();
for (unsigned i = 0; i < m_size; i++) { for (unsigned i = 0; i < m_size; i++) {
m_array[i] = v[i]; m_array[i] = v[i];
} }
@ -2937,8 +3021,16 @@ namespace z3 {
return *this; return *this;
} }
operator Z3_fixedpoint() const { return m_fp; } operator Z3_fixedpoint() const { return m_fp; }
void from_string(char const* s) { Z3_fixedpoint_from_string(ctx(), m_fp, s); check_error(); } expr_vector from_string(char const* s) {
void from_file(char const* s) { Z3_fixedpoint_from_file(ctx(), m_fp, s); check_error(); } Z3_ast_vector r = Z3_fixedpoint_from_string(ctx(), m_fp, s);
check_error();
return expr_vector(ctx(), r);
}
expr_vector from_file(char const* s) {
Z3_ast_vector r = Z3_fixedpoint_from_file(ctx(), m_fp, s);
check_error();
return expr_vector(ctx(), r);
}
void add_rule(expr& rule, symbol const& name) { Z3_fixedpoint_add_rule(ctx(), m_fp, rule, name); check_error(); } void add_rule(expr& rule, symbol const& name) { Z3_fixedpoint_add_rule(ctx(), m_fp, rule, name); check_error(); }
void add_fact(func_decl& f, unsigned * args) { Z3_fixedpoint_add_fact(ctx(), m_fp, f, f.arity(), args); check_error(); } void add_fact(func_decl& f, unsigned * args) { Z3_fixedpoint_add_fact(ctx(), m_fp, f, f.arity(), args); check_error(); }
check_result query(expr& q) { Z3_lbool r = Z3_fixedpoint_query(ctx(), m_fp, q); check_error(); return to_check_result(r); } check_result query(expr& q) { Z3_lbool r = Z3_fixedpoint_query(ctx(), m_fp, q); check_error(); return to_check_result(r); }
@ -3176,6 +3268,7 @@ namespace z3 {
inline expr context::bool_const(char const * name) { return constant(name, bool_sort()); } inline expr context::bool_const(char const * name) { return constant(name, bool_sort()); }
inline expr context::int_const(char const * name) { return constant(name, int_sort()); } inline expr context::int_const(char const * name) { return constant(name, int_sort()); }
inline expr context::real_const(char const * name) { return constant(name, real_sort()); } inline expr context::real_const(char const * name) { return constant(name, real_sort()); }
inline expr context::string_const(char const * name) { return constant(name, string_sort()); }
inline expr context::bv_const(char const * name, unsigned sz) { return constant(name, bv_sort(sz)); } inline expr context::bv_const(char const * name, unsigned sz) { return constant(name, bv_sort(sz)); }
inline expr context::fpa_const(char const * name, unsigned ebits, unsigned sbits) { return constant(name, fpa_sort(ebits, sbits)); } inline expr context::fpa_const(char const * name, unsigned ebits, unsigned sbits) { return constant(name, fpa_sort(ebits, sbits)); }

View file

@ -140,7 +140,7 @@ endforeach()
# Note, nuget package file names do not have the ${VER_REV} part. # Note, nuget package file names do not have the ${VER_REV} part.
set(Z3_DOTNET_NUPKG_VERSION "${VER_MAJOR}.${VER_MINOR}.${VER_BUILD}") set(Z3_DOTNET_NUPKG_VERSION "${VER_MAJOR}.${VER_MINOR}.${VER_BUILD}")
if("${TARGET_ARCHITECTURE}" STREQUAL "i686") if(TARGET_ARCHITECTURE STREQUAL "i686")
set(Z3_DOTNET_PLATFORM "x86") set(Z3_DOTNET_PLATFORM "x86")
else() else()
set(Z3_DOTNET_PLATFORM "AnyCPU") set(Z3_DOTNET_PLATFORM "AnyCPU")

View file

@ -83,6 +83,9 @@ ${Z3_DOTNET_COMPILE_ITEMS}
<Content Include="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libz3.so" Condition="Exists('${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libz3.so')"> <Content Include="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libz3.so" Condition="Exists('${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libz3.so')">
<PackagePath>runtimes\linux-x64\native</PackagePath> <PackagePath>runtimes\linux-x64\native</PackagePath>
</Content> </Content>
<Content Include="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libz3.dylib" Condition="Exists('${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libz3.dylib')">
<PackagePath>runtimes\macos\native</PackagePath>
</Content>
</ItemGroup> </ItemGroup>
<!-- Native binaries for x86; currently only Windows is supported. --> <!-- Native binaries for x86; currently only Windows is supported. -->

View file

@ -898,7 +898,8 @@ bool arith_util::is_extended_numeral(expr* term, rational& r) const {
continue; continue;
} }
if (is_mul(term)) { if (is_mul(term)) {
rational r(mul), n(0); r = mul;
rational n(0);
for (expr* arg : *to_app(term)) { for (expr* arg : *to_app(term)) {
if (!is_extended_numeral(arg, n)) if (!is_extended_numeral(arg, n))
return false; return false;
@ -907,7 +908,8 @@ bool arith_util::is_extended_numeral(expr* term, rational& r) const {
return true; return true;
} }
if (is_add(term)) { if (is_add(term)) {
rational r(0), n(0); rational n(0);
r = 0;
for (expr* arg : *to_app(term)) { for (expr* arg : *to_app(term)) {
if (!is_extended_numeral(arg, n)) if (!is_extended_numeral(arg, n))
return false; return false;
@ -921,8 +923,7 @@ bool arith_util::is_extended_numeral(expr* term, rational& r) const {
if (is_sub(term, t1, t2) && if (is_sub(term, t1, t2) &&
is_extended_numeral(t1, k1) && is_extended_numeral(t1, k1) &&
is_extended_numeral(t2, k2)) { is_extended_numeral(t2, k2)) {
r = k1 - k2; r = (k1 - k2) * mul;
r *= mul;
return true; return true;
} }
return false; return false;

View file

@ -718,7 +718,7 @@ void bv_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const
op_names.push_back(builtin_name("rotate_right",OP_ROTATE_RIGHT)); op_names.push_back(builtin_name("rotate_right",OP_ROTATE_RIGHT));
op_names.push_back(builtin_name("bit2bool", OP_BIT2BOOL)); op_names.push_back(builtin_name("bit2bool", OP_BIT2BOOL));
if (logic == symbol::null || logic == symbol("ALL") || logic == "QF_FD") { if (logic == symbol::null || logic == symbol("ALL") || logic == "QF_FD" || logic == "HORN") {
op_names.push_back(builtin_name("bvumul_noovfl",OP_BUMUL_NO_OVFL)); op_names.push_back(builtin_name("bvumul_noovfl",OP_BUMUL_NO_OVFL));
op_names.push_back(builtin_name("bvsmul_noovfl",OP_BSMUL_NO_OVFL)); op_names.push_back(builtin_name("bvsmul_noovfl",OP_BSMUL_NO_OVFL));
op_names.push_back(builtin_name("bvsmul_noudfl",OP_BSMUL_NO_UDFL)); op_names.push_back(builtin_name("bvsmul_noudfl",OP_BSMUL_NO_UDFL));
@ -827,6 +827,15 @@ bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, ex
return true; return true;
} }
bool bv_recognizers::is_repeat(expr const * e, expr*& arg, unsigned& n) const {
if (!is_app_of(e, get_fid(), OP_REPEAT))
return false;
arg = to_app(e)->get_arg(0);
n = to_app(e)->get_parameter(0).get_int();
return true;
}
bool bv_recognizers::is_bv2int(expr const* e, expr*& r) const { bool bv_recognizers::is_bv2int(expr const* e, expr*& r) const {
if (!is_bv2int(e)) return false; if (!is_bv2int(e)) return false;
r = to_app(e)->get_arg(0); r = to_app(e)->get_arg(0);

View file

@ -310,6 +310,7 @@ public:
unsigned get_extract_high(expr const * n) const { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); } unsigned get_extract_high(expr const * n) const { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); }
unsigned get_extract_low(expr const * n) const { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); } unsigned get_extract_low(expr const * n) const { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); }
bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b) const; bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b) const;
bool is_repeat(expr const * e, expr*& arg, unsigned& n) const;
bool is_bv2int(expr const * e, expr * & r) const; bool is_bv2int(expr const * e, expr * & r) const;
bool is_bv_add(expr const * e) const { return is_app_of(e, get_fid(), OP_BADD); } bool is_bv_add(expr const * e) const { return is_app_of(e, get_fid(), OP_BADD); }
bool is_bv_sub(expr const * e) const { return is_app_of(e, get_fid(), OP_BSUB); } bool is_bv_sub(expr const * e) const { return is_app_of(e, get_fid(), OP_BSUB); }

View file

@ -281,21 +281,36 @@ namespace euf {
VERIFY(n->num_args() == 0 || !n->merge_enabled() || m_table.contains(n)); VERIFY(n->num_args() == 0 || !n->merge_enabled() || m_table.contains(n));
} }
void egraph::set_value(enode* n, lbool value) { void egraph::set_value(enode* n, lbool value) {
force_push(); if (n->value() == l_undef) {
TRACE("euf", tout << bpp(n) << "\n";); force_push();
SASSERT(n->value() == l_undef); TRACE("euf", tout << bpp(n) << " := " << value << "\n";);
n->set_value(value); n->set_value(value);
m_updates.push_back(update_record(n, update_record::value_assignment())); m_updates.push_back(update_record(n, update_record::value_assignment()));
}
} }
void egraph::set_lbl_hash(enode* n) { void egraph::set_lbl_hash(enode* n) {
NOT_IMPLEMENTED_YET(); SASSERT(n->m_lbl_hash == -1);
// m_lbl_hash should be different from -1, if and only if,
// there is a pattern that contains the enode. So,
// I use a trail to restore the value of m_lbl_hash to -1.
m_updates.push_back(update_record(n, update_record::lbl_hash()));
unsigned h = hash_u(n->get_expr_id());
n->m_lbl_hash = h & (APPROX_SET_CAPACITY - 1);
// propagate modification to the root m_lbls set.
enode* r = n->get_root();
approx_set & r_lbls = r->m_lbls;
if (!r_lbls.may_contain(n->m_lbl_hash)) {
m_updates.push_back(update_record(r, update_record::lbl_set()));
r_lbls.insert(n->m_lbl_hash);
}
} }
void egraph::pop(unsigned num_scopes) { void egraph::pop(unsigned num_scopes) {
if (num_scopes <= m_num_scopes) { if (num_scopes <= m_num_scopes) {
m_num_scopes -= num_scopes; m_num_scopes -= num_scopes;
m_to_merge.reset();
return; return;
} }
num_scopes -= m_num_scopes; num_scopes -= m_num_scopes;
@ -355,6 +370,12 @@ namespace euf {
VERIFY(p.r1->value() != l_undef); VERIFY(p.r1->value() != l_undef);
p.r1->set_value(l_undef); p.r1->set_value(l_undef);
break; break;
case update_record::tag_t::is_lbl_hash:
p.r1->m_lbl_hash = p.m_lbl_hash;
break;
case update_record::tag_t::is_lbl_set:
p.r1->m_lbls.set(p.m_lbls);
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
@ -439,8 +460,8 @@ namespace euf {
auto rc = insert_table(p); auto rc = insert_table(p);
enode* p_other = rc.first; enode* p_other = rc.first;
SASSERT(m_table.contains_ptr(p) == (p_other == p)); SASSERT(m_table.contains_ptr(p) == (p_other == p));
if (p_other != p) if (p_other != p)
m_to_merge.push_back(to_merge(p_other, p, rc.second)); m_to_merge.push_back(to_merge(p_other, p, rc.second));
else else
r2->m_parents.push_back(p); r2->m_parents.push_back(p);
if (p->is_equality()) if (p->is_equality())
@ -704,8 +725,6 @@ namespace euf {
TRACE("euf", display(tout << bpp(n) << " is not closed under congruence\n");); TRACE("euf", display(tout << bpp(n) << " is not closed under congruence\n"););
UNREACHABLE(); UNREACHABLE();
} }
} }
std::ostream& egraph::display(std::ostream& out, unsigned max_args, enode* n) const { std::ostream& egraph::display(std::ostream& out, unsigned max_args, enode* n) const {
@ -765,7 +784,6 @@ namespace euf {
void egraph::copy_from(egraph const& src, std::function<void*(void*)>& copy_justification) { void egraph::copy_from(egraph const& src, std::function<void*(void*)>& copy_justification) {
SASSERT(m_scopes.empty()); SASSERT(m_scopes.empty());
SASSERT(src.m_scopes.empty());
SASSERT(m_nodes.empty()); SASSERT(m_nodes.empty());
ptr_vector<enode> old_expr2new_enode, args; ptr_vector<enode> old_expr2new_enode, args;
ast_translation tr(src.m, m); ast_translation tr(src.m, m);
@ -793,6 +811,9 @@ namespace euf {
merge(n2, n2t, n1->m_justification.copy(copy_justification)); merge(n2, n2t, n1->m_justification.copy(copy_justification));
} }
propagate(); propagate();
for (unsigned i = 0; i < src.m_scopes.size(); ++i)
push();
force_push();
} }
} }

View file

@ -102,9 +102,12 @@ namespace euf {
struct new_lits_qhead {}; struct new_lits_qhead {};
struct inconsistent {}; struct inconsistent {};
struct value_assignment {}; struct value_assignment {};
struct lbl_hash {};
struct lbl_set {};
enum class tag_t { is_set_parent, is_add_node, is_toggle_merge, enum class tag_t { is_set_parent, is_add_node, is_toggle_merge,
is_add_th_var, is_replace_th_var, is_new_lit, is_new_th_eq, is_add_th_var, is_replace_th_var, is_new_lit, is_new_th_eq,
is_new_th_eq_qhead, is_new_lits_qhead, is_inconsistent, is_value_assignment }; is_lbl_hash, is_new_th_eq_qhead, is_new_lits_qhead,
is_inconsistent, is_value_assignment, is_lbl_set };
tag_t tag; tag_t tag;
enode* r1; enode* r1;
enode* n1; enode* n1;
@ -116,6 +119,8 @@ namespace euf {
}; };
unsigned qhead; unsigned qhead;
bool m_inconsistent; bool m_inconsistent;
signed char m_lbl_hash;
unsigned long long m_lbls;
}; };
update_record(enode* r1, enode* n1, unsigned r2_num_parents) : update_record(enode* r1, enode* n1, unsigned r2_num_parents) :
tag(tag_t::is_set_parent), r1(r1), n1(n1), r2_num_parents(r2_num_parents) {} tag(tag_t::is_set_parent), r1(r1), n1(n1), r2_num_parents(r2_num_parents) {}
@ -139,6 +144,10 @@ namespace euf {
tag(tag_t::is_inconsistent), r1(nullptr), n1(nullptr), m_inconsistent(inc) {} tag(tag_t::is_inconsistent), r1(nullptr), n1(nullptr), m_inconsistent(inc) {}
update_record(enode* n, value_assignment) : update_record(enode* n, value_assignment) :
tag(tag_t::is_value_assignment), r1(n), n1(nullptr), qhead(0) {} tag(tag_t::is_value_assignment), r1(n), n1(nullptr), qhead(0) {}
update_record(enode* n, lbl_hash):
tag(tag_t::is_lbl_hash), r1(n), n1(nullptr), m_lbl_hash(n->m_lbl_hash) {}
update_record(enode* n, lbl_set):
tag(tag_t::is_lbl_set), r1(n), n1(nullptr), m_lbls(n->m_lbls.get()) {}
}; };
ast_manager& m; ast_manager& m;
svector<to_merge> m_to_merge; svector<to_merge> m_to_merge;

View file

@ -72,7 +72,7 @@ namespace euf {
void * etable::mk_table_for(unsigned arity, func_decl * d) { void * etable::mk_table_for(unsigned arity, func_decl * d) {
void * r; void * r;
SASSERT(d->get_arity() >= 1); SASSERT(d->get_arity() >= 1);
SASSERT(arity >= d->get_arity()); SASSERT(arity >= d->get_arity() || d->is_associative());
switch (arity) { switch (arity) {
case 1: case 1:
r = TAG(void*, alloc(unary_table), UNARY); r = TAG(void*, alloc(unary_table), UNARY);

View file

@ -336,8 +336,13 @@ br_status array_rewriter::mk_map_core(func_decl * f, unsigned num_args, expr * c
// //
quantifier* lam = nullptr; quantifier* lam = nullptr;
for (unsigned i = 0; i < num_args; ++i) { for (unsigned i = 0; i < num_args; ++i) {
if (is_lambda(args[i])) { if (is_lambda(args[i]))
lam = to_quantifier(args[i]); lam = to_quantifier(args[i]);
else if (m_util.is_const(args[i]))
continue;
else {
lam = nullptr;
break;
} }
} }
if (lam) { if (lam) {
@ -351,15 +356,6 @@ br_status array_rewriter::mk_map_core(func_decl * f, unsigned num_args, expr * c
lam = to_quantifier(a); lam = to_quantifier(a);
args1.push_back(lam->get_expr()); args1.push_back(lam->get_expr());
} }
else {
expr_ref_vector sel(m());
sel.push_back(a);
unsigned n = lam->get_num_decls();
for (unsigned i = 0; i < n; ++i) {
sel.push_back(m().mk_var(n - i - 1, lam->get_decl_sort(i)));
}
args1.push_back(m_util.mk_select(sel.size(), sel.data()));
}
} }
result = m().mk_app(f, args1.size(), args1.data()); result = m().mk_app(f, args1.size(), args1.data());
result = m().update_quantifier(lam, result); result = m().update_quantifier(lam, result);

View file

@ -437,7 +437,7 @@ namespace seq {
expr_ref t_eq_empty = mk_eq_empty(t); expr_ref t_eq_empty = mk_eq_empty(t);
// |t| = 0 => |s| = 0 or indexof(t,s,offset) = -1 // |t| = 0 => |s| = 0 or indexof(t,s,offset) = -1
// ~contains(t,s) <=> indexof(t,s,offset) = -1 // ~contains(t,s) => indexof(t,s,offset) = -1
add_clause(cnt, i_eq_m1); add_clause(cnt, i_eq_m1);
add_clause(~t_eq_empty, s_eq_empty, i_eq_m1); add_clause(~t_eq_empty, s_eq_empty, i_eq_m1);
@ -489,7 +489,7 @@ namespace seq {
// 0 <= offset & offset < len(t) => len(x) = offset // 0 <= offset & offset < len(t) => len(x) = offset
// 0 <= offset & offset < len(t) & indexof(y,s,0) = -1 => -1 = i // 0 <= offset & offset < len(t) & indexof(y,s,0) = -1 => -1 = i
// 0 <= offset & offset < len(t) & indexof(y,s,0) >= 0 => // 0 <= offset & offset < len(t) & indexof(y,s,0) >= 0 =>
// -1 = indexof(y,s,0) + offset = indexof(t, s, offset) // indexof(y,s,0) + offset = indexof(t, s, offset)
add_clause(~offset_ge_0, offset_ge_len, mk_seq_eq(t, mk_concat(x, y))); add_clause(~offset_ge_0, offset_ge_len, mk_seq_eq(t, mk_concat(x, y)));
add_clause(~offset_ge_0, offset_ge_len, mk_eq(mk_len(x), offset)); add_clause(~offset_ge_0, offset_ge_len, mk_eq(mk_len(x), offset));

View file

@ -1492,6 +1492,7 @@ seq_util::rex::info seq_util::rex::info::orelse(seq_util::rex::info const& i) co
seq_util::rex::info seq_util::rex::info::loop(unsigned lower, unsigned upper) const { seq_util::rex::info seq_util::rex::info::loop(unsigned lower, unsigned upper) const {
if (is_known()) { if (is_known()) {
unsigned m = min_length * lower; unsigned m = min_length * lower;
// Code review: this is not a complete overflow check.
if (m > 0 && (m < min_length || m < lower)) if (m > 0 && (m < min_length || m < lower))
m = UINT_MAX; m = UINT_MAX;
lbool loop_nullable = (nullable == l_true || lower == 0 ? l_true : nullable); lbool loop_nullable = (nullable == l_true || lower == 0 ? l_true : nullable);

View file

@ -104,7 +104,7 @@ void static_features::reset() {
m_num_aliens_per_family .reset(); m_num_aliens_per_family .reset();
m_num_theories = 0; m_num_theories = 0;
m_theories .reset(); m_theories .reset();
m_max_stack_depth = 500; m_max_stack_depth = 100;
flush_cache(); flush_cache();
} }
@ -404,10 +404,11 @@ void static_features::process(expr * e, bool form_ctx, bool or_and_ctx, bool ite
m_num_sharing++; m_num_sharing++;
return; return;
} }
if (stack_depth > m_max_stack_depth) { if (stack_depth > m_max_stack_depth) {
for (expr* arg : subterms(expr_ref(e, m))) for (expr* arg : subterms(expr_ref(e, m)))
if (get_depth(arg) <= 3 || is_quantifier(arg)) if (get_depth(arg) <= 3 || is_quantifier(arg))
process(arg, form_ctx, or_and_ctx, ite_ctx, stack_depth-10); process(arg, form_ctx, or_and_ctx, ite_ctx, stack_depth - 10);
return; return;
} }
mark(e); mark(e);

View file

@ -877,10 +877,11 @@ void cmd_context::insert(symbol const & s, func_decl * f) {
} }
void cmd_context::insert(symbol const & s, psort_decl * p) { void cmd_context::insert(symbol const & s, psort_decl * p) {
pm().inc_ref(p);
if (m_psort_decls.contains(s)) { if (m_psort_decls.contains(s)) {
pm().dec_ref(p);
throw cmd_exception("sort already defined ", s); throw cmd_exception("sort already defined ", s);
} }
pm().inc_ref(p);
m_psort_decls.insert(s, p); m_psort_decls.insert(s, p);
if (!m_global_decls) { if (!m_global_decls) {
m_psort_decls_stack.push_back(s); m_psort_decls_stack.push_back(s);
@ -1122,7 +1123,7 @@ bool cmd_context::try_mk_builtin_app(symbol const & s, unsigned num_args, expr *
result = m().mk_app(fid, k, num_indices, indices, num_args, args, range); result = m().mk_app(fid, k, num_indices, indices, num_args, args, range);
} }
CHECK_SORT(result.get()); CHECK_SORT(result.get());
return true; return nullptr != result.get();
} }
bool cmd_context::try_mk_declared_app(symbol const & s, unsigned num_args, expr * const * args, bool cmd_context::try_mk_declared_app(symbol const & s, unsigned num_args, expr * const * args,

View file

@ -1246,8 +1246,8 @@ namespace dd {
} }
else { else {
set_mark(r); set_mark(r);
m_todo.pop_back(); m_todo.push_back(lo(r));
m_todo.push_back(lo(r)).push_back(hi(r)); m_todo.push_back(hi(r));
} }
} }
return max_d; return max_d;

View file

@ -89,7 +89,7 @@ class hilbert_basis {
reslimit& m_limit; reslimit& m_limit;
vector<num_vector> m_ineqs; // set of asserted inequalities vector<num_vector> m_ineqs; // set of asserted inequalities
bool_vector m_iseq; // inequalities that are equalities bool_vector m_iseq; // inequalities that are equalities
num_vector m_store; // store of vectors mutable num_vector m_store; // store of vectors
svector<offset_t> m_basis; // vector of current basis svector<offset_t> m_basis; // vector of current basis
svector<offset_t> m_free_list; // free list of unused storage svector<offset_t> m_free_list; // free list of unused storage
svector<offset_t> m_active; // active set svector<offset_t> m_active; // active set

View file

@ -23,21 +23,30 @@ bool const_iterator_mon::get_factors(factor& k, factor& j, rational& sign) const
std::sort(k_vars.begin(), k_vars.end()); std::sort(k_vars.begin(), k_vars.end());
std::sort(j_vars.begin(), j_vars.end()); std::sort(j_vars.begin(), j_vars.end());
if (false && m_num_failures > 10) {
for (bool& m : m_mask) m = true;
m_mask[0] = false;
m_full_factorization_returned = true;
return false;
}
if (k_vars.size() == 1) { if (k_vars.size() == 1) {
k.set(k_vars[0], factor_type::VAR); k.set(k_vars[0], factor_type::VAR);
} else { } else {
unsigned i; unsigned i;
if (!m_ff->find_canonical_monic_of_vars(k_vars, i)) { if (!m_ff->find_canonical_monic_of_vars(k_vars, i)) {
++m_num_failures;
return false; return false;
} }
k.set(i, factor_type::MON); k.set(i, factor_type::MON);
} }
m_num_failures = 0;
if (j_vars.size() == 1) { if (j_vars.size() == 1) {
j.set(j_vars[0], factor_type::VAR); j.set(j_vars[0], factor_type::VAR);
} else { } else {
unsigned i; unsigned i;
if (!m_ff->find_canonical_monic_of_vars(j_vars, i)) { if (!m_ff->find_canonical_monic_of_vars(j_vars, i)) {
++m_num_failures;
return false; return false;
} }
j.set(i, factor_type::MON); j.set(i, factor_type::MON);
@ -46,7 +55,7 @@ bool const_iterator_mon::get_factors(factor& k, factor& j, rational& sign) const
} }
factorization const_iterator_mon::operator*() const { factorization const_iterator_mon::operator*() const {
if (m_full_factorization_returned == false) { if (!m_full_factorization_returned) {
return create_full_factorization(m_ff->m_monic); return create_full_factorization(m_ff->m_monic);
} }
factor j, k; rational sign; factor j, k; rational sign;

View file

@ -30,12 +30,12 @@ struct factorization_factory;
enum class factor_type { VAR, MON }; enum class factor_type { VAR, MON };
class factor { class factor {
lpvar m_var; lpvar m_var{ UINT_MAX };
factor_type m_type; factor_type m_type{ factor_type::VAR };
bool m_sign; bool m_sign{ false };
public: public:
factor(): factor(false) {} factor(): factor(false) {}
factor(bool sign): m_var(UINT_MAX), m_type(factor_type::VAR), m_sign(sign) {} factor(bool sign): m_sign(sign) {}
explicit factor(lpvar v, factor_type t) : m_var(v), m_type(t), m_sign(false) {} explicit factor(lpvar v, factor_type t) : m_var(v), m_type(t), m_sign(false) {}
unsigned var() const { return m_var; } unsigned var() const { return m_var; }
factor_type type() const { return m_type; } factor_type type() const { return m_type; }
@ -77,9 +77,10 @@ public:
struct const_iterator_mon { struct const_iterator_mon {
// fields // fields
bool_vector m_mask; mutable bool_vector m_mask;
const factorization_factory * m_ff; const factorization_factory * m_ff;
bool m_full_factorization_returned; mutable bool m_full_factorization_returned;
mutable unsigned m_num_failures{ 0 };
// typedefs // typedefs
typedef const_iterator_mon self_type; typedef const_iterator_mon self_type;

View file

@ -61,7 +61,7 @@ namespace lp {
return true; return true;
const lar_term* t = lra.terms()[i]; const lar_term* t = lra.terms()[i];
impq delta = get_cube_delta_for_term(*t); impq delta = get_cube_delta_for_term(*t);
TRACE("cube", lra.print_term_as_indices(*t, tout); tout << ", delta = " << delta;); TRACE("cube", lra.print_term_as_indices(*t, tout); tout << ", delta = " << delta << "\n";);
if (is_zero(delta)) if (is_zero(delta))
return true; return true;
return lra.tighten_term_bounds_by_delta(tv::term(i), delta); return lra.tighten_term_bounds_by_delta(tv::term(i), delta);

View file

@ -2331,15 +2331,16 @@ namespace lp {
v = flv; v = flv;
} }
m_incorrect_columns.insert(j); m_incorrect_columns.insert(j);
TRACE("cube", tout << "new val = " << v << "\n";); TRACE("cube", tout << "new val = " << v << " column: " << j << "\n";);
} }
if (m_incorrect_columns.size()) { if (!m_incorrect_columns.empty()) {
fix_terms_with_rounded_columns(); fix_terms_with_rounded_columns();
m_incorrect_columns.clear(); m_incorrect_columns.clear();
} }
} }
void lar_solver::fix_terms_with_rounded_columns() { void lar_solver::fix_terms_with_rounded_columns() {
for (unsigned i = 0; i < m_terms.size(); i++) { for (unsigned i = 0; i < m_terms.size(); i++) {
if (!term_is_used_as_row(i)) if (!term_is_used_as_row(i))
continue; continue;
@ -2357,8 +2358,10 @@ namespace lp {
m_mpq_lar_core_solver.m_r_solver.update_x(j, v); m_mpq_lar_core_solver.m_r_solver.update_x(j, v);
} }
} }
SASSERT(ax_is_correct()); SASSERT(ax_is_correct());
} }
// return true if all y coords are zeroes // return true if all y coords are zeroes
bool lar_solver::sum_first_coords(const lar_term& t, mpq& val) const { bool lar_solver::sum_first_coords(const lar_term& t, mpq& val) const {
val = zero_of_type<mpq>(); val = zero_of_type<mpq>();

View file

@ -66,7 +66,7 @@ namespace lp_api {
lp::constraint_index get_constraint(bool b) const { return m_constraints[b]; } lp::constraint_index get_constraint(bool b) const { return m_constraints[b]; }
inf_rational get_value(bool is_true) const { inf_rational get_value(bool is_true) const {
if (is_true) if (is_true != get_lit().sign())
return inf_rational(m_value); // v >= value or v <= value return inf_rational(m_value); // v >= value or v <= value
if (m_is_int) { if (m_is_int) {
SASSERT(m_value.is_int()); SASSERT(m_value.is_int());

View file

@ -34,7 +34,7 @@ public:
void flush() { void flush() {
SASSERT(b.size() == A.size()); SASSERT(b.size() == A.size());
unsigned sz = A.size(); auto sz = A.size();
for (unsigned i = 0; i < sz; i++) { for (unsigned i = 0; i < sz; i++) {
svector<numeral> & as = A[i]; svector<numeral> & as = A[i];
m.del(b[i]); m.del(b[i]);

View file

@ -4096,7 +4096,7 @@ namespace polynomial {
// select a new random value in GF(p) that is not in vals, and store it in r // select a new random value in GF(p) that is not in vals, and store it in r
void peek_fresh(scoped_numeral_vector const & vals, unsigned p, scoped_numeral & r) { void peek_fresh(scoped_numeral_vector const & vals, unsigned p, scoped_numeral & r) {
SASSERT(vals.size() < p); // otherwise we can't keep the fresh value SASSERT(vals.size() < p); // otherwise we can't keep the fresh value
unsigned sz = vals.size(); auto sz = vals.size();
while (true) { while (true) {
m().set(r, rand() % p); m().set(r, rand() % p);
// check if fresh value... // check if fresh value...
@ -6240,7 +6240,7 @@ namespace polynomial {
} }
void reset() { void reset() {
unsigned sz = m_xs.size(); auto sz = m_xs.size();
for (unsigned i = 0; i < sz; i++) { for (unsigned i = 0; i < sz; i++) {
m_max_degree[m_xs[i]] = 0; m_max_degree[m_xs[i]] = 0;
} }

View file

@ -2126,7 +2126,7 @@ namespace upolynomial {
} }
frame_stack.push_back(drs_frame(parent_idx, sz, true)); frame_stack.push_back(drs_frame(parent_idx, sz, true));
// right child // right child
translate(sz, p_stack.end() - sz, p_aux); translate(sz, p_stack.data() + p_stack.size() - sz, p_aux);
normalize(p_aux); normalize(p_aux);
for (unsigned i = 0; i < sz; i++) { for (unsigned i = 0; i < sz; i++) {
p_stack.push_back(numeral()); p_stack.push_back(numeral());
@ -2226,7 +2226,7 @@ namespace upolynomial {
drs_frame & fr = frame_stack.back(); drs_frame & fr = frame_stack.back();
unsigned sz = fr.m_size; unsigned sz = fr.m_size;
SASSERT(sz <= p_stack.size()); SASSERT(sz <= p_stack.size());
numeral const * p = p_stack.end() - sz; numeral const * p = p_stack.data() + p_stack.size() - sz;
TRACE("upolynomial", tout << "processing frame #" << frame_stack.size() - 1 << "\n" TRACE("upolynomial", tout << "processing frame #" << frame_stack.size() - 1 << "\n"
<< "first: " << fr.m_first << ", left: " << fr.m_left << ", sz: " << fr.m_size << ", parent_idx: "; << "first: " << fr.m_first << ", left: " << fr.m_left << ", sz: " << fr.m_size << ", parent_idx: ";
if (fr.m_parent_idx == UINT_MAX) tout << "<null>"; else tout << fr.m_parent_idx; if (fr.m_parent_idx == UINT_MAX) tout << "<null>"; else tout << fr.m_parent_idx;

View file

@ -39,8 +39,9 @@ namespace opt {
class model_based_opt { class model_based_opt {
public: public:
struct var { struct var {
unsigned m_id; unsigned m_id { 0 };
rational m_coeff; rational m_coeff;
var() {}
var(unsigned id, rational const& c): m_id(id), m_coeff(c) {} var(unsigned id, rational const& c): m_id(id), m_coeff(c) {}
struct compare { struct compare {
bool operator()(var x, var y) { bool operator()(var x, var y) {

View file

@ -616,7 +616,6 @@ struct model_evaluator::imp : public rewriter_tpl<mev::evaluator_cfg> {
false, // no proofs for evaluator false, // no proofs for evaluator
m_cfg), m_cfg),
m_cfg(md.get_manager(), md, p) { m_cfg(md.get_manager(), md, p) {
set_cancel_check(false);
} }
void expand_stores(expr_ref &val) {m_cfg.expand_stores(val);} void expand_stores(expr_ref &val) {m_cfg.expand_stores(val);}
void reset() { void reset() {

View file

@ -202,12 +202,14 @@ namespace opt {
return r; return r;
} }
void opt_solver::maximize_objectives(expr_ref_vector& blockers) { bool opt_solver::maximize_objectives1(expr_ref_vector& blockers) {
expr_ref blocker(m); expr_ref blocker(m);
for (unsigned i = 0; i < m_objective_vars.size(); ++i) { for (unsigned i = 0; i < m_objective_vars.size(); ++i) {
maximize_objective(i, blocker); if (!maximize_objective(i, blocker))
return false;
blockers.push_back(blocker); blockers.push_back(blocker);
} }
return true;
} }
lbool opt_solver::find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) { lbool opt_solver::find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) {
@ -238,7 +240,7 @@ namespace opt {
Precondition: the state of the solver is satisfiable and such that a current model can be extracted. Precondition: the state of the solver is satisfiable and such that a current model can be extracted.
*/ */
void opt_solver::maximize_objective(unsigned i, expr_ref& blocker) { bool opt_solver::maximize_objective(unsigned i, expr_ref& blocker) {
smt::theory_var v = m_objective_vars[i]; smt::theory_var v = m_objective_vars[i];
bool has_shared = false; bool has_shared = false;
m_last_model = nullptr; m_last_model = nullptr;
@ -256,8 +258,9 @@ namespace opt {
SASSERT(has_shared); SASSERT(has_shared);
decrement_value(i, val); decrement_value(i, val);
if (l_true != m_context.check(0, nullptr)) if (l_true != m_context.check(0, nullptr))
throw default_exception("maximization suspended"); return false;
m_context.get_model(m_last_model); m_context.get_model(m_last_model);
return true;
}; };
if (!val.is_finite()) { if (!val.is_finite()) {
@ -268,15 +271,15 @@ namespace opt {
m_last_model = nullptr; m_last_model = nullptr;
m_context.get_model(m_last_model); m_context.get_model(m_last_model);
if (has_shared && val != current_objective_value(i)) { if (has_shared && val != current_objective_value(i)) {
decrement(); if (!decrement())
return false;
} }
else { else {
m_models.set(i, m_last_model.get()); m_models.set(i, m_last_model.get());
} }
} }
else { else if (!decrement())
decrement(); return false;
}
m_objective_values[i] = val; m_objective_values[i] = val;
TRACE("opt", { TRACE("opt", {
tout << "objective: " << mk_pp(m_objective_terms[i].get(), m) << "\n"; tout << "objective: " << mk_pp(m_objective_terms[i].get(), m) << "\n";
@ -285,6 +288,7 @@ namespace opt {
if (m_models[i]) model_smt2_pp(tout << "update model:\n", m, *m_models[i], 0); if (m_models[i]) model_smt2_pp(tout << "update model:\n", m, *m_models[i], 0);
if (m_last_model) model_smt2_pp(tout << "last model:\n", m, *m_last_model, 0); if (m_last_model) model_smt2_pp(tout << "last model:\n", m, *m_last_model, 0);
}); });
return true;
} }
lbool opt_solver::decrement_value(unsigned i, inf_eps& val) { lbool opt_solver::decrement_value(unsigned i, inf_eps& val) {

View file

@ -119,8 +119,8 @@ namespace opt {
smt::theory_var add_objective(app* term); smt::theory_var add_objective(app* term);
void reset_objectives(); void reset_objectives();
void maximize_objective(unsigned i, expr_ref& blocker); bool maximize_objective(unsigned i, expr_ref& blocker);
void maximize_objectives(expr_ref_vector& blockers); bool maximize_objectives1(expr_ref_vector& blockers);
inf_eps const & saved_objective_value(unsigned obj_index); inf_eps const & saved_objective_value(unsigned obj_index);
inf_eps current_objective_value(unsigned obj_index); inf_eps current_objective_value(unsigned obj_index);
model* get_model_idx(unsigned obj_index) { return m_models[obj_index]; } model* get_model_idx(unsigned obj_index) { return m_models[obj_index]; }

View file

@ -321,7 +321,8 @@ namespace opt {
is_sat = m_s->check_sat(1,vars); is_sat = m_s->check_sat(1,vars);
if (is_sat == l_true) { if (is_sat == l_true) {
disj.reset(); disj.reset();
m_s->maximize_objectives(disj); if (!m_s->maximize_objectives1(disj))
return l_undef;
m_s->get_model(m_model); m_s->get_model(m_model);
m_s->get_labels(m_labels); m_s->get_labels(m_labels);
for (unsigned i = 0; i < ors.size(); ++i) { for (unsigned i = 0; i < ors.size(); ++i) {
@ -395,7 +396,8 @@ namespace opt {
expr_ref_vector disj(m); expr_ref_vector disj(m);
m_s->get_model(m_model); m_s->get_model(m_model);
m_s->get_labels(m_labels); m_s->get_labels(m_labels);
m_s->maximize_objectives(disj); if (!m_s->maximize_objectives1(disj))
return expr_ref(m.mk_true(), m);
set_max(m_lower, m_s->get_objective_values(), disj); set_max(m_lower, m_s->get_objective_values(), disj);
TRACE("opt", model_pp(tout << m_lower << "\n", *m_model);); TRACE("opt", model_pp(tout << m_lower << "\n", *m_model););
IF_VERBOSE(2, verbose_stream() << "(optsmt.lower " << m_lower << ")\n";); IF_VERBOSE(2, verbose_stream() << "(optsmt.lower " << m_lower << ")\n";);

View file

@ -1944,6 +1944,8 @@ namespace smt2 {
expr ** expr_it = expr_stack().data() + fr->m_expr_spos; expr ** expr_it = expr_stack().data() + fr->m_expr_spos;
expr ** expr_end = expr_it + num_decls; expr ** expr_end = expr_it + num_decls;
for (; expr_it != expr_end; ++expr_it, ++sym_it) { for (; expr_it != expr_end; ++expr_it, ++sym_it) {
if (!(*expr_it))
throw parser_exception("invalid let expression");
TRACE("let_frame", tout << "declaring: " << *sym_it << " " << mk_pp(*expr_it, m()) << "\n";); TRACE("let_frame", tout << "declaring: " << *sym_it << " " << mk_pp(*expr_it, m()) << "\n";);
m_env.insert(*sym_it, local(*expr_it, m_num_bindings)); m_env.insert(*sym_it, local(*expr_it, m_num_bindings));
} }
@ -2569,7 +2571,7 @@ namespace smt2 {
throw cmd_exception("invalid assert command, expression required as argument"); throw cmd_exception("invalid assert command, expression required as argument");
} }
expr * f = expr_stack().back(); expr * f = expr_stack().back();
if (!m().is_bool(f)) { if (!f || !m().is_bool(f)) {
TRACE("smt2parser", tout << expr_ref(f, m()) << "\n";); TRACE("smt2parser", tout << expr_ref(f, m()) << "\n";);
throw cmd_exception("invalid assert command, term is not Boolean"); throw cmd_exception("invalid assert command, term is not Boolean");
} }

View file

@ -68,7 +68,7 @@ namespace sat {
symbol m_name; symbol m_name;
solver* m_solver { nullptr }; solver* m_solver { nullptr };
public: public:
extension(symbol const& name, int id): m_id(id), m_name(name) {} extension(symbol const& name, int id): m_id(id), m_name(name) { }
virtual ~extension() {} virtual ~extension() {}
int get_id() const { return m_id; } int get_id() const { return m_id; }
void set_solver(solver* s) { m_solver = s; } void set_solver(solver* s) { m_solver = s; }

View file

@ -1296,7 +1296,7 @@ namespace sat {
return do_local_search(num_lits, lits); return do_local_search(num_lits, lits);
} }
if ((m_config.m_num_threads > 1 || m_config.m_local_search_threads > 0 || if ((m_config.m_num_threads > 1 || m_config.m_local_search_threads > 0 ||
m_config.m_ddfw_threads > 0) && !m_par) { m_config.m_ddfw_threads > 0) && !m_par && !m_ext) {
SASSERT(scope_lvl() == 0); SASSERT(scope_lvl() == 0);
return check_par(num_lits, lits); return check_par(num_lits, lits);
} }
@ -1440,6 +1440,9 @@ namespace sat {
if (!rlimit().inc()) { if (!rlimit().inc()) {
return l_undef; return l_undef;
} }
if (m_ext)
return l_undef;
scoped_ptr_vector<i_local_search> ls; scoped_ptr_vector<i_local_search> ls;
scoped_ptr_vector<solver> uw; scoped_ptr_vector<solver> uw;
int num_extra_solvers = m_config.m_num_threads - 1; int num_extra_solvers = m_config.m_num_threads - 1;

View file

@ -164,7 +164,7 @@ namespace arith {
unsigned index = 0; unsigned index = 0;
while (index < terms.size()) { while (index < terms.size()) {
SASSERT(index >= vars.size()); SASSERT(index >= vars.size());
expr* n = terms[index].get(); expr* n = terms.get(index);
st.to_ensure_enode().push_back(n); st.to_ensure_enode().push_back(n);
if (a.is_add(n)) { if (a.is_add(n)) {
for (expr* arg : *to_app(n)) { for (expr* arg : *to_app(n)) {
@ -382,7 +382,7 @@ namespace arith {
updt_unassigned_bounds(v, +1); updt_unassigned_bounds(v, +1);
m_bounds_trail.push_back(v); m_bounds_trail.push_back(v);
m_bool_var2bound.insert(bv, b); m_bool_var2bound.insert(bv, b);
TRACE("arith_verbose", tout << "Internalized " << bv << ": " << mk_pp(atom, m) << "\n";); TRACE("arith_verbose", tout << "Internalized " << lit << ": " << mk_pp(atom, m) << " " << *b << "\n";);
m_new_bounds.push_back(b); m_new_bounds.push_back(b);
//add_use_lists(b); //add_use_lists(b);
return true; return true;
@ -391,7 +391,7 @@ namespace arith {
bool solver::internalize_term(expr* term) { bool solver::internalize_term(expr* term) {
if (!has_var(term)) if (!has_var(term))
internalize_def(term); register_theory_var_in_lar_solver(internalize_def(term));
return true; return true;
} }
@ -583,11 +583,10 @@ namespace arith {
if (e->is_attached_to(get_id())) if (e->is_attached_to(get_id()))
return e->get_th_var(get_id()); return e->get_th_var(get_id());
theory_var v = mk_var(e); theory_var v = mk_var(e);
TRACE("arith", tout << "fresh var: v" << v << " " << mk_pp(n, m) << "\n";); TRACE("arith_verbose", tout << "v" << v << " " << mk_pp(n, m) << "\n";);
SASSERT(m_bounds.size() <= static_cast<unsigned>(v) || m_bounds[v].empty()); SASSERT(m_bounds.size() <= static_cast<unsigned>(v) || m_bounds[v].empty());
reserve_bounds(v); reserve_bounds(v);
ctx.attach_th_var(e, this, v); ctx.attach_th_var(e, this, v);
TRACE("arith", tout << mk_pp(n, m) << " " << v << "\n";);
SASSERT(euf::null_theory_var != v); SASSERT(euf::null_theory_var != v);
return v; return v;
} }

View file

@ -145,7 +145,7 @@ namespace arith {
bool v_is_int = b.is_int(); bool v_is_int = b.is_int();
literal lit2 = sat::null_literal; literal lit2 = sat::null_literal;
bool find_glb = (is_true == (k == lp_api::lower_t)); bool find_glb = (is_true == (k == lp_api::lower_t));
TRACE("arith", tout << "v" << v << " find_glb: " << find_glb << " is_true: " << is_true << " k: " << k << " is_lower: " << (k == lp_api::lower_t) << "\n";); TRACE("arith", tout << lit1 << " v" << v << " val " << val << " find_glb: " << find_glb << " is_true: " << is_true << " k: " << k << " is_lower: " << (k == lp_api::lower_t) << "\n";);
if (find_glb) { if (find_glb) {
rational glb; rational glb;
api_bound* lb = nullptr; api_bound* lb = nullptr;
@ -187,6 +187,7 @@ namespace arith {
m_params.push_back(parameter(m_farkas)); m_params.push_back(parameter(m_farkas));
m_params.push_back(parameter(rational(1))); m_params.push_back(parameter(rational(1)));
m_params.push_back(parameter(rational(1))); m_params.push_back(parameter(rational(1)));
TRACE("arith", tout << lit2 << " <- " << m_core << "\n";);
assign(lit2, m_core, m_eqs, m_params); assign(lit2, m_core, m_eqs, m_params);
++m_stats.m_bounds_propagations; ++m_stats.m_bounds_propagations;
} }
@ -1001,6 +1002,8 @@ namespace arith {
++m_stats.m_assume_eqs; ++m_stats.m_assume_eqs;
return sat::check_result::CR_CONTINUE; return sat::check_result::CR_CONTINUE;
} }
if (!check_delayed_eqs())
return sat::check_result::CR_CONTINUE;
if (m_not_handled != nullptr) { if (m_not_handled != nullptr) {
TRACE("arith", tout << "unhandled operator " << mk_pp(m_not_handled, m) << "\n";); TRACE("arith", tout << "unhandled operator " << mk_pp(m_not_handled, m) << "\n";);
return sat::check_result::CR_GIVEUP; return sat::check_result::CR_GIVEUP;

View file

@ -39,8 +39,10 @@ namespace array {
dep.add(n, p->get_arg(i)); dep.add(n, p->get_arg(i));
} }
for (euf::enode* k : euf::enode_class(n)) for (euf::enode* k : euf::enode_class(n))
if (a.is_const(k->get_expr())) if (a.is_const(k->get_expr()))
dep.add(n, k->get_arg(0)); dep.add(n, k->get_arg(0));
if (!dep.deps().contains(n))
dep.insert(n, nullptr);
return true; return true;
} }

View file

@ -31,6 +31,8 @@ namespace bv {
} }
void ackerman::reset() { void ackerman::reset() {
while (m_queue)
remove(m_queue->prev());
m_table.reset(); m_table.reset();
m_queue = nullptr; m_queue = nullptr;
} }

View file

@ -90,7 +90,7 @@ namespace bv {
m_wpos.push_back(0); m_wpos.push_back(0);
m_zero_one_bits.push_back(zero_one_bits()); m_zero_one_bits.push_back(zero_one_bits());
ctx.attach_th_var(n, this, r); ctx.attach_th_var(n, this, r);
TRACE("bv", tout << "mk-var: " << r << " " << n->get_expr_id() << " " << mk_bounded_pp(n->get_expr(), m) << "\n";); TRACE("bv", tout << "mk-var: v" << r << " " << n->get_expr_id() << " " << mk_bounded_pp(n->get_expr(), m) << "\n";);
return r; return r;
} }
@ -157,11 +157,15 @@ namespace bv {
std::function<void(unsigned sz, expr* const* xs, expr* const* ys, expr_ref& bit)> ebin; std::function<void(unsigned sz, expr* const* xs, expr* const* ys, expr_ref& bit)> ebin;
std::function<void(unsigned sz, expr* const* xs, expr_ref_vector& bits)> un; std::function<void(unsigned sz, expr* const* xs, expr_ref_vector& bits)> un;
std::function<void(unsigned sz, expr* const* xs, unsigned p, expr_ref_vector& bits)> pun; std::function<void(unsigned sz, expr* const* xs, unsigned p, expr_ref_vector& bits)> pun;
std::function<expr*(expr* x, expr* y)> ibin;
std::function<expr*(expr* x)> iun;
#define internalize_bin(F) bin = [&](unsigned sz, expr* const* xs, expr* const* ys, expr_ref_vector& bits) { m_bb.F(sz, xs, ys, bits); }; internalize_binary(a, bin); #define internalize_bin(F) bin = [&](unsigned sz, expr* const* xs, expr* const* ys, expr_ref_vector& bits) { m_bb.F(sz, xs, ys, bits); }; internalize_binary(a, bin);
#define internalize_un(F) un = [&](unsigned sz, expr* const* xs, expr_ref_vector& bits) { m_bb.F(sz, xs, bits);}; internalize_unary(a, un); #define internalize_un(F) un = [&](unsigned sz, expr* const* xs, expr_ref_vector& bits) { m_bb.F(sz, xs, bits);}; internalize_unary(a, un);
#define internalize_ac(F) bin = [&](unsigned sz, expr* const* xs, expr* const* ys, expr_ref_vector& bits) { m_bb.F(sz, xs, ys, bits); }; internalize_ac_binary(a, bin); #define internalize_ac(F) bin = [&](unsigned sz, expr* const* xs, expr* const* ys, expr_ref_vector& bits) { m_bb.F(sz, xs, ys, bits); }; internalize_ac_binary(a, bin);
#define internalize_pun(F) pun = [&](unsigned sz, expr* const* xs, unsigned p, expr_ref_vector& bits) { m_bb.F(sz, xs, p, bits);}; internalize_par_unary(a, pun); #define internalize_pun(F) pun = [&](unsigned sz, expr* const* xs, unsigned p, expr_ref_vector& bits) { m_bb.F(sz, xs, p, bits);}; internalize_par_unary(a, pun);
#define internalize_nfl(F) ebin = [&](unsigned sz, expr* const* xs, expr* const* ys, expr_ref& out) { m_bb.F(sz, xs, ys, out);}; internalize_novfl(a, ebin); #define internalize_nfl(F) ebin = [&](unsigned sz, expr* const* xs, expr* const* ys, expr_ref& out) { m_bb.F(sz, xs, ys, out);}; internalize_novfl(a, ebin);
#define internalize_int(B, U) ibin = [&](expr* x, expr* y) { return B(x, y); }; iun = [&](expr* x) { return U(x); }; internalize_interp(a, ibin, iun);
switch (a->get_decl_kind()) { switch (a->get_decl_kind()) {
case OP_BV_NUM: internalize_num(a); break; case OP_BV_NUM: internalize_num(a); break;
@ -209,10 +213,15 @@ namespace bv {
case OP_BSUB: internalize_sub(a); break; case OP_BSUB: internalize_sub(a); break;
case OP_CONCAT: internalize_concat(a); break; case OP_CONCAT: internalize_concat(a); break;
case OP_EXTRACT: internalize_extract(a); break; case OP_EXTRACT: internalize_extract(a); break;
case OP_REPEAT: internalize_repeat(a); break;
case OP_MKBV: internalize_mkbv(a); break; case OP_MKBV: internalize_mkbv(a); break;
case OP_INT2BV: internalize_int2bv(a); break; case OP_INT2BV: internalize_int2bv(a); break;
case OP_BV2INT: internalize_bv2int(a); break; case OP_BV2INT: internalize_bv2int(a); break;
case OP_BUDIV: internalize_udiv(a); break; case OP_BUDIV: internalize_int(bv.mk_bv_udiv_i, bv.mk_bv_udiv0); break;
case OP_BSDIV: internalize_int(bv.mk_bv_sdiv_i, bv.mk_bv_sdiv0); break;
case OP_BSREM: internalize_int(bv.mk_bv_srem_i, bv.mk_bv_srem0); break;
case OP_BUREM: internalize_int(bv.mk_bv_urem_i, bv.mk_bv_urem0); break;
case OP_BSMOD: internalize_int(bv.mk_bv_smod_i, bv.mk_bv_smod0); break;
case OP_BSDIV0: break; case OP_BSDIV0: break;
case OP_BUDIV0: break; case OP_BUDIV0: break;
case OP_BSREM0: break; case OP_BSREM0: break;
@ -280,6 +289,7 @@ namespace bv {
SASSERT(l == mk_true() || ~l == mk_true()); SASSERT(l == mk_true() || ~l == mk_true());
bool is_true = l == mk_true(); bool is_true = l == mk_true();
zero_one_bits& bits = m_zero_one_bits[v]; zero_one_bits& bits = m_zero_one_bits[v];
TRACE("bv", tout << "register v" << v << " " << l << " " << mk_true() << "\n";);
bits.push_back(zero_one_bit(v, idx, is_true)); bits.push_back(zero_one_bit(v, idx, is_true));
} }
@ -516,19 +526,20 @@ namespace bv {
internalize_binary(a, bin); internalize_binary(a, bin);
} }
void solver::internalize_udiv(app* n) { void solver::internalize_interp(app* n, std::function<expr*(expr*, expr*)>& ibin, std::function<expr*(expr*)>& iun) {
bv_rewriter_params p(s().params()); bv_rewriter_params p(s().params());
expr* arg1 = n->get_arg(0); expr* arg1 = n->get_arg(0);
expr* arg2 = n->get_arg(1); expr* arg2 = n->get_arg(1);
mk_bits(get_th_var(n));
if (p.hi_div0()) { if (p.hi_div0()) {
add_unit(eq_internalize(n, bv.mk_bv_udiv_i(arg1, arg2))); add_unit(eq_internalize(n, ibin(arg1, arg2)));
return; return;
} }
unsigned sz = bv.get_bv_size(n); unsigned sz = bv.get_bv_size(n);
expr_ref zero(bv.mk_numeral(0, sz), m); expr_ref zero(bv.mk_numeral(0, sz), m);
expr_ref eq(m.mk_eq(arg2, zero), m); expr_ref eq(m.mk_eq(arg2, zero), m);
expr_ref udiv(m.mk_ite(eq, bv.mk_bv_udiv0(arg1), bv.mk_bv_udiv_i(arg1, arg2)), m); expr_ref ite(m.mk_ite(eq, iun(arg1), ibin(arg1, arg2)), m);
add_unit(eq_internalize(n, udiv)); add_unit(eq_internalize(n, ite));
} }
void solver::internalize_unary(app* n, std::function<void(unsigned, expr* const*, expr_ref_vector&)>& fn) { void solver::internalize_unary(app* n, std::function<void(unsigned, expr* const*, expr_ref_vector&)>& fn) {
@ -559,7 +570,7 @@ namespace bv {
} }
void solver::internalize_ac_binary(app* e, std::function<void(unsigned, expr* const*, expr* const*, expr_ref_vector&)>& fn) { void solver::internalize_ac_binary(app* e, std::function<void(unsigned, expr* const*, expr* const*, expr_ref_vector&)>& fn) {
SASSERT(e->get_num_args() >= 2); SASSERT(e->get_num_args() >= 1);
expr_ref_vector bits(m), new_bits(m), arg_bits(m); expr_ref_vector bits(m), new_bits(m), arg_bits(m);
unsigned i = e->get_num_args() - 1; unsigned i = e->get_num_args() - 1;
get_arg_bits(e, i, bits); get_arg_bits(e, i, bits);
@ -632,6 +643,18 @@ namespace bv {
find_wpos(v); find_wpos(v);
} }
void solver::internalize_repeat(app* e) {
unsigned n = 0;
expr* arg = nullptr;
VERIFY(bv.is_repeat(e, arg, n));
expr_ref_vector conc(m);
for (unsigned i = 0; i < n; ++i)
conc.push_back(arg);
expr_ref r(bv.mk_concat(conc), m);
mk_bits(get_th_var(e));
add_unit(eq_internalize(e, r));
}
void solver::internalize_bit2bool(app* n) { void solver::internalize_bit2bool(app* n) {
unsigned idx = 0; unsigned idx = 0;
expr* arg = nullptr; expr* arg = nullptr;

View file

@ -93,8 +93,16 @@ namespace bv {
} while (curr != v); } while (curr != v);
zero_one_bits const& _bits = m_zero_one_bits[v]; zero_one_bits const& _bits = m_zero_one_bits[v];
if (_bits.size() != num_bits) if (_bits.size() != num_bits) {
std::cout << v << " " << _bits.size() << " " << num_bits << "\n"; std::cout << "v" << v << " " << _bits.size() << " " << num_bits << "\n";
std::cout << "true: " << mk_true() << "\n";
do {
std::cout << "v" << curr << ": " << m_bits[curr] << "\n";
curr = m_find.next(curr);
}
while (curr != v);
}
SASSERT(_bits.size() == num_bits);
VERIFY(_bits.size() == num_bits); VERIFY(_bits.size() == num_bits);
bool_vector already_found; bool_vector already_found;
already_found.resize(bv_sz, false); already_found.resize(bv_sz, false);

View file

@ -661,9 +661,10 @@ namespace bv {
result->m_bits[i].append(m_bits[i]); result->m_bits[i].append(m_bits[i]);
result->m_zero_one_bits[i].append(m_zero_one_bits[i]); result->m_zero_one_bits[i].append(m_zero_one_bits[i]);
} }
result->set_solver(&ctx.s());
for (theory_var i = 0; i < static_cast<theory_var>(get_num_vars()); ++i) for (theory_var i = 0; i < static_cast<theory_var>(get_num_vars()); ++i)
if (find(i) != i) if (find(i) != i)
result->m_find.merge(i, find(i)); result->m_find.set_root(i, find(i));
result->m_prop_queue.append(m_prop_queue); result->m_prop_queue.append(m_prop_queue);
for (unsigned i = 0; i < m_bool_var2atom.size(); ++i) { for (unsigned i = 0; i < m_bool_var2atom.size(); ++i) {
atom* a = m_bool_var2atom[i]; atom* a = m_bool_var2atom[i];

View file

@ -102,6 +102,9 @@ namespace bv {
unsigned m_is_true:1; unsigned m_is_true:1;
zero_one_bit(theory_var v = euf::null_theory_var, unsigned idx = UINT_MAX, bool is_true = false): zero_one_bit(theory_var v = euf::null_theory_var, unsigned idx = UINT_MAX, bool is_true = false):
m_owner(v), m_idx(idx), m_is_true(is_true) {} m_owner(v), m_idx(idx), m_is_true(is_true) {}
std::ostream& display(std::ostream& out) const {
return out << "v" << m_owner << " @ " << m_idx << " " << (m_is_true?"T":"F");
}
}; };
typedef svector<zero_one_bit> zero_one_bits; typedef svector<zero_one_bit> zero_one_bits;
@ -239,6 +242,7 @@ namespace bv {
void internalize_ac_binary(app* n, std::function<void(unsigned, expr* const*, expr* const*, expr_ref_vector&)>& fn); void internalize_ac_binary(app* n, std::function<void(unsigned, expr* const*, expr* const*, expr_ref_vector&)>& fn);
void internalize_par_unary(app* n, std::function<void(unsigned, expr* const*, unsigned p, expr_ref_vector&)>& fn); void internalize_par_unary(app* n, std::function<void(unsigned, expr* const*, unsigned p, expr_ref_vector&)>& fn);
void internalize_novfl(app* n, std::function<void(unsigned, expr* const*, expr* const*, expr_ref&)>& fn); void internalize_novfl(app* n, std::function<void(unsigned, expr* const*, expr* const*, expr_ref&)>& fn);
void internalize_interp(app* n, std::function<expr*(expr*, expr*)>& ibin, std::function<expr*(expr*)>& un);
void internalize_num(app * n); void internalize_num(app * n);
void internalize_concat(app * n); void internalize_concat(app * n);
void internalize_bv2int(app* n); void internalize_bv2int(app* n);
@ -248,8 +252,8 @@ namespace bv {
void internalize_carry(app* n); void internalize_carry(app* n);
void internalize_sub(app* n); void internalize_sub(app* n);
void internalize_extract(app* n); void internalize_extract(app* n);
void internalize_repeat(app* n);
void internalize_bit2bool(app* n); void internalize_bit2bool(app* n);
void internalize_udiv(app* n);
void internalize_udiv_i(app* n); void internalize_udiv_i(app* n);
template<bool Signed, bool Reverse, bool Negated> template<bool Signed, bool Reverse, bool Negated>
void internalize_le(app* n); void internalize_le(app* n);
@ -366,9 +370,12 @@ namespace bv {
typedef std::pair<solver const*, theory_var> pp_var; typedef std::pair<solver const*, theory_var> pp_var;
pp_var pp(theory_var v) const { return pp_var(this, v); } pp_var pp(theory_var v) const { return pp_var(this, v); }
friend std::ostream& operator<<(std::ostream& out, solver::zero_one_bit const& zo) { return zo.display(out); }
}; };
inline std::ostream& operator<<(std::ostream& out, solver::pp_var const& p) { return p.first->display(out, p.second); } inline std::ostream& operator<<(std::ostream& out, solver::pp_var const& p) { return p.first->display(out, p.second); }
} }

View file

@ -63,6 +63,7 @@ namespace dt {
SASSERT(s.m_to_unmark2.empty()); SASSERT(s.m_to_unmark2.empty());
s.m_used_eqs.reset(); s.m_used_eqs.reset();
s.m_dfs.reset(); s.m_dfs.reset();
s.m_parent.reset();
} }
solver::final_check_st::~final_check_st() { solver::final_check_st::~final_check_st() {
@ -692,6 +693,10 @@ namespace dt {
void solver::add_value(euf::enode* n, model& mdl, expr_ref_vector& values) { void solver::add_value(euf::enode* n, model& mdl, expr_ref_vector& values) {
theory_var v = n->get_th_var(get_id()); theory_var v = n->get_th_var(get_id());
if (v == euf::null_theory_var) {
values.set(n->get_root_id(), mdl.get_fresh_value(n->get_sort()));
return;
}
v = m_find.find(v); v = m_find.find(v);
SASSERT(v != euf::null_theory_var); SASSERT(v != euf::null_theory_var);
enode* con = m_var_data[v]->m_constructor; enode* con = m_var_data[v]->m_constructor;
@ -703,9 +708,11 @@ namespace dt {
} }
bool solver::add_dep(euf::enode* n, top_sort<euf::enode>& dep) { bool solver::add_dep(euf::enode* n, top_sort<euf::enode>& dep) {
theory_var v = n->get_th_var(get_id());
if (!is_datatype(n->get_expr())) if (!is_datatype(n->get_expr()))
return true; return false;
theory_var v = n->get_th_var(get_id());
if (v == euf::null_theory_var)
return false;
euf::enode* con = m_var_data[m_find.find(v)]->m_constructor; euf::enode* con = m_var_data[m_find.find(v)]->m_constructor;
if (con->num_args() == 0) if (con->num_args() == 0)
dep.insert(n, nullptr); dep.insert(n, nullptr);
@ -715,10 +722,8 @@ namespace dt {
} }
sat::literal solver::internalize(expr* e, bool sign, bool root, bool redundant) { sat::literal solver::internalize(expr* e, bool sign, bool root, bool redundant) {
if (!visit_rec(m, e, sign, root, redundant)) { if (!visit_rec(m, e, sign, root, redundant))
TRACE("dt", tout << mk_pp(e, m) << "\n";); return sat::null_literal;
return sat::null_literal;
}
auto lit = ctx.expr2literal(e); auto lit = ctx.expr2literal(e);
if (sign) if (sign)
lit.neg(); lit.neg();

View file

@ -141,8 +141,7 @@ namespace euf {
} }
m_bool_var2expr.reserve(v + 1, nullptr); m_bool_var2expr.reserve(v + 1, nullptr);
if (m_bool_var2expr[v]) { if (m_bool_var2expr[v] && m_egraph.find(e)) {
SASSERT(m_egraph.find(e));
SASSERT(m_egraph.find(e)->bool_var() == v); SASSERT(m_egraph.find(e)->bool_var() == v);
return lit; return lit;
} }
@ -158,6 +157,8 @@ namespace euf {
m_egraph.set_merge_enabled(n, false); m_egraph.set_merge_enabled(n, false);
if (!si.is_bool_op(e)) if (!si.is_bool_op(e))
track_relevancy(lit.var()); track_relevancy(lit.var());
if (s().value(lit) != l_undef)
m_egraph.set_value(n, s().value(lit));
return lit; return lit;
} }

View file

@ -48,8 +48,10 @@ namespace euf {
if (s().inconsistent()) if (s().inconsistent())
return; return;
for (enode* n : m_egraph.nodes()) for (enode* n : m_egraph.nodes())
if (m.is_false(n->get_root()->get_expr()) && m.is_eq(n->get_expr()) && if (m.is_false(n->get_root()->get_expr()) &&
n->get_arg(0)->get_root() == n->get_arg(1)->get_root()) { m.is_eq(n->get_expr()) &&
!m.is_bool(n->get_app()->get_arg(0)) &&
(n->get_arg(0)->get_root() == n->get_arg(1)->get_root())) {
enable_trace("euf"); enable_trace("euf");
TRACE("euf", display(tout << n->get_expr_id() << ": " << mk_pp(n->get_expr(), m) << "\n" TRACE("euf", display(tout << n->get_expr_id() << ": " << mk_pp(n->get_expr(), m) << "\n"
<< "#" << n->get_arg(0)->get_expr_id() << " == #" << n->get_arg(1)->get_expr_id() << " r: " << n->get_arg(0)->get_root_id() << "\n"); << "#" << n->get_arg(0)->get_expr_id() << " == #" << n->get_arg(1)->get_expr_id() << " r: " << n->get_arg(0)->get_root_id() << "\n");

View file

@ -144,6 +144,16 @@ namespace euf {
m_values.set(id, m.mk_false()); m_values.set(id, m.mk_false());
continue; continue;
} }
switch (n->value()) {
case l_true:
m_values.set(id, m.mk_true());
continue;
case l_false:
m_values.set(id, m.mk_false());
continue;
default:
break;
}
if (is_app(e) && to_app(e)->get_family_id() == m.get_basic_family_id()) if (is_app(e) && to_app(e)->get_family_id() == m.get_basic_family_id())
continue; continue;
sat::bool_var v = get_enode(e)->bool_var(); sat::bool_var v = get_enode(e)->bool_var();
@ -198,6 +208,7 @@ namespace euf {
fi = alloc(func_interp, m, arity); fi = alloc(func_interp, m, arity);
mdl->register_decl(f, fi); mdl->register_decl(f, fi);
} }
TRACE("euf", tout << f->get_name() << "\n";);
args.reset(); args.reset();
for (enode* arg : enode_args(n)) for (enode* arg : enode_args(n))
args.push_back(m_values.get(arg->get_root_id())); args.push_back(m_values.get(arg->get_root_id()));

View file

@ -410,10 +410,8 @@ namespace q {
mam::ground_subterms(pat, m_ground); mam::ground_subterms(pat, m_ground);
for (expr* g : m_ground) { for (expr* g : m_ground) {
euf::enode* n = ctx.get_egraph().find(g); euf::enode* n = ctx.get_egraph().find(g);
if (!n->is_attached_to(m_qs.get_id())) { if (!n->is_attached_to(m_qs.get_id()))
euf::theory_var v = m_qs.mk_var(n); m_qs.mk_var(n);
ctx.get_egraph().add_th_var(n, v, m_qs.get_id());
}
} }
} }

View file

@ -96,7 +96,6 @@ namespace q {
} }
euf::theory_var solver::mk_var(euf::enode* n) { euf::theory_var solver::mk_var(euf::enode* n) {
SASSERT(is_forall(n->get_expr()) || is_exists(n->get_expr()));
auto v = euf::th_euf_solver::mk_var(n); auto v = euf::th_euf_solver::mk_var(n);
ctx.attach_th_var(n, this, v); ctx.attach_th_var(n, this, v);
return v; return v;

View file

@ -162,13 +162,13 @@ namespace smt {
The variables are replaced by skolem constants. These constants are stored in sks. The variables are replaced by skolem constants. These constants are stored in sks.
*/ */
void model_checker::assert_neg_q_m(quantifier * q, expr_ref_vector & sks) { bool model_checker::assert_neg_q_m(quantifier * q, expr_ref_vector & sks) {
expr_ref tmp(m); expr_ref tmp(m);
TRACE("model_checker", tout << "curr_model:\n"; model_pp(tout, *m_curr_model);); TRACE("model_checker", tout << "curr_model:\n"; model_pp(tout, *m_curr_model););
if (!m_curr_model->eval(q->get_expr(), tmp, true)) { if (!m_curr_model->eval(q->get_expr(), tmp, true)) {
return; return false;
} }
TRACE("model_checker", tout << "q after applying interpretation:\n" << mk_ismt2_pp(tmp, m) << "\n";); TRACE("model_checker", tout << "q after applying interpretation:\n" << mk_ismt2_pp(tmp, m) << "\n";);
ptr_buffer<expr> subst_args; ptr_buffer<expr> subst_args;
@ -191,6 +191,7 @@ namespace smt {
r = m.mk_not(sk_body); r = m.mk_not(sk_body);
TRACE("model_checker", tout << "mk_neg_q_m:\n" << mk_ismt2_pp(r, m) << "\n";); TRACE("model_checker", tout << "mk_neg_q_m:\n" << mk_ismt2_pp(r, m) << "\n";);
m_aux_context->assert_expr(r); m_aux_context->assert_expr(r);
return true;
} }
bool model_checker::add_instance(quantifier * q, model * cex, expr_ref_vector & sks, bool use_inv) { bool model_checker::add_instance(quantifier * q, model * cex, expr_ref_vector & sks, bool use_inv) {
@ -333,7 +334,8 @@ namespace smt {
TRACE("model_checker", tout << "model checking:\n" << expr_ref(flat_q->get_expr(), m) << "\n";); TRACE("model_checker", tout << "model checking:\n" << expr_ref(flat_q->get_expr(), m) << "\n";);
expr_ref_vector sks(m); expr_ref_vector sks(m);
assert_neg_q_m(flat_q, sks); if (!assert_neg_q_m(flat_q, sks))
return false;
TRACE("model_checker", tout << "skolems:\n" << sks << "\n";); TRACE("model_checker", tout << "skolems:\n" << sks << "\n";);
flet<bool> l(m_aux_context->get_fparams().m_array_fake_support, true); flet<bool> l(m_aux_context->get_fparams().m_array_fake_support, true);

View file

@ -62,7 +62,7 @@ namespace smt {
expr * get_type_compatible_term(expr * val); expr * get_type_compatible_term(expr * val);
expr_ref replace_value_from_ctx(expr * e); expr_ref replace_value_from_ctx(expr * e);
void restrict_to_universe(expr * sk, obj_hashtable<expr> const & universe); void restrict_to_universe(expr * sk, obj_hashtable<expr> const & universe);
void assert_neg_q_m(quantifier * q, expr_ref_vector & sks); bool assert_neg_q_m(quantifier * q, expr_ref_vector & sks);
bool add_blocking_clause(model * cex, expr_ref_vector & sks); bool add_blocking_clause(model * cex, expr_ref_vector & sks);
bool check(quantifier * q); bool check(quantifier * q);
void check_quantifiers(bool& found_relevant, unsigned& num_failures); void check_quantifiers(bool& found_relevant, unsigned& num_failures);

View file

@ -74,7 +74,6 @@ namespace smt {
for (auto const& kv : m_elems) { for (auto const& kv : m_elems) {
m.dec_ref(kv.m_key); m.dec_ref(kv.m_key);
} }
m_elems.reset();
} }
obj_map<expr, unsigned> const& get_elems() const { return m_elems; } obj_map<expr, unsigned> const& get_elems() const { return m_elems; }

View file

@ -1872,11 +1872,14 @@ public:
app* theory_seq::get_ite_value(expr* e) { app* theory_seq::get_ite_value(expr* e) {
expr* e1, *e2, *e3; expr* e1, *e2, *e3;
while (m.is_ite(e, e1, e2, e3)) { while (m.is_ite(e, e1, e2, e3)) {
if (get_root(e2) == get_root(e)) { if (!ctx.e_internalized(e))
break;
enode* r = ctx.get_enode(e)->get_root();
if (ctx.get_enode(e2)->get_root() == r) {
e = e2; e = e2;
} }
else if (get_root(e3) == get_root(e)) { else if (ctx.get_enode(e3)->get_root() == r) {
e = e3; e = e3;
} }
else { else {

View file

@ -70,6 +70,10 @@ public:
m_set(s.m_set) { m_set(s.m_set) {
} }
void set(R s) { m_set = s; }
R get() const { return m_set; }
void insert(T const & e) { void insert(T const & e) {
m_set |= e2s(e); m_set |= e2s(e);
} }
@ -162,7 +166,7 @@ class approx_set : public u_approx_set {
public: public:
approx_set():u_approx_set() {} approx_set():u_approx_set() {}
approx_set(unsigned e):u_approx_set(e) {} approx_set(unsigned e):u_approx_set(e) {}
class iterator { class iterator {
unsigned long long m_set; unsigned long long m_set;
unsigned m_val; unsigned m_val;

View file

@ -139,7 +139,7 @@ public:
if (empty()) { if (empty()) {
return; return;
} }
memset(m_value2indices.begin(), 0, sizeof(int) * m_value2indices.size()); memset(m_value2indices.data(), 0, sizeof(int) * m_value2indices.size());
m_values.reset(); m_values.reset();
m_values.push_back(-1); m_values.push_back(-1);
CASSERT("heap", check_invariant()); CASSERT("heap", check_invariant());
@ -244,11 +244,11 @@ public:
} }
iterator begin() { iterator begin() {
return m_values.begin() + 1; return m_values.data() + 1;
} }
iterator end() { iterator end() {
return m_values.end(); return m_values.data() + m_values.size();
} }
const_iterator begin() const { const_iterator begin() const {

View file

@ -112,7 +112,7 @@ class mpff_manager {
unsigned m_precision; //!< Number of words in the significand. Must be an even number. unsigned m_precision; //!< Number of words in the significand. Must be an even number.
unsigned m_precision_bits; //!< Number of bits in the significand. Must be 32*m_precision. unsigned m_precision_bits; //!< Number of bits in the significand. Must be 32*m_precision.
unsigned_vector m_significands; //!< Array containing all significands. mutable unsigned_vector m_significands; //!< Array containing all significands.
unsigned m_capacity; //!< Number of significands that can be stored in m_significands. unsigned m_capacity; //!< Number of significands that can be stored in m_significands.
bool m_to_plus_inf; //!< If True, then round to plus infinity, otherwise to minus infinity bool m_to_plus_inf; //!< If True, then round to plus infinity, otherwise to minus infinity
id_gen m_id_gen; id_gen m_id_gen;

View file

@ -258,7 +258,7 @@ void mpfx_manager::set_core(mpfx & n, mpz_manager<SYNCH> & m, mpz const & v) {
m_tmp_digits.reset(); m_tmp_digits.reset();
allocate_if_needed(n); allocate_if_needed(n);
n.m_sign = m.decompose(v, m_tmp_digits); n.m_sign = m.decompose(v, m_tmp_digits);
unsigned sz = m_tmp_digits.size(); auto sz = m_tmp_digits.size();
if (sz > m_int_part_sz) if (sz > m_int_part_sz)
throw overflow_exception(); throw overflow_exception();
unsigned * w = words(n); unsigned * w = words(n);
@ -299,7 +299,7 @@ void mpfx_manager::set_core(mpfx & n, mpq_manager<SYNCH> & m, mpq const & v) {
} }
m_tmp_digits.reset(); m_tmp_digits.reset();
m.decompose(tmp, m_tmp_digits); m.decompose(tmp, m_tmp_digits);
unsigned sz = m_tmp_digits.size(); auto sz = m_tmp_digits.size();
if (sz > m_total_sz) if (sz > m_total_sz)
throw overflow_exception(); throw overflow_exception();
unsigned * w = words(n); unsigned * w = words(n);

View file

@ -81,11 +81,11 @@ class mpfx_manager {
unsigned m_int_part_sz; unsigned m_int_part_sz;
unsigned m_frac_part_sz; unsigned m_frac_part_sz;
unsigned m_total_sz; //!< == m_int_part_sz + m_frac_part_sz unsigned m_total_sz; //!< == m_int_part_sz + m_frac_part_sz
unsigned_vector m_words; //!< Array containing all words mutable unsigned_vector m_words; //!< Array containing all words
unsigned m_capacity; //!< Number of mpfx numerals that can be stored in m_words. unsigned m_capacity; //!< Number of mpfx numerals that can be stored in m_words.
bool m_to_plus_inf; //!< If True, then round to plus infinity, otherwise to minus infinity bool m_to_plus_inf; //!< If True, then round to plus infinity, otherwise to minus infinity
id_gen m_id_gen; id_gen m_id_gen;
unsigned_vector m_buffer0, m_buffer1, m_buffer2; mutable unsigned_vector m_buffer0, m_buffer1, m_buffer2;
unsigned_vector m_tmp_digits; unsigned_vector m_tmp_digits;
mpfx m_one; mpfx m_one;
mpn_manager m_mpn_manager; mpn_manager m_mpn_manager;

View file

@ -52,10 +52,14 @@ Revision History:
// This is needed for _tzcnt_u32 and friends. // This is needed for _tzcnt_u32 and friends.
#include <immintrin.h> #include <immintrin.h>
#define _trailing_zeros32(X) _tzcnt_u32(X) #define _trailing_zeros32(X) _tzcnt_u32(X)
#endif #elif defined(__GNUC__)
#if defined(__GNUC__)
#define _trailing_zeros32(X) __builtin_ctz(X) #define _trailing_zeros32(X) __builtin_ctz(X)
#else
static uint32_t _trailing_zeros32(uint32_t x) {
uint32_t r = 0;
for (; 0 == (x & 1) && r < 32; ++r, x >>= 1);
return r;
}
#endif #endif
#if (defined(__LP64__) || defined(_WIN64)) && !defined(_M_ARM) && !defined(_M_ARM64) #if (defined(__LP64__) || defined(_WIN64)) && !defined(_M_ARM) && !defined(_M_ARM64)
@ -65,23 +69,11 @@ Revision History:
#define _trailing_zeros64(X) _tzcnt_u64(X) #define _trailing_zeros64(X) _tzcnt_u64(X)
#endif #endif
#else #else
inline uint64_t _trailing_zeros64(uint64_t x) { static uint64_t _trailing_zeros64(uint64_t x) {
uint64_t r = 0; uint64_t r = 0;
for (; 0 == (x & 1) && r < 64; ++r, x >>= 1); for (; 0 == (x & 1) && r < 64; ++r, x >>= 1);
return r; return r;
} }
#if defined(_WINDOWS) && !defined(_M_ARM) && !defined(_M_ARM64)
// _trailing_zeros32 already defined using intrinsics
#elif defined(__GNUC__)
// _trailing_zeros32 already defined using intrinsics
#else
inline uint32_t _trailing_zeros32(uint32_t x) {
uint32_t r = 0;
for (; 0 == (x & 1) && r < 32; ++r, x >>= 1);
return r;
}
#endif
#endif #endif
unsigned trailing_zeros(uint32_t x) { unsigned trailing_zeros(uint32_t x) {
@ -1723,8 +1715,8 @@ void mpz_manager<SYNCH>::display(std::ostream & out, mpz const & a) const {
// GMP version // GMP version
size_t sz = mpz_sizeinbase(*a.m_ptr, 10) + 2; size_t sz = mpz_sizeinbase(*a.m_ptr, 10) + 2;
sbuffer<char, 1024> buffer(sz, 0); sbuffer<char, 1024> buffer(sz, 0);
mpz_get_str(buffer.c_ptr(), 10, *a.m_ptr); mpz_get_str(buffer.data(), 10, *a.m_ptr);
out << buffer.c_ptr(); out << buffer.data();
#endif #endif
} }
} }
@ -1783,11 +1775,11 @@ void mpz_manager<SYNCH>::display_hex(std::ostream & out, mpz const & a, unsigned
unsigned requiredLength = num_bits / 4; unsigned requiredLength = num_bits / 4;
unsigned padding = requiredLength > sz ? requiredLength - sz : 0; unsigned padding = requiredLength > sz ? requiredLength - sz : 0;
sbuffer<char, 1024> buffer(sz, 0); sbuffer<char, 1024> buffer(sz, 0);
mpz_get_str(buffer.c_ptr(), 16, *(a.m_ptr)); mpz_get_str(buffer.data(), 16, *(a.m_ptr));
for (unsigned i = 0; i < padding; ++i) { for (unsigned i = 0; i < padding; ++i) {
out << "0"; out << "0";
} }
out << buffer.c_ptr() + (sz > requiredLength ? sz - requiredLength : 0); out << buffer.data() + (sz > requiredLength ? sz - requiredLength : 0);
#endif #endif
} }
out.copyfmt(fmt); out.copyfmt(fmt);
@ -1837,11 +1829,11 @@ void mpz_manager<SYNCH>::display_bin(std::ostream & out, mpz const & a, unsigned
size_t sz = mpz_sizeinbase(*(a.m_ptr), 2); size_t sz = mpz_sizeinbase(*(a.m_ptr), 2);
unsigned padding = num_bits > sz ? num_bits - sz : 0; unsigned padding = num_bits > sz ? num_bits - sz : 0;
sbuffer<char, 1024> buffer(sz, 0); sbuffer<char, 1024> buffer(sz, 0);
mpz_get_str(buffer.c_ptr(), 2, *(a.m_ptr)); mpz_get_str(buffer.data(), 2, *(a.m_ptr));
for (unsigned i = 0; i < padding; ++i) { for (unsigned i = 0; i < padding; ++i) {
out << "0"; out << "0";
} }
out << buffer.c_ptr() + (sz > num_bits ? sz - num_bits : 0); out << buffer.data() + (sz > num_bits ? sz - num_bits : 0);
#endif #endif
} }
} }

View file

@ -58,28 +58,28 @@ public:
ref_vector_core(ref_vector_core &&) noexcept = default; ref_vector_core(ref_vector_core &&) noexcept = default;
~ref_vector_core() { ~ref_vector_core() {
dec_range_ref(m_nodes.begin(), m_nodes.end()); dec_range_ref(m_nodes.data(), m_nodes.data() + m_nodes.size());
} }
void reset() { void reset() {
dec_range_ref(m_nodes.begin(), m_nodes.end()); dec_range_ref(m_nodes.data(), m_nodes.data() + m_nodes.size());
m_nodes.reset(); m_nodes.reset();
} }
void finalize() { void finalize() {
dec_range_ref(m_nodes.begin(), m_nodes.end()); dec_range_ref(m_nodes.data(), m_nodes.data() + m_nodes.size());
m_nodes.finalize(); m_nodes.finalize();
} }
void resize(unsigned sz) { void resize(unsigned sz) {
if (sz < m_nodes.size()) if (sz < m_nodes.size())
dec_range_ref(m_nodes.begin() + sz, m_nodes.end()); dec_range_ref(m_nodes.data() + sz, m_nodes.data() + m_nodes.size());
m_nodes.resize(sz); m_nodes.resize(sz);
} }
void resize(unsigned sz, T * d) { void resize(unsigned sz, T * d) {
if (sz < m_nodes.size()) { if (sz < m_nodes.size()) {
dec_range_ref(m_nodes.begin() + sz, m_nodes.end()); dec_range_ref(m_nodes.data() + sz, m_nodes.data() + m_nodes.size());
m_nodes.shrink(sz); m_nodes.shrink(sz);
} }
else { else {
@ -130,11 +130,11 @@ public:
T * get(unsigned idx, T * d) const { return m_nodes.get(idx, d); } T * get(unsigned idx, T * d) const { return m_nodes.get(idx, d); }
T * const * data() const { return m_nodes.begin(); } T * const * data() const { return m_nodes.data(); }
typedef T* const* iterator; typedef T* const* iterator;
T ** data() { return m_nodes.begin(); } T ** data() { return m_nodes.data(); }
unsigned hash() const { unsigned hash() const {
unsigned sz = size(); unsigned sz = size();

View file

@ -39,7 +39,7 @@ public:
} }
void reset() { void reset() {
unsigned sz = this->size(); auto sz = this->size();
for (unsigned i = 0; i < sz; i++) { for (unsigned i = 0; i < sz; i++) {
m().del(this->operator[](i)); m().del(this->operator[](i));
} }

View file

@ -80,7 +80,7 @@ public:
// Insert in the this object the elements in the set source. // Insert in the this object the elements in the set source.
uint_set & operator |=(const uint_set & source) { uint_set & operator |=(const uint_set & source) {
unsigned source_size = source.size(); auto source_size = source.size();
if (source_size > size()) { if (source_size > size()) {
resize(source_size + 1); resize(source_size + 1);
} }
@ -91,7 +91,7 @@ public:
} }
uint_set& operator &=(const uint_set& source) { uint_set& operator &=(const uint_set& source) {
unsigned source_size = source.size(); auto source_size = source.size();
if (source_size < size()) { if (source_size < size()) {
resize(source_size); resize(source_size);
} }
@ -102,7 +102,7 @@ public:
} }
bool operator==(const uint_set & source) const { bool operator==(const uint_set & source) const {
unsigned min_size = size(); auto min_size = size();
if (source.size() < min_size) { if (source.size() < min_size) {
min_size = source.size(); min_size = source.size();
} }
@ -111,12 +111,12 @@ public:
return false; return false;
} }
} }
for (unsigned i = min_size; i < size(); ++i) { for (auto i = min_size; i < size(); ++i) {
if ((*this)[i]) { if ((*this)[i]) {
return false; return false;
} }
} }
for (unsigned i = min_size; i < source.size(); ++i) { for (auto i = min_size; i < source.size(); ++i) {
if (source[i]) { if (source[i]) {
return false; return false;
} }
@ -131,7 +131,7 @@ public:
// Return true if the this set is a subset of source. // Return true if the this set is a subset of source.
bool subset_of(const uint_set & source) const { bool subset_of(const uint_set & source) const {
unsigned min_size = size(); auto min_size = size();
if (source.size() < min_size) { if (source.size() < min_size) {
min_size = source.size(); min_size = source.size();
} }
@ -140,7 +140,7 @@ public:
return false; return false;
} }
} }
for (unsigned i = min_size; i < size(); ++i) { for (auto i = min_size; i < size(); ++i) {
if ((*this)[i]) { if ((*this)[i]) {
return false; return false;
} }
@ -252,7 +252,7 @@ public:
void remove(unsigned v) { void remove(unsigned v) {
if (contains(v)) { if (contains(v)) {
m_in_set[v] = false; m_in_set[v] = false;
unsigned i = m_set.size(); auto i = m_set.size();
for (; i > 0 && m_set[--i] != v; ) for (; i > 0 && m_set[--i] != v; )
; ;
SASSERT(m_set[i] == v); SASSERT(m_set[i] == v);
@ -282,7 +282,7 @@ public:
iterator end() const { return m_set.end(); } iterator end() const { return m_set.end(); }
// void reset() { m_set.reset(); m_in_set.reset(); } // void reset() { m_set.reset(); m_in_set.reset(); }
void reset() { void reset() {
unsigned sz = m_set.size(); auto sz = m_set.size();
for (unsigned i = 0; i < sz; ++i) m_in_set[m_set[i]] = false; for (unsigned i = 0; i < sz; ++i) m_in_set[m_set[i]] = false;
m_set.reset(); m_set.reset();
} }

View file

@ -134,6 +134,14 @@ public:
CASSERT("union_find", check_invariant()); CASSERT("union_find", check_invariant());
} }
void set_root(unsigned v, unsigned root) {
TRACE("union_find", tout << "merging " << v << " " << root << "\n";);
SASSERT(v != root);
m_find[v] = root;
m_size[root] += m_size[v];
std::swap(m_next[root], m_next[v]);
}
// dissolve equivalence class of v // dissolve equivalence class of v
// this method cannot be used with backtracking. // this method cannot be used with backtracking.
void dissolve(unsigned v) { void dissolve(unsigned v) {

View file

@ -40,6 +40,125 @@ Revision History:
#pragma warning(disable:4127) #pragma warning(disable:4127)
#endif #endif
#if 0
// portability guide to std::vector.
// memory allocator should be based on memory_allocator<T>
//
// template<typename T>
// struct memory_allocator {
// typedef T value_type;
// etc (interface seems to change between C++17, 20 versions)
// };
//
// Note:
// polynomial.h contains declaration
// typedef svector<numeral> numeral_vector;
// it is crucial that it uses svector and not vector. The destructors on elements of the numeral vector are handled outside.
// Numeral gets instantiated by mpz and mpz does not support copy constructors.
// porting svector to vector is therefore blocked on the semantics of svector being
// copy-constructor free.
//
#include <vector>
template<typename T, bool CallDestructors=true, typename SZ = unsigned>
class vector : public std::vector<T> {
public:
typedef T data_t;
typedef typename std::vector<T>::iterator iterator;
vector() {}
vector(SZ s) {
// TODO resize(s, T());
}
vector(SZ s, T const& e) {
// TODO resize(s, e);
}
vector(SZ s, T const* e) {
// TODO
}
void reset() { clear(); }
void finalize() { clear(); }
void reserve(SZ s, T const & d) {
if (s > size())
resize(s, d);
}
void reserve(SZ s) {
}
void setx(SZ idx, T const & elem, T const & d) {
if (idx >= size())
resize(idx+1, d);
(*this)[idx] = elem;
}
T const & get(SZ idx, T const & d) const {
if (idx >= size()) {
return d;
}
return (*this)[idx];
}
void insert(T const & elem) {
push_back(elem);
}
void erase(iterator pos) {
// TODO
}
void erase(T const& e) {
// TODO
}
void fill(T const & elem) {
for (auto& e : *this)
e = elem;
}
void fill(unsigned sz, T const & elem) {
resize(sz);
fill(elem);
}
void shrink(SZ s) {
resize(s);
}
void reverse() {
SZ sz = size();
for (SZ i = 0; i < sz/2; ++i) {
std::swap((*this)[i], (*this)[sz-i-1]);
}
}
void append(vector<T, CallDestructors> const & other) {
for(SZ i = 0; i < other.size(); ++i) {
push_back(other[i]);
}
}
void append(unsigned n, T const* elems) {
// TODO
}
bool contains(T const & elem) const {
for (auto const& e : *this)
if (e == elem)
return true;
return false;
}
};
#else
template<typename T, bool CallDestructors=true, typename SZ = unsigned> template<typename T, bool CallDestructors=true, typename SZ = unsigned>
class vector { class vector {
#define SIZE_IDX -1 #define SIZE_IDX -1
@ -602,6 +721,8 @@ public:
}; };
#endif
template<typename T> template<typename T>
class ptr_vector : public vector<T *, false> { class ptr_vector : public vector<T *, false> {
public: public: