mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 13:29:11 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master' into lackr
This commit is contained in:
		
						commit
						743a59254e
					
				
					 100 changed files with 8825 additions and 3447 deletions
				
			
		| 
						 | 
				
			
			@ -2758,17 +2758,17 @@ void fpa_example() {
 | 
			
		|||
	Z3_solver_push(ctx, s);
 | 
			
		||||
	c1 = Z3_mk_fpa_fp(ctx,
 | 
			
		||||
					  Z3_mk_numeral(ctx, "0", Z3_mk_bv_sort(ctx, 1)),
 | 
			
		||||
					  Z3_mk_numeral(ctx, "3377699720527872", Z3_mk_bv_sort(ctx, 52)),
 | 
			
		||||
					  Z3_mk_numeral(ctx, "1025", Z3_mk_bv_sort(ctx, 11)));
 | 
			
		||||
					  Z3_mk_numeral(ctx, "1025", Z3_mk_bv_sort(ctx, 11)),
 | 
			
		||||
                      Z3_mk_numeral(ctx, "3377699720527872", Z3_mk_bv_sort(ctx, 52)));
 | 
			
		||||
	c2 = Z3_mk_fpa_to_fp_bv(ctx,
 | 
			
		||||
							Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64)),
 | 
			
		||||
							Z3_mk_fpa_sort(ctx, 11, 53));
 | 
			
		||||
	c3 = Z3_mk_fpa_to_fp_int_real(ctx,
 | 
			
		||||
    c3 = Z3_mk_fpa_to_fp_int_real(ctx,
 | 
			
		||||
                                  Z3_mk_fpa_rtz(ctx),
 | 
			
		||||
								  Z3_mk_numeral(ctx, "2", Z3_mk_int_sort(ctx)),
 | 
			
		||||
                                  Z3_mk_numeral(ctx, "1.75", Z3_mk_real_sort(ctx)),                                  
 | 
			
		||||
								  Z3_mk_numeral(ctx, "2", Z3_mk_int_sort(ctx)), /* exponent */
 | 
			
		||||
                                  Z3_mk_numeral(ctx, "1.75", Z3_mk_real_sort(ctx)), /* significand */
 | 
			
		||||
                                  Z3_mk_fpa_sort(ctx, 11, 53));
 | 
			
		||||
	c4 = Z3_mk_fpa_to_fp_real(ctx,
 | 
			
		||||
    c4 = Z3_mk_fpa_to_fp_real(ctx,
 | 
			
		||||
							  Z3_mk_fpa_rtz(ctx),
 | 
			
		||||
							  Z3_mk_numeral(ctx, "7.0", Z3_mk_real_sort(ctx)),
 | 
			
		||||
							  Z3_mk_fpa_sort(ctx, 11, 53));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,15 +19,15 @@ def has_cr(file):
 | 
			
		|||
    lines = 0
 | 
			
		||||
    line = ins.readline()
 | 
			
		||||
    while line and lines < 20:
 | 
			
		||||
	m = cr.search(line)
 | 
			
		||||
	if m:
 | 
			
		||||
	    ins.close()
 | 
			
		||||
	    return True
 | 
			
		||||
	m = aut.search(line)
 | 
			
		||||
	if m:
 | 
			
		||||
	    ins.close()
 | 
			
		||||
	    return True
 | 
			
		||||
	line = ins.readline()
 | 
			
		||||
        m = cr.search(line)
 | 
			
		||||
        if m:
 | 
			
		||||
            ins.close()
 | 
			
		||||
            return True
 | 
			
		||||
        m = aut.search(line)
 | 
			
		||||
        if m:
 | 
			
		||||
            ins.close()
 | 
			
		||||
            return True
 | 
			
		||||
        line = ins.readline()
 | 
			
		||||
    ins.close()
 | 
			
		||||
    return False
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,20 +38,20 @@ def add_cr(file):
 | 
			
		|||
    ous.write(cr_notice)
 | 
			
		||||
    line = ins.readline()
 | 
			
		||||
    while line:
 | 
			
		||||
	ous.write(line)
 | 
			
		||||
	line = ins.readline()
 | 
			
		||||
        ous.write(line)
 | 
			
		||||
        line = ins.readline()
 | 
			
		||||
    ins.close()
 | 
			
		||||
    ous.close()
 | 
			
		||||
    os.system("move %s %s" % (tmp, file))
 | 
			
		||||
 | 
			
		||||
def add_missing_cr(dir):
 | 
			
		||||
    for root, dirs, files in os.walk(dir):
 | 
			
		||||
	for f in files:
 | 
			
		||||
	    if f.endswith('.cpp') or f.endswith('.h') or f.endswith('.c') or f.endswith('.cs'):
 | 
			
		||||
		path = "%s\\%s" % (root, f)
 | 
			
		||||
		if not has_cr(path):
 | 
			
		||||
		    print("Missing CR for %s" % path)
 | 
			
		||||
		    add_cr(path)
 | 
			
		||||
        for f in files:
 | 
			
		||||
            if f.endswith('.cpp') or f.endswith('.h') or f.endswith('.c') or f.endswith('.cs'):
 | 
			
		||||
                path = "%s\\%s" % (root, f)
 | 
			
		||||
                if not has_cr(path):
 | 
			
		||||
                    print("Missing CR for %s" % path)
 | 
			
		||||
                    add_cr(path)
 | 
			
		||||
 | 
			
		||||
add_missing_cr('src')
 | 
			
		||||
add_missing_cr('examples')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ update_version()
 | 
			
		|||
mk_auto_src()
 | 
			
		||||
mk_bindings(API_files)
 | 
			
		||||
mk_vs_proj('z3', ['shell'])
 | 
			
		||||
mk_vs_proj_dll('libz3', ['api_dll'])
 | 
			
		||||
mk_makefile()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,11 +16,12 @@ def init_project_def():
 | 
			
		|||
    add_lib('nlsat', ['polynomial', 'sat'])
 | 
			
		||||
    add_lib('hilbert', ['util'], 'math/hilbert')
 | 
			
		||||
    add_lib('simplex', ['util'], 'math/simplex')
 | 
			
		||||
    add_lib('automata', ['util'], 'math/automata')
 | 
			
		||||
    add_lib('interval', ['util'], 'math/interval')
 | 
			
		||||
    add_lib('realclosure', ['interval'], 'math/realclosure')
 | 
			
		||||
    add_lib('subpaving', ['interval'], 'math/subpaving')
 | 
			
		||||
    add_lib('ast', ['util', 'polynomial'])
 | 
			
		||||
    add_lib('rewriter', ['ast', 'polynomial'], 'ast/rewriter')
 | 
			
		||||
    add_lib('rewriter', ['ast', 'polynomial', 'automata'], 'ast/rewriter')
 | 
			
		||||
    add_lib('normal_forms', ['rewriter'], 'ast/normal_forms')
 | 
			
		||||
    add_lib('model', ['rewriter'])
 | 
			
		||||
    add_lib('tactic', ['ast', 'model'])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -643,7 +643,7 @@ def display_help(exit_code):
 | 
			
		|||
def parse_options():
 | 
			
		||||
    global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM
 | 
			
		||||
    global DOTNET_ENABLED, JAVA_ENABLED, ML_ENABLED, STATIC_LIB, PREFIX, GMP, FOCI2, FOCI2LIB, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH
 | 
			
		||||
    global LINUX_X64, SLOW_OPTIMIZE, USE_OMP, PYTHON_INSTALL_ENABLED
 | 
			
		||||
    global LINUX_X64, SLOW_OPTIMIZE, USE_OMP
 | 
			
		||||
    try:
 | 
			
		||||
        options, remainder = getopt.gnu_getopt(sys.argv[1:],
 | 
			
		||||
                                               'b:df:sxhmcvtnp:gj',
 | 
			
		||||
| 
						 | 
				
			
			@ -711,26 +711,7 @@ def parse_options():
 | 
			
		|||
        else:
 | 
			
		||||
            print("ERROR: Invalid command line option '%s'" % opt)
 | 
			
		||||
            display_help(1)
 | 
			
		||||
    # Handle the Python package directory
 | 
			
		||||
    if IS_WINDOWS:
 | 
			
		||||
        # Installing under Windows doesn't make sense as the install prefix is used
 | 
			
		||||
        # but that doesn't make sense under Windows
 | 
			
		||||
        PYTHON_INSTALL_ENABLED = False
 | 
			
		||||
    else:
 | 
			
		||||
        if not PYTHON_PACKAGE_DIR.startswith(PREFIX):
 | 
			
		||||
            print(("Warning: The detected Python package directory (%s)"
 | 
			
		||||
                   " does not live under the installation prefix (%s)"
 | 
			
		||||
                   ". This would lead to a broken Python installation."
 | 
			
		||||
                   "Use --pypkgdir= to change the Python package directory") %
 | 
			
		||||
                  (PYTHON_PACKAGE_DIR, PREFIX))
 | 
			
		||||
            if IS_OSX and PYTHON_PACKAGE_DIR.startswith('/Library/'):
 | 
			
		||||
                print("Using hack to install Python bindings, this might lead to a broken system")
 | 
			
		||||
                PYTHON_INSTALL_ENABLED = True
 | 
			
		||||
            else:
 | 
			
		||||
                print("Disabling install of Python bindings")
 | 
			
		||||
                PYTHON_INSTALL_ENABLED = False
 | 
			
		||||
        else:
 | 
			
		||||
            PYTHON_INSTALL_ENABLED = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Return a list containing a file names included using '#include' in
 | 
			
		||||
# the given C/C++ file named fname.
 | 
			
		||||
| 
						 | 
				
			
			@ -1036,6 +1017,11 @@ class Component:
 | 
			
		|||
    def mk_unix_dist(self, build_path, dist_path):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # Used to print warnings or errors after mk_make.py is done, so that they
 | 
			
		||||
    # are not quite as easy to miss.
 | 
			
		||||
    def final_info(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
class LibComponent(Component):
 | 
			
		||||
    def __init__(self, name, path, deps, includes2install):
 | 
			
		||||
        Component.__init__(self, name, path, deps)
 | 
			
		||||
| 
						 | 
				
			
			@ -1062,8 +1048,8 @@ class LibComponent(Component):
 | 
			
		|||
        out.write('\n')
 | 
			
		||||
        out.write('%s: %s\n\n' % (self.name, libfile))
 | 
			
		||||
 | 
			
		||||
    def mk_install_dep(self, out):
 | 
			
		||||
        out.write('%s' % libfile)
 | 
			
		||||
    def mk_install_deps(self, out):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    def mk_install(self, out):
 | 
			
		||||
        for include in self.includes2install:
 | 
			
		||||
| 
						 | 
				
			
			@ -1151,8 +1137,10 @@ class ExeComponent(Component):
 | 
			
		|||
    def main_component(self):
 | 
			
		||||
        return self.install
 | 
			
		||||
 | 
			
		||||
    def mk_install_dep(self, out):
 | 
			
		||||
        out.write('%s' % exefile)
 | 
			
		||||
    def mk_install_deps(self, out):
 | 
			
		||||
        if self.install:
 | 
			
		||||
            exefile = '%s$(EXE_EXT)' % self.exe_name
 | 
			
		||||
            out.write('%s' % exefile)
 | 
			
		||||
 | 
			
		||||
    def mk_install(self, out):
 | 
			
		||||
        if self.install:
 | 
			
		||||
| 
						 | 
				
			
			@ -1308,7 +1296,7 @@ class DLLComponent(Component):
 | 
			
		|||
    def require_def_file(self):
 | 
			
		||||
        return IS_WINDOWS and self.export_files
 | 
			
		||||
 | 
			
		||||
    def mk_install_dep(self, out):
 | 
			
		||||
    def mk_install_deps(self, out):
 | 
			
		||||
        out.write('%s$(SO_EXT)' % self.dll_name)
 | 
			
		||||
        if self.static:
 | 
			
		||||
            out.write(' %s$(LIB_EXT)' % self.dll_name)
 | 
			
		||||
| 
						 | 
				
			
			@ -1345,27 +1333,43 @@ class DLLComponent(Component):
 | 
			
		|||
class PythonInstallComponent(Component):
 | 
			
		||||
    def __init__(self, name, libz3Component):
 | 
			
		||||
        assert isinstance(libz3Component, DLLComponent)
 | 
			
		||||
        global PYTHON_INSTALL_ENABLED
 | 
			
		||||
        Component.__init__(self, name, None, [])
 | 
			
		||||
        self.pythonPkgDir = None
 | 
			
		||||
        self.in_prefix_install = True
 | 
			
		||||
        self.libz3Component = libz3Component
 | 
			
		||||
        if not PYTHON_INSTALL_ENABLED:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if self.is_osx_hack():
 | 
			
		||||
            # Use full path that is outside of install prefix
 | 
			
		||||
            self.pythonPkgDir = PYTHON_PACKAGE_DIR
 | 
			
		||||
            self.in_prefix_install = False
 | 
			
		||||
            assert os.path.isabs(self.pythonPkgDir)
 | 
			
		||||
        if IS_WINDOWS:
 | 
			
		||||
            # Installing under Windows doesn't make sense as the install prefix is used
 | 
			
		||||
            # but that doesn't make sense under Windows
 | 
			
		||||
            # CMW: It makes perfectly good sense; the prefix is Python's sys.prefix,
 | 
			
		||||
            # i.e., something along the lines of C:\Python\... At the moment we are not
 | 
			
		||||
            # sure whether we would want to install libz3.dll into that directory though.
 | 
			
		||||
            PYTHON_INSTALL_ENABLED = False
 | 
			
		||||
            return
 | 
			
		||||
        else:
 | 
			
		||||
            # Use path inside the prefix (should be the normal case)
 | 
			
		||||
            PYTHON_INSTALL_ENABLED = True
 | 
			
		||||
 | 
			
		||||
        if IS_WINDOWS or IS_OSX:
 | 
			
		||||
            # Use full path that is possibly outside of install prefix
 | 
			
		||||
            self.in_prefix_install = PYTHON_PACKAGE_DIR.startswith(PREFIX)
 | 
			
		||||
            self.pythonPkgDir = strip_path_prefix(PYTHON_PACKAGE_DIR, PREFIX)
 | 
			
		||||
        else:
 | 
			
		||||
            # Use path inside the prefix (should be the normal case on Linux)
 | 
			
		||||
            # CMW: Also normal on *BSD?
 | 
			
		||||
            assert PYTHON_PACKAGE_DIR.startswith(PREFIX)
 | 
			
		||||
            self.pythonPkgDir = strip_path_prefix(PYTHON_PACKAGE_DIR, PREFIX)
 | 
			
		||||
            assert not os.path.isabs(self.pythonPkgDir)
 | 
			
		||||
            assert self.in_prefix_install
 | 
			
		||||
            self.in_prefix_install = True
 | 
			
		||||
 | 
			
		||||
    def is_osx_hack(self):
 | 
			
		||||
        return IS_OSX and not PYTHON_PACKAGE_DIR.startswith(PREFIX)
 | 
			
		||||
        if self.in_prefix_install:
 | 
			
		||||
            assert not os.path.isabs(self.pythonPkgDir)
 | 
			
		||||
 | 
			
		||||
    def final_info(self):
 | 
			
		||||
        if not PYTHON_PACKAGE_DIR.startswith(PREFIX):
 | 
			
		||||
            print("Warning: The detected Python package directory (%s) is not "
 | 
			
		||||
                  "in the installation prefix (%s). This can lead to a broken "
 | 
			
		||||
                  "Python API installation. Use --pypkgdir= to change the "
 | 
			
		||||
                  "Python package directory." % (PYTHON_PACKAGE_DIR, PREFIX))
 | 
			
		||||
 | 
			
		||||
    def main_component(self):
 | 
			
		||||
        return False
 | 
			
		||||
| 
						 | 
				
			
			@ -1376,7 +1380,7 @@ class PythonInstallComponent(Component):
 | 
			
		|||
        MakeRuleCmd.make_install_directory(out, self.pythonPkgDir, in_prefix=self.in_prefix_install)
 | 
			
		||||
 | 
			
		||||
        # Sym-link or copy libz3 into python package directory
 | 
			
		||||
        if IS_WINDOWS or self.is_osx_hack():
 | 
			
		||||
        if IS_WINDOWS or IS_OSX:
 | 
			
		||||
            MakeRuleCmd.install_files(out,
 | 
			
		||||
                                      self.libz3Component.dll_file(),
 | 
			
		||||
                                      os.path.join(self.pythonPkgDir,
 | 
			
		||||
| 
						 | 
				
			
			@ -1568,7 +1572,6 @@ class DotNetDLLComponent(Component):
 | 
			
		|||
 | 
			
		||||
    def mk_win_dist(self, build_path, dist_path):
 | 
			
		||||
        if is_dotnet_enabled():
 | 
			
		||||
            # Assuming all .NET dlls should be in the distribution
 | 
			
		||||
            mk_dir(os.path.join(dist_path, INSTALL_BIN_DIR))
 | 
			
		||||
            shutil.copy('%s.dll' % os.path.join(build_path, self.dll_name),
 | 
			
		||||
                        '%s.dll' % os.path.join(dist_path, INSTALL_BIN_DIR, self.dll_name))
 | 
			
		||||
| 
						 | 
				
			
			@ -1578,11 +1581,13 @@ class DotNetDLLComponent(Component):
 | 
			
		|||
                shutil.copy('%s.pdb' % os.path.join(build_path, self.dll_name),
 | 
			
		||||
                            '%s.pdb' % os.path.join(dist_path, INSTALL_BIN_DIR, self.dll_name))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def mk_unix_dist(self, build_path, dist_path):
 | 
			
		||||
        # Do nothing
 | 
			
		||||
        return
 | 
			
		||||
        if is_dotnet_enabled():
 | 
			
		||||
            mk_dir(os.path.join(dist_path, INSTALL_BIN_DIR))
 | 
			
		||||
            shutil.copy('%s.dll' % os.path.join(build_path, self.dll_name),
 | 
			
		||||
                        '%s.dll' % os.path.join(dist_path, INSTALL_BIN_DIR, self.dll_name))
 | 
			
		||||
            shutil.copy('%s.xml' % os.path.join(build_path, self.dll_name),
 | 
			
		||||
                        '%s.xml' % os.path.join(dist_path, INSTALL_BIN_DIR, self.dll_name))
 | 
			
		||||
 | 
			
		||||
    def mk_install_deps(self, out):
 | 
			
		||||
        if not is_dotnet_enabled():
 | 
			
		||||
| 
						 | 
				
			
			@ -2336,12 +2341,12 @@ def mk_makefile():
 | 
			
		|||
            out.write(' %s' % c.name)
 | 
			
		||||
    out.write('\n\t@echo Z3 was successfully built.\n')
 | 
			
		||||
    out.write("\t@echo \"Z3Py scripts can already be executed in the \'%s\' directory.\"\n" % BUILD_DIR)
 | 
			
		||||
    out.write("\t@echo \"Z3Py scripts stored in arbitrary directories can be also executed if \'%s\' directory is added to the PYTHONPATH environment variable.\"\n" % BUILD_DIR)
 | 
			
		||||
    out.write("\t@echo \"Z3Py scripts stored in arbitrary directories can be executed if the \'%s\' directory is added to the PYTHONPATH environment variable.\"\n" % BUILD_DIR)
 | 
			
		||||
    if not IS_WINDOWS:
 | 
			
		||||
        out.write("\t@echo Use the following command to install Z3 at prefix $(PREFIX).\n")
 | 
			
		||||
        out.write('\t@echo "    sudo make install"\n\n')
 | 
			
		||||
        out.write("\t@echo If you are doing a staged install you can use DESTDIR.\n")
 | 
			
		||||
        out.write('\t@echo "    make DESTDIR=/some/temp/directory install"\n')
 | 
			
		||||
        # out.write("\t@echo If you are doing a staged install you can use DESTDIR.\n")
 | 
			
		||||
        # out.write('\t@echo "    make DESTDIR=/some/temp/directory install"\n')
 | 
			
		||||
    # Generate :examples rule
 | 
			
		||||
    out.write('examples:')
 | 
			
		||||
    for c in get_components():
 | 
			
		||||
| 
						 | 
				
			
			@ -2355,6 +2360,8 @@ def mk_makefile():
 | 
			
		|||
    if not IS_WINDOWS:
 | 
			
		||||
        mk_install(out)
 | 
			
		||||
        mk_uninstall(out)
 | 
			
		||||
    for c in get_components():
 | 
			
		||||
        c.final_info()
 | 
			
		||||
    out.close()
 | 
			
		||||
    # Finalize
 | 
			
		||||
    if VERBOSE:
 | 
			
		||||
| 
						 | 
				
			
			@ -3298,15 +3305,18 @@ def mk_z3consts_ml(api_files):
 | 
			
		|||
def mk_gui_str(id):
 | 
			
		||||
    return '4D2F40D8-E5F9-473B-B548-%012d' % id
 | 
			
		||||
 | 
			
		||||
def mk_vs_proj(name, components):
 | 
			
		||||
    if not VS_PROJ:
 | 
			
		||||
        return
 | 
			
		||||
    proj_name = '%s.vcxproj' % os.path.join(BUILD_DIR, name)
 | 
			
		||||
    modes=['Debug', 'Release']
 | 
			
		||||
    PLATFORMS=['Win32']
 | 
			
		||||
    f = open(proj_name, 'w')
 | 
			
		||||
    f.write('<?xml version="1.0" encoding="utf-8"?>\n')
 | 
			
		||||
    f.write('<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n')
 | 
			
		||||
def get_platform_toolset_str():
 | 
			
		||||
    default = 'v110';
 | 
			
		||||
    vstr = check_output(['msbuild', '/ver'])
 | 
			
		||||
    lines = vstr.split('\n')
 | 
			
		||||
    lline = lines[-1]
 | 
			
		||||
    tokens = lline.split('.')
 | 
			
		||||
    if len(tokens) < 2:
 | 
			
		||||
        return default
 | 
			
		||||
    else:
 | 
			
		||||
        return 'v' + tokens[0] + tokens[1]
 | 
			
		||||
 | 
			
		||||
def mk_vs_proj_property_groups(f, name, target_ext, type):
 | 
			
		||||
    f.write('  <ItemGroup Label="ProjectConfigurations">\n')
 | 
			
		||||
    f.write('    <ProjectConfiguration Include="Debug|Win32">\n')
 | 
			
		||||
    f.write('      <Configuration>Debug</Configuration>\n')
 | 
			
		||||
| 
						 | 
				
			
			@ -3317,35 +3327,46 @@ def mk_vs_proj(name, components):
 | 
			
		|||
    f.write('      <Platform>Win32</Platform>\n')
 | 
			
		||||
    f.write('    </ProjectConfiguration>\n')
 | 
			
		||||
    f.write('  </ItemGroup>\n')
 | 
			
		||||
    f.write('   <PropertyGroup Label="Globals">\n')
 | 
			
		||||
    f.write('  <PropertyGroup Label="Globals">\n')
 | 
			
		||||
    f.write('    <ProjectGuid>{%s}</ProjectGuid>\n' % mk_gui_str(0))
 | 
			
		||||
    f.write('    <ProjectName>%s</ProjectName>\n' % name)
 | 
			
		||||
    f.write('    <Keyword>Win32Proj</Keyword>\n')
 | 
			
		||||
    f.write('    <PlatformToolset>%s</PlatformToolset>\n' % get_platform_toolset_str())
 | 
			
		||||
    f.write('  </PropertyGroup>\n')
 | 
			
		||||
    f.write('  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\n')
 | 
			
		||||
    f.write('  <PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'" Label="Configuration">\n')
 | 
			
		||||
    f.write('    <ConfigurationType>Application</ConfigurationType>\n')
 | 
			
		||||
    f.write('    <ConfigurationType>%s</ConfigurationType>\n' % type)
 | 
			
		||||
    f.write('    <CharacterSet>Unicode</CharacterSet>\n')
 | 
			
		||||
    f.write('    <UseOfMfc>false</UseOfMfc>\n')
 | 
			
		||||
    f.write('  </PropertyGroup>\n')
 | 
			
		||||
    f.write('  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\n')
 | 
			
		||||
    f.write('  <ImportGroup Label="ExtensionSettings">\n')
 | 
			
		||||
    f.write('   </ImportGroup>\n')
 | 
			
		||||
    f.write('  <ImportGroup Label="ExtensionSettings" />\n')
 | 
			
		||||
    f.write('   <ImportGroup Label="PropertySheets">\n')
 | 
			
		||||
    f.write('    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" />  </ImportGroup>\n')
 | 
			
		||||
    f.write('  <PropertyGroup Label="UserMacros" />\n')
 | 
			
		||||
    f.write('  <PropertyGroup>\n')
 | 
			
		||||
    f.write('    <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">$(SolutionDir)$(Configuration)\</OutDir>\n')
 | 
			
		||||
    f.write('    <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">$(SolutionDir)\$(ProjectName)\$(Configuration)\</OutDir>\n')
 | 
			
		||||
    f.write('    <TargetName Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">%s</TargetName>\n' % name)
 | 
			
		||||
    f.write('    <TargetExt Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">.exe</TargetExt>\n')
 | 
			
		||||
    f.write('    <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">$(SolutionDir)$(Configuration)\</OutDir>\n')
 | 
			
		||||
    f.write('    <TargetExt Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">.%s</TargetExt>\n' % target_ext)
 | 
			
		||||
    f.write('    <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">$(SolutionDir)\$(ProjectName)\$(Configuration)\</OutDir>\n')
 | 
			
		||||
    f.write('    <TargetName Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">%s</TargetName>\n' % name)
 | 
			
		||||
    f.write('    <TargetExt Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">.exe</TargetExt>\n')
 | 
			
		||||
    f.write('    <TargetExt Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">.%s</TargetExt>\n' % target_ext)
 | 
			
		||||
    f.write('  </PropertyGroup>\n')
 | 
			
		||||
    f.write('  <ItemDefinitionGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">\n')
 | 
			
		||||
    f.write('  <PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">\n')
 | 
			
		||||
    f.write('        <IntDir>$(ProjectName)\$(Configuration)\</IntDir>\n')
 | 
			
		||||
    f.write('  </PropertyGroup>\n')
 | 
			
		||||
    f.write('  <PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">\n')
 | 
			
		||||
    f.write('    <IntDir>$(ProjectName)\$(Configuration)\</IntDir>\n')
 | 
			
		||||
    f.write('  </PropertyGroup>\n')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def mk_vs_proj_cl_compile(f, name, components, debug):
 | 
			
		||||
    f.write('    <ClCompile>\n')
 | 
			
		||||
    f.write('      <Optimization>Disabled</Optimization>\n')
 | 
			
		||||
    f.write('      <PreprocessorDefinitions>WIN32;_DEBUG;Z3DEBUG;_TRACE;_MP_INTERNAL;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n')
 | 
			
		||||
    if debug:
 | 
			
		||||
        f.write('      <PreprocessorDefinitions>WIN32;_DEBUG;Z3DEBUG;_TRACE;_MP_INTERNAL;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n')
 | 
			
		||||
    else:
 | 
			
		||||
        f.write('      <PreprocessorDefinitions>WIN32;_NDEBUG;_MP_INTERNAL;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n')
 | 
			
		||||
    if VS_PAR:
 | 
			
		||||
        f.write('      <MinimalRebuild>false</MinimalRebuild>\n')
 | 
			
		||||
        f.write('      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n')
 | 
			
		||||
| 
						 | 
				
			
			@ -3353,8 +3374,14 @@ def mk_vs_proj(name, components):
 | 
			
		|||
        f.write('      <MinimalRebuild>true</MinimalRebuild>\n')
 | 
			
		||||
    f.write('      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n')
 | 
			
		||||
    f.write('      <WarningLevel>Level3</WarningLevel>\n')
 | 
			
		||||
    f.write('      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n')
 | 
			
		||||
    f.write('      <OpenMPSupport>true</OpenMPSupport>\n')
 | 
			
		||||
    if debug:
 | 
			
		||||
        f.write('      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n')
 | 
			
		||||
    else:
 | 
			
		||||
        f.write('      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\n')
 | 
			
		||||
    if USE_OMP:
 | 
			
		||||
        f.write('      <OpenMPSupport>true</OpenMPSupport>\n')
 | 
			
		||||
    else:
 | 
			
		||||
        f.write('      <OpenMPSupport>false</OpenMPSupport>\n')
 | 
			
		||||
    f.write('      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n')
 | 
			
		||||
    f.write('      <AdditionalIncludeDirectories>')
 | 
			
		||||
    deps = find_all_deps(name, components)
 | 
			
		||||
| 
						 | 
				
			
			@ -3367,63 +3394,89 @@ def mk_vs_proj(name, components):
 | 
			
		|||
        f.write(get_component(dep).to_src_dir)
 | 
			
		||||
    f.write('</AdditionalIncludeDirectories>\n')
 | 
			
		||||
    f.write('    </ClCompile>\n')
 | 
			
		||||
    f.write('    <Link>\n')
 | 
			
		||||
    f.write('      <OutputFile>$(OutDir)%s.exe</OutputFile>\n' % name)
 | 
			
		||||
    f.write('      <GenerateDebugInformation>true</GenerateDebugInformation>\n')
 | 
			
		||||
    f.write('      <SubSystem>Console</SubSystem>\n')
 | 
			
		||||
    f.write('      <StackReserveSize>8388608</StackReserveSize>\n')
 | 
			
		||||
    f.write('      <RandomizedBaseAddress>false</RandomizedBaseAddress>\n')
 | 
			
		||||
    f.write('      <DataExecutionPrevention>\n')
 | 
			
		||||
    f.write('      </DataExecutionPrevention>\n')
 | 
			
		||||
    f.write('      <TargetMachine>MachineX86</TargetMachine>\n')
 | 
			
		||||
    f.write('      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n')
 | 
			
		||||
    f.write('<AdditionalDependencies>psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n')
 | 
			
		||||
    f.write('    </Link>\n')
 | 
			
		||||
    f.write('  </ItemDefinitionGroup>\n')
 | 
			
		||||
    f.write('  <ItemDefinitionGroup Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">\n')
 | 
			
		||||
    f.write('    <ClCompile>\n')
 | 
			
		||||
    f.write('      <Optimization>Disabled</Optimization>\n')
 | 
			
		||||
    f.write('      <PreprocessorDefinitions>WIN32;_NDEBUG;_MP_INTERNAL;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n')
 | 
			
		||||
    if VS_PAR:
 | 
			
		||||
        f.write('      <MinimalRebuild>false</MinimalRebuild>\n')
 | 
			
		||||
        f.write('      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n')
 | 
			
		||||
    else:
 | 
			
		||||
        f.write('      <MinimalRebuild>true</MinimalRebuild>\n')
 | 
			
		||||
    f.write('      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n')
 | 
			
		||||
    f.write('      <WarningLevel>Level3</WarningLevel>\n')
 | 
			
		||||
    f.write('      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\n')
 | 
			
		||||
    f.write('      <OpenMPSupport>true</OpenMPSupport>\n')
 | 
			
		||||
    f.write('      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n')
 | 
			
		||||
    f.write('      <AdditionalIncludeDirectories>')
 | 
			
		||||
    deps = find_all_deps(name, components)
 | 
			
		||||
    first = True
 | 
			
		||||
    for dep in deps:
 | 
			
		||||
        if first:
 | 
			
		||||
            first = False
 | 
			
		||||
        else:
 | 
			
		||||
            f.write(';')
 | 
			
		||||
        f.write(get_component(dep).to_src_dir)
 | 
			
		||||
    f.write('</AdditionalIncludeDirectories>\n')
 | 
			
		||||
    f.write('    </ClCompile>\n')
 | 
			
		||||
    f.write('    <Link>\n')
 | 
			
		||||
    f.write('      <OutputFile>$(OutDir)%s.exe</OutputFile>\n' % name)
 | 
			
		||||
    f.write('      <GenerateDebugInformation>true</GenerateDebugInformation>\n')
 | 
			
		||||
    f.write('      <SubSystem>Console</SubSystem>\n')
 | 
			
		||||
    f.write('      <StackReserveSize>8388608</StackReserveSize>\n')
 | 
			
		||||
    f.write('      <RandomizedBaseAddress>false</RandomizedBaseAddress>\n')
 | 
			
		||||
    f.write('      <DataExecutionPrevention>\n')
 | 
			
		||||
    f.write('      </DataExecutionPrevention>\n')
 | 
			
		||||
    f.write('      <TargetMachine>MachineX86</TargetMachine>\n')
 | 
			
		||||
    f.write('      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n')
 | 
			
		||||
    f.write('<AdditionalDependencies>psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n')
 | 
			
		||||
    f.write('    </Link>\n')
 | 
			
		||||
    f.write('  </ItemDefinitionGroup>\n')
 | 
			
		||||
 | 
			
		||||
def mk_vs_proj_dep_groups(f, name, components):
 | 
			
		||||
    f.write('  <ItemGroup>\n')
 | 
			
		||||
    deps = find_all_deps(name, components)
 | 
			
		||||
    for dep in deps:
 | 
			
		||||
        dep = get_component(dep)
 | 
			
		||||
        for cpp in filter(lambda f: f.endswith('.cpp'), os.listdir(dep.src_dir)):
 | 
			
		||||
            f.write('    <ClCompile Include="%s" />\n' % os.path.join(dep.to_src_dir, cpp))
 | 
			
		||||
    f.write('  </ItemGroup>\n')
 | 
			
		||||
 | 
			
		||||
def mk_vs_proj_link_exe(f, name, debug):
 | 
			
		||||
    f.write('    <Link>\n')
 | 
			
		||||
    f.write('      <OutputFile>$(OutDir)%s.exe</OutputFile>\n' % name)
 | 
			
		||||
    f.write('      <GenerateDebugInformation>true</GenerateDebugInformation>\n')
 | 
			
		||||
    f.write('      <SubSystem>Console</SubSystem>\n')
 | 
			
		||||
    f.write('      <StackReserveSize>8388608</StackReserveSize>\n')
 | 
			
		||||
    f.write('      <RandomizedBaseAddress>false</RandomizedBaseAddress>\n')
 | 
			
		||||
    f.write('      <DataExecutionPrevention/>\n')
 | 
			
		||||
    f.write('      <TargetMachine>MachineX86</TargetMachine>\n')
 | 
			
		||||
    f.write('      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n')
 | 
			
		||||
    f.write('      <AdditionalDependencies>psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n')
 | 
			
		||||
    f.write('    </Link>\n')
 | 
			
		||||
 | 
			
		||||
def mk_vs_proj(name, components):
 | 
			
		||||
    if not VS_PROJ:
 | 
			
		||||
        return
 | 
			
		||||
    proj_name = '%s.vcxproj' % os.path.join(BUILD_DIR, name)
 | 
			
		||||
    modes=['Debug', 'Release']
 | 
			
		||||
    PLATFORMS=['Win32']
 | 
			
		||||
    f = open(proj_name, 'w')
 | 
			
		||||
    f.write('<?xml version="1.0" encoding="utf-8"?>\n')
 | 
			
		||||
    f.write('<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n')
 | 
			
		||||
    mk_vs_proj_property_groups(f, name, 'exe', 'Application')
 | 
			
		||||
    f.write('  <ItemDefinitionGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">\n')
 | 
			
		||||
    mk_vs_proj_cl_compile(f, name, components, debug=True)
 | 
			
		||||
    mk_vs_proj_link_exe(f, name, debug=True)
 | 
			
		||||
    f.write('  </ItemDefinitionGroup>\n')
 | 
			
		||||
    f.write('  <ItemDefinitionGroup Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">\n')
 | 
			
		||||
    mk_vs_proj_cl_compile(f, name, components, debug=False)
 | 
			
		||||
    mk_vs_proj_link_exe(f, name, debug=False)
 | 
			
		||||
    f.write('  </ItemDefinitionGroup>\n')
 | 
			
		||||
    mk_vs_proj_dep_groups(f, name, components)
 | 
			
		||||
    f.write('  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\n')
 | 
			
		||||
    f.write('  <ImportGroup Label="ExtensionTargets">\n')
 | 
			
		||||
    f.write('  </ImportGroup>\n')
 | 
			
		||||
    f.write('</Project>\n')
 | 
			
		||||
    f.close()
 | 
			
		||||
    if is_verbose():
 | 
			
		||||
        print("Generated '%s'" % proj_name)
 | 
			
		||||
 | 
			
		||||
def mk_vs_proj_link_dll(f, name, debug):
 | 
			
		||||
    f.write('    <Link>\n')
 | 
			
		||||
    f.write('      <OutputFile>$(OutDir)%s.dll</OutputFile>\n' % name)
 | 
			
		||||
    f.write('      <GenerateDebugInformation>true</GenerateDebugInformation>\n')
 | 
			
		||||
    f.write('      <SubSystem>Console</SubSystem>\n')
 | 
			
		||||
    f.write('      <StackReserveSize>8388608</StackReserveSize>\n')
 | 
			
		||||
    f.write('      <RandomizedBaseAddress>false</RandomizedBaseAddress>\n')
 | 
			
		||||
    f.write('      <DataExecutionPrevention/>\n')
 | 
			
		||||
    f.write('      <TargetMachine>MachineX86</TargetMachine>\n')
 | 
			
		||||
    f.write('      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n')
 | 
			
		||||
    f.write('      <AdditionalDependencies>psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n')
 | 
			
		||||
    f.write('      <ModuleDefinitionFile>%s</ModuleDefinitionFile>' % os.path.join(get_component('api_dll').to_src_dir, 'api_dll.def'))
 | 
			
		||||
    f.write('    </Link>\n')
 | 
			
		||||
 | 
			
		||||
def mk_vs_proj_dll(name, components):
 | 
			
		||||
    if not VS_PROJ:
 | 
			
		||||
        return
 | 
			
		||||
    proj_name = '%s.vcxproj' % os.path.join(BUILD_DIR, name)
 | 
			
		||||
    modes=['Debug', 'Release']
 | 
			
		||||
    PLATFORMS=['Win32']
 | 
			
		||||
    f = open(proj_name, 'w')
 | 
			
		||||
    f.write('<?xml version="1.0" encoding="utf-8"?>\n')
 | 
			
		||||
    f.write('<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n')
 | 
			
		||||
    mk_vs_proj_property_groups(f, name, 'dll', 'DynamicLibrary')
 | 
			
		||||
    f.write('  <ItemDefinitionGroup Condition="\'$(Configuration)|$(Platform)\'==\'Debug|Win32\'">\n')
 | 
			
		||||
    mk_vs_proj_cl_compile(f, name, components, debug=True)
 | 
			
		||||
    mk_vs_proj_link_dll(f, name, debug=True)
 | 
			
		||||
    f.write('  </ItemDefinitionGroup>\n')
 | 
			
		||||
    f.write('  <ItemDefinitionGroup Condition="\'$(Configuration)|$(Platform)\'==\'Release|Win32\'">\n')
 | 
			
		||||
    mk_vs_proj_cl_compile(f, name, components, debug=False)
 | 
			
		||||
    mk_vs_proj_link_dll(f, name, debug=False)
 | 
			
		||||
    f.write('  </ItemDefinitionGroup>\n')
 | 
			
		||||
    mk_vs_proj_dep_groups(f, name, components)
 | 
			
		||||
    f.write('  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\n')
 | 
			
		||||
    f.write('  <ImportGroup Label="ExtensionTargets">\n')
 | 
			
		||||
    f.write('  </ImportGroup>\n')
 | 
			
		||||
| 
						 | 
				
			
			@ -3470,22 +3523,17 @@ class MakeRuleCmd(object):
 | 
			
		|||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def _install_root(cls, path, in_prefix, out, is_install=True):
 | 
			
		||||
        if in_prefix:
 | 
			
		||||
            assert not os.path.isabs(path)
 | 
			
		||||
            install_root = cls.install_root()
 | 
			
		||||
        else:
 | 
			
		||||
            # This hack only exists for the Python bindings on OSX
 | 
			
		||||
            # which are sometimes not installed inside the prefix.
 | 
			
		||||
            # In all other cases installing outside the prefix is
 | 
			
		||||
            # misleading and dangerous!
 | 
			
		||||
            assert IS_OSX
 | 
			
		||||
            assert os.path.isabs(path)
 | 
			
		||||
        if not in_prefix:
 | 
			
		||||
            # The Python bindings on OSX are sometimes not installed inside the prefix.
 | 
			
		||||
            install_root = "$(DESTDIR)"
 | 
			
		||||
            action_string = 'install' if is_install else 'uninstall'
 | 
			
		||||
            cls.write_cmd(out, 'echo "WARNING: {}ing files/directories ({}) that are not in the install prefix ($(PREFIX))."'.format(
 | 
			
		||||
                action_string, path))
 | 
			
		||||
            print("WARNING: Generating makefile rule that {}s {} '{}' which is outside the installation prefix '{}'.".format(
 | 
			
		||||
                action_string, 'to' if is_install else 'from', path, PREFIX))
 | 
			
		||||
                    action_string, path))
 | 
			
		||||
            #print("WARNING: Generating makefile rule that {}s {} '{}' which is outside the installation prefix '{}'.".format(
 | 
			
		||||
            #        action_string, 'to' if is_install else 'from', path, PREFIX))
 | 
			
		||||
        else:
 | 
			
		||||
            assert not os.path.isabs(path)
 | 
			
		||||
            install_root = cls.install_root()
 | 
			
		||||
        return install_root
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
| 
						 | 
				
			
			@ -3605,14 +3653,15 @@ class MakeRuleCmd(object):
 | 
			
		|||
        out.write("\t@{}\n".format(line))
 | 
			
		||||
 | 
			
		||||
def strip_path_prefix(path, prefix):
 | 
			
		||||
    assert path.startswith(prefix)
 | 
			
		||||
    stripped_path = path[len(prefix):]
 | 
			
		||||
    stripped_path.replace('//','/')
 | 
			
		||||
    if stripped_path[0] == '/':
 | 
			
		||||
        stripped_path = stripped_path[1:]
 | 
			
		||||
 | 
			
		||||
    assert not os.path.isabs(stripped_path)
 | 
			
		||||
    return stripped_path
 | 
			
		||||
    if path.startswith(prefix):
 | 
			
		||||
        stripped_path = path[len(prefix):]
 | 
			
		||||
        stripped_path.replace('//','/')
 | 
			
		||||
        if stripped_path[0] == '/':
 | 
			
		||||
            stripped_path = stripped_path[1:]
 | 
			
		||||
        assert not os.path.isabs(stripped_path)
 | 
			
		||||
        return stripped_path
 | 
			
		||||
    else:
 | 
			
		||||
        return path
 | 
			
		||||
 | 
			
		||||
def configure_file(template_file_path, output_file_path, substitutions):
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1079,7 +1079,7 @@ def def_API(name, result, params):
 | 
			
		|||
def mk_bindings():
 | 
			
		||||
    exe_c.write("void register_z3_replayer_cmds(z3_replayer & in) {\n")
 | 
			
		||||
    for key, val in API2Id.items():
 | 
			
		||||
        exe_c.write("  in.register_cmd(%s, exec_%s);\n" % (key, val))
 | 
			
		||||
        exe_c.write("  in.register_cmd(%s, exec_%s, \"%s\");\n" % (key, val, val))
 | 
			
		||||
    exe_c.write("}\n")
 | 
			
		||||
 | 
			
		||||
def ml_method_name(name):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,55 +17,55 @@ def fix_hdr(file):
 | 
			
		|||
    line = ins.readline()
 | 
			
		||||
    found = False
 | 
			
		||||
    while line:
 | 
			
		||||
	m = doubleu.search(line)
 | 
			
		||||
	if m:
 | 
			
		||||
	    ous.write("#")
 | 
			
		||||
	    ous.write(m.group(1))
 | 
			
		||||
	    ous.write(" ")
 | 
			
		||||
	    ous.write(m.group(2))
 | 
			
		||||
	    ous.write("_H_\n")
 | 
			
		||||
	    line = ins.readline()
 | 
			
		||||
	    found = True
 | 
			
		||||
	    continue	    
 | 
			
		||||
	m = ifndef.search(line)
 | 
			
		||||
	if m:
 | 
			
		||||
	    print(m.group(1))
 | 
			
		||||
	    ous.write("#ifndef ")
 | 
			
		||||
	    ous.write(m.group(1))
 | 
			
		||||
	    ous.write("_H_\n")
 | 
			
		||||
	    line = ins.readline()
 | 
			
		||||
	    found = True
 | 
			
		||||
	    continue
 | 
			
		||||
	m = defn.search(line)
 | 
			
		||||
	if m:
 | 
			
		||||
	    ous.write("#define ")
 | 
			
		||||
	    ous.write(m.group(1))
 | 
			
		||||
	    ous.write("_H_\n")
 | 
			
		||||
	    line = ins.readline()
 | 
			
		||||
	    found = True
 | 
			
		||||
	    continue
 | 
			
		||||
	m = endif.search(line)
 | 
			
		||||
	if m:
 | 
			
		||||
	    ous.write("#endif /* ")
 | 
			
		||||
	    ous.write(m.group(1))
 | 
			
		||||
	    ous.write("_H_ */\n")
 | 
			
		||||
	    line = ins.readline()
 | 
			
		||||
	    found = True
 | 
			
		||||
	    continue
 | 
			
		||||
	ous.write(line)
 | 
			
		||||
	line = ins.readline()
 | 
			
		||||
        m = doubleu.search(line)
 | 
			
		||||
        if m:
 | 
			
		||||
            ous.write("#")
 | 
			
		||||
            ous.write(m.group(1))
 | 
			
		||||
            ous.write(" ")
 | 
			
		||||
            ous.write(m.group(2))
 | 
			
		||||
            ous.write("_H_\n")
 | 
			
		||||
            line = ins.readline()
 | 
			
		||||
            found = True
 | 
			
		||||
            continue
 | 
			
		||||
        m = ifndef.search(line)
 | 
			
		||||
        if m:
 | 
			
		||||
            print(m.group(1))
 | 
			
		||||
            ous.write("#ifndef ")
 | 
			
		||||
            ous.write(m.group(1))
 | 
			
		||||
            ous.write("_H_\n")
 | 
			
		||||
            line = ins.readline()
 | 
			
		||||
            found = True
 | 
			
		||||
            continue
 | 
			
		||||
        m = defn.search(line)
 | 
			
		||||
        if m:
 | 
			
		||||
            ous.write("#define ")
 | 
			
		||||
            ous.write(m.group(1))
 | 
			
		||||
            ous.write("_H_\n")
 | 
			
		||||
            line = ins.readline()
 | 
			
		||||
            found = True
 | 
			
		||||
            continue
 | 
			
		||||
        m = endif.search(line)
 | 
			
		||||
        if m:
 | 
			
		||||
            ous.write("#endif /* ")
 | 
			
		||||
            ous.write(m.group(1))
 | 
			
		||||
            ous.write("_H_ */\n")
 | 
			
		||||
            line = ins.readline()
 | 
			
		||||
            found = True
 | 
			
		||||
            continue
 | 
			
		||||
        ous.write(line)
 | 
			
		||||
        line = ins.readline()
 | 
			
		||||
    ins.close()
 | 
			
		||||
    ous.close()
 | 
			
		||||
    if found:
 | 
			
		||||
	os.system("move %s %s" % (tmp, file))
 | 
			
		||||
        os.system("move %s %s" % (tmp, file))
 | 
			
		||||
    else:
 | 
			
		||||
	os.system("del %s" % tmp)
 | 
			
		||||
        os.system("del %s" % tmp)
 | 
			
		||||
 | 
			
		||||
def fixup(dir):
 | 
			
		||||
    for root, dirs, files in os.walk(dir):
 | 
			
		||||
	for f in files:
 | 
			
		||||
	    if f.endswith('.h'):
 | 
			
		||||
		path = "%s\\%s" % (root, f)
 | 
			
		||||
		fix_hdr(path)
 | 
			
		||||
        for f in files:
 | 
			
		||||
            if f.endswith('.h'):
 | 
			
		||||
                path = "%s\\%s" % (root, f)
 | 
			
		||||
                fix_hdr(path)
 | 
			
		||||
 | 
			
		||||
fixup('src')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -641,6 +641,12 @@ extern "C" {
 | 
			
		|||
        else if (fid == mk_c(c)->get_fpa_fid() && k == ROUNDING_MODE_SORT) {
 | 
			
		||||
            return Z3_ROUNDING_MODE_SORT;
 | 
			
		||||
        }
 | 
			
		||||
        else if (fid == mk_c(c)->get_seq_fid() && k == SEQ_SORT) {
 | 
			
		||||
            return Z3_SEQ_SORT;
 | 
			
		||||
        }
 | 
			
		||||
        else if (fid == mk_c(c)->get_seq_fid() && k == RE_SORT) {
 | 
			
		||||
            return Z3_RE_SORT;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return Z3_UNKNOWN_SORT;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -776,6 +782,8 @@ extern "C" {
 | 
			
		|||
                SET_ERROR_CODE(Z3_SORT_ERROR);
 | 
			
		||||
                RETURN_Z3(of_expr(0));
 | 
			
		||||
            }
 | 
			
		||||
            SASSERT(from[i]->get_ref_count() > 0);
 | 
			
		||||
            SASSERT(to[i]->get_ref_count() > 0);
 | 
			
		||||
        }
 | 
			
		||||
        expr_safe_replace subst(m);
 | 
			
		||||
        for (unsigned i = 0; i < num_exprs; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1106,6 +1114,32 @@ extern "C" {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mk_c(c)->get_seq_fid() == _d->get_family_id()) {
 | 
			
		||||
            switch (_d->get_decl_kind()) {
 | 
			
		||||
            case Z3_OP_SEQ_UNIT: return Z3_OP_SEQ_UNIT;
 | 
			
		||||
            case Z3_OP_SEQ_EMPTY: return Z3_OP_SEQ_EMPTY;
 | 
			
		||||
            case Z3_OP_SEQ_CONCAT: return Z3_OP_SEQ_CONCAT;
 | 
			
		||||
            case Z3_OP_SEQ_PREFIX: return Z3_OP_SEQ_PREFIX;
 | 
			
		||||
            case Z3_OP_SEQ_SUFFIX: return Z3_OP_SEQ_SUFFIX;
 | 
			
		||||
            case Z3_OP_SEQ_CONTAINS: return Z3_OP_SEQ_CONTAINS;
 | 
			
		||||
            case Z3_OP_SEQ_EXTRACT: return Z3_OP_SEQ_EXTRACT;
 | 
			
		||||
            case Z3_OP_SEQ_REPLACE: return Z3_OP_SEQ_REPLACE;
 | 
			
		||||
            case Z3_OP_SEQ_AT: return Z3_OP_SEQ_AT;
 | 
			
		||||
            case Z3_OP_SEQ_LENGTH: return Z3_OP_SEQ_LENGTH;
 | 
			
		||||
            case Z3_OP_SEQ_INDEX: return Z3_OP_SEQ_INDEX;
 | 
			
		||||
            case Z3_OP_SEQ_TO_RE: return Z3_OP_SEQ_TO_RE;
 | 
			
		||||
            case Z3_OP_SEQ_IN_RE: return Z3_OP_SEQ_IN_RE;
 | 
			
		||||
                    
 | 
			
		||||
            case Z3_OP_RE_PLUS: return Z3_OP_RE_PLUS;
 | 
			
		||||
            case Z3_OP_RE_STAR: return Z3_OP_RE_STAR;
 | 
			
		||||
            case Z3_OP_RE_OPTION: return Z3_OP_RE_OPTION;
 | 
			
		||||
            case Z3_OP_RE_CONCAT: return Z3_OP_RE_CONCAT;
 | 
			
		||||
            case Z3_OP_RE_UNION: return Z3_OP_RE_UNION;
 | 
			
		||||
            default:
 | 
			
		||||
                return Z3_OP_UNINTERPRETED;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mk_c(c)->get_fpa_fid() == _d->get_family_id()) {
 | 
			
		||||
            switch (_d->get_decl_kind()) {
 | 
			
		||||
            case OP_FPA_RM_NEAREST_TIES_TO_EVEN: return Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,6 +73,7 @@ namespace api {
 | 
			
		|||
        m_datalog_util(m()),
 | 
			
		||||
        m_fpa_util(m()),
 | 
			
		||||
        m_dtutil(m()),
 | 
			
		||||
        m_sutil(m()),
 | 
			
		||||
        m_last_result(m()),
 | 
			
		||||
        m_ast_trail(m()),
 | 
			
		||||
        m_replay_stack(),
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +98,7 @@ namespace api {
 | 
			
		|||
        m_dt_fid    = m().mk_family_id("datatype");
 | 
			
		||||
        m_datalog_fid = m().mk_family_id("datalog_relation");
 | 
			
		||||
        m_fpa_fid   = m().mk_family_id("fpa");
 | 
			
		||||
        m_seq_fid   = m().mk_family_id("seq");
 | 
			
		||||
        m_dt_plugin = static_cast<datatype_decl_plugin*>(m().get_plugin(m_dt_fid));
 | 
			
		||||
 | 
			
		||||
        if (!m_user_ref_count) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ Revision History:
 | 
			
		|||
#include"api_util.h"
 | 
			
		||||
#include"arith_decl_plugin.h"
 | 
			
		||||
#include"bv_decl_plugin.h"
 | 
			
		||||
#include"seq_decl_plugin.h"
 | 
			
		||||
#include"datatype_decl_plugin.h"
 | 
			
		||||
#include"dl_decl_plugin.h"
 | 
			
		||||
#include"fpa_decl_plugin.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +59,7 @@ namespace api {
 | 
			
		|||
        datalog::dl_decl_util      m_datalog_util;
 | 
			
		||||
        fpa_util                   m_fpa_util;
 | 
			
		||||
	datatype_util              m_dtutil;
 | 
			
		||||
        seq_util                   m_sutil;
 | 
			
		||||
 | 
			
		||||
        // Support for old solver API
 | 
			
		||||
        smt_params                 m_fparams;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +80,7 @@ namespace api {
 | 
			
		|||
        family_id                  m_datalog_fid;
 | 
			
		||||
        family_id                  m_pb_fid;
 | 
			
		||||
        family_id                  m_fpa_fid;
 | 
			
		||||
        family_id                  m_seq_fid;
 | 
			
		||||
        datatype_decl_plugin *     m_dt_plugin;
 | 
			
		||||
        
 | 
			
		||||
        std::string                m_string_buffer; // temporary buffer used to cache strings sent to the "external" world.
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +124,7 @@ namespace api {
 | 
			
		|||
        datalog::dl_decl_util & datalog_util() { return m_datalog_util; }
 | 
			
		||||
        fpa_util & fpautil() { return m_fpa_util; }
 | 
			
		||||
	datatype_util& dtutil() { return m_dtutil; }
 | 
			
		||||
        seq_util& sutil() { return m_sutil; }
 | 
			
		||||
        family_id get_basic_fid() const { return m_basic_fid; }
 | 
			
		||||
        family_id get_array_fid() const { return m_array_fid; }
 | 
			
		||||
        family_id get_arith_fid() const { return m_arith_fid; }
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +133,7 @@ namespace api {
 | 
			
		|||
        family_id get_datalog_fid() const { return m_datalog_fid; }
 | 
			
		||||
        family_id get_pb_fid() const { return m_pb_fid; }
 | 
			
		||||
        family_id get_fpa_fid() const { return m_fpa_fid; }
 | 
			
		||||
        family_id get_seq_fid() const { return m_seq_fid; }
 | 
			
		||||
        datatype_decl_plugin * get_dt_plugin() const { return m_dt_plugin; }
 | 
			
		||||
 | 
			
		||||
        Z3_error_code get_error_code() const { return m_error_code; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -268,14 +268,14 @@ extern "C" {
 | 
			
		|||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_fpa_fp(Z3_context c, Z3_ast sgn, Z3_ast exp, Z3_ast sig) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_fpa_fp(c, sgn, sig, exp);
 | 
			
		||||
        LOG_Z3_mk_fpa_fp(c, sgn, exp, sig);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        if (!is_bv(c, sgn) || !is_bv(c, exp) || !is_bv(c, sig)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            RETURN_Z3(0);
 | 
			
		||||
        }
 | 
			
		||||
        api::context * ctx = mk_c(c);
 | 
			
		||||
        expr * a = ctx->fpautil().mk_fp(to_expr(sgn), to_expr(sig), to_expr(exp));
 | 
			
		||||
        expr * a = ctx->fpautil().mk_fp(to_expr(sgn), to_expr(exp), to_expr(sig));
 | 
			
		||||
        ctx->save_ast_trail(a);
 | 
			
		||||
        RETURN_Z3(of_expr(a));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
| 
						 | 
				
			
			@ -351,7 +351,7 @@ extern "C" {
 | 
			
		|||
        ctx->fpautil().fm().set(tmp,
 | 
			
		||||
                                ctx->fpautil().get_ebits(to_sort(ty)),
 | 
			
		||||
                                ctx->fpautil().get_sbits(to_sort(ty)),
 | 
			
		||||
                                sgn != 0, sig, exp);
 | 
			
		||||
                                sgn != 0, exp, sig);
 | 
			
		||||
        expr * a = ctx->fpautil().mk_value(tmp);
 | 
			
		||||
        ctx->save_ast_trail(a);
 | 
			
		||||
        RETURN_Z3(of_expr(a));
 | 
			
		||||
| 
						 | 
				
			
			@ -371,7 +371,7 @@ extern "C" {
 | 
			
		|||
        ctx->fpautil().fm().set(tmp,
 | 
			
		||||
                                ctx->fpautil().get_ebits(to_sort(ty)),
 | 
			
		||||
                                ctx->fpautil().get_sbits(to_sort(ty)),
 | 
			
		||||
                                sgn != 0, sig, exp);
 | 
			
		||||
                                sgn != 0, exp, sig);
 | 
			
		||||
        expr * a = ctx->fpautil().mk_value(tmp);
 | 
			
		||||
        ctx->save_ast_trail(a);
 | 
			
		||||
        RETURN_Z3(of_expr(a));
 | 
			
		||||
| 
						 | 
				
			
			@ -931,15 +931,23 @@ extern "C" {
 | 
			
		|||
        mpf_manager & mpfm = mk_c(c)->fpautil().fm();
 | 
			
		||||
        unsynch_mpz_manager & mpzm = mpfm.mpz_manager();
 | 
			
		||||
        unsynch_mpq_manager & mpqm = mpfm.mpq_manager();
 | 
			
		||||
        fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid());
 | 
			
		||||
        scoped_mpf val(mpfm);
 | 
			
		||||
        if (!plugin->is_numeral(to_expr(t), val)) {
 | 
			
		||||
        family_id fid = mk_c(c)->get_fpa_fid();
 | 
			
		||||
        fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(fid);
 | 
			
		||||
        SASSERT(plugin != 0);
 | 
			
		||||
        expr * e = to_expr(t);
 | 
			
		||||
        if (!is_app(e) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_NAN) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_PLUS_INF) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_MINUS_INF)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
        else if (!mpfm.is_regular(val)) {
 | 
			
		||||
        scoped_mpf val(mpfm);
 | 
			
		||||
        app * a = to_app(e);
 | 
			
		||||
        bool r = plugin->is_numeral(e, val);
 | 
			
		||||
        if (!r || !mpfm.is_regular(val)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG)
 | 
			
		||||
                return "";
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
        unsigned sbits = val.get().get_sbits();
 | 
			
		||||
        scoped_mpq q(mpqm);
 | 
			
		||||
| 
						 | 
				
			
			@ -960,16 +968,25 @@ extern "C" {
 | 
			
		|||
        ast_manager & m = mk_c(c)->m();
 | 
			
		||||
        mpf_manager & mpfm = mk_c(c)->fpautil().fm();
 | 
			
		||||
        unsynch_mpz_manager & mpzm = mpfm.mpz_manager();
 | 
			
		||||
        fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid());
 | 
			
		||||
        scoped_mpf val(mpfm);
 | 
			
		||||
        bool r = plugin->is_numeral(to_expr(t), val);
 | 
			
		||||
        if (!r) {
 | 
			
		||||
        family_id fid = mk_c(c)->get_fpa_fid();
 | 
			
		||||
        fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(fid);
 | 
			
		||||
        SASSERT(plugin != 0);
 | 
			
		||||
        expr * e = to_expr(t);
 | 
			
		||||
        if (!is_app(e) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_NAN) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_PLUS_INF) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_MINUS_INF)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            *n = 0;
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        scoped_mpf val(mpfm);
 | 
			
		||||
        app * a = to_app(e);
 | 
			
		||||
        bool r = plugin->is_numeral(e, val);
 | 
			
		||||
        const mpz & z = mpfm.sig(val);
 | 
			
		||||
        if (!mpzm.is_uint64(z)) {
 | 
			
		||||
        if (!r || mpfm.is_regular(val)|| !mpzm.is_uint64(z)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            *n = 0;
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        *n = mpzm.get_uint64(z);
 | 
			
		||||
| 
						 | 
				
			
			@ -983,16 +1000,23 @@ extern "C" {
 | 
			
		|||
        RESET_ERROR_CODE();
 | 
			
		||||
        ast_manager & m = mk_c(c)->m();
 | 
			
		||||
        mpf_manager & mpfm = mk_c(c)->fpautil().fm();
 | 
			
		||||
        family_id fid = mk_c(c)->get_fpa_fid();
 | 
			
		||||
        fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid());
 | 
			
		||||
        scoped_mpf val(mpfm);
 | 
			
		||||
        bool r = plugin->is_numeral(to_expr(t), val);
 | 
			
		||||
        if (!r) {
 | 
			
		||||
        SASSERT(plugin != 0);
 | 
			
		||||
        expr * e = to_expr(t);
 | 
			
		||||
        if (!is_app(e) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_NAN) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_PLUS_INF) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_MINUS_INF)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
        else if (!mpfm.is_normal(val) && !mpfm.is_denormal(val)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG)
 | 
			
		||||
                return "";
 | 
			
		||||
        scoped_mpf val(mpfm);
 | 
			
		||||
        app * a = to_app(e);
 | 
			
		||||
        bool r = plugin->is_numeral(e, val);
 | 
			
		||||
        if (!r || !mpfm.is_regular(val)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
        mpf_exp_t exp = mpfm.exp_normalized(val);
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
| 
						 | 
				
			
			@ -1007,11 +1031,24 @@ extern "C" {
 | 
			
		|||
        RESET_ERROR_CODE();
 | 
			
		||||
        ast_manager & m = mk_c(c)->m();
 | 
			
		||||
        mpf_manager & mpfm = mk_c(c)->fpautil().fm();
 | 
			
		||||
        family_id fid = mk_c(c)->get_fpa_fid();
 | 
			
		||||
        fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid());
 | 
			
		||||
        scoped_mpf val(mpfm);
 | 
			
		||||
        bool r = plugin->is_numeral(to_expr(t), val);
 | 
			
		||||
        if (!r) {
 | 
			
		||||
        SASSERT(plugin != 0);
 | 
			
		||||
        expr * e = to_expr(t);
 | 
			
		||||
        if (!is_app(e) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_NAN) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_PLUS_INF) ||
 | 
			
		||||
            is_app_of(e, fid, OP_FPA_MINUS_INF)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            *n = 0;
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        scoped_mpf val(mpfm);
 | 
			
		||||
        app * a = to_app(e);
 | 
			
		||||
        bool r = plugin->is_numeral(e, val);
 | 
			
		||||
        if (!r || !mpfm.is_regular(val)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            *n = 0;
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        *n = mpfm.exp(val);
 | 
			
		||||
| 
						 | 
				
			
			@ -1035,18 +1072,18 @@ extern "C" {
 | 
			
		|||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_fpa_to_fp_int_real(Z3_context c, Z3_ast rm, Z3_ast exp, Z3_ast sig, Z3_sort s) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_fpa_to_fp_int_real(c, rm, sig, exp, s);
 | 
			
		||||
        LOG_Z3_mk_fpa_to_fp_int_real(c, rm, exp, sig, s);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        api::context * ctx = mk_c(c);
 | 
			
		||||
        fpa_util & fu = ctx->fpautil();
 | 
			
		||||
        if (!fu.is_rm(to_expr(rm)) ||
 | 
			
		||||
            !ctx->autil().is_real(to_expr(sig)) ||
 | 
			
		||||
            !ctx->autil().is_int(to_expr(exp)) ||
 | 
			
		||||
            !ctx->autil().is_real(to_expr(sig)) ||
 | 
			
		||||
            !fu.is_float(to_sort(s))) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        expr * a = fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(sig), to_expr(exp));
 | 
			
		||||
        expr * a = fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(exp), to_expr(sig));
 | 
			
		||||
        ctx->save_ast_trail(a);
 | 
			
		||||
        RETURN_Z3(of_expr(a));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -277,7 +277,9 @@ extern "C" {
 | 
			
		|||
        RESET_ERROR_CODE();
 | 
			
		||||
        CHECK_NON_NULL(f, 0);
 | 
			
		||||
        expr * e = to_func_interp_ref(f)->get_else();
 | 
			
		||||
        mk_c(c)->save_ast_trail(e);
 | 
			
		||||
        if (e) {
 | 
			
		||||
            mk_c(c)->save_ast_trail(e);
 | 
			
		||||
        }
 | 
			
		||||
        RETURN_Z3(of_expr(e));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										151
									
								
								src/api/api_seq.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								src/api/api_seq.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,151 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2016 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    api_seq.cpp
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    API for sequences and regular expressions.
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Nikolaj Bjorner (nbjorner) 2016-01-02.
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
#include<iostream>
 | 
			
		||||
#include"z3.h"
 | 
			
		||||
#include"api_log_macros.h"
 | 
			
		||||
#include"api_context.h"
 | 
			
		||||
#include"api_util.h"
 | 
			
		||||
#include"ast_pp.h"
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
 | 
			
		||||
    Z3_sort Z3_API Z3_mk_seq_sort(Z3_context c, Z3_sort domain) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_seq_sort(c, domain);
 | 
			
		||||
        RESET_ERROR_CODE();  
 | 
			
		||||
        sort * ty =  mk_c(c)->sutil().str.mk_seq(to_sort(domain));
 | 
			
		||||
        mk_c(c)->save_ast_trail(ty);
 | 
			
		||||
        RETURN_Z3(of_sort(ty));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_sort Z3_API Z3_mk_re_sort(Z3_context c, Z3_sort domain) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_re_sort(c, domain);
 | 
			
		||||
        RESET_ERROR_CODE();  
 | 
			
		||||
        sort * ty =  mk_c(c)->sutil().re.mk_re(to_sort(domain));
 | 
			
		||||
        mk_c(c)->save_ast_trail(ty);
 | 
			
		||||
        RETURN_Z3(of_sort(ty));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_string(Z3_context c, Z3_string str) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_string(c, str);
 | 
			
		||||
        RESET_ERROR_CODE();  
 | 
			
		||||
        zstring s(str, zstring::ascii);
 | 
			
		||||
        app* a = mk_c(c)->sutil().str.mk_string(s);
 | 
			
		||||
        mk_c(c)->save_ast_trail(a);
 | 
			
		||||
        RETURN_Z3(of_ast(a));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    Z3_sort Z3_API Z3_mk_string_sort(Z3_context c) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_string_sort(c);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        sort* ty = mk_c(c)->sutil().str.mk_string_sort();
 | 
			
		||||
        mk_c(c)->save_ast_trail(ty);
 | 
			
		||||
        RETURN_Z3(of_sort(ty));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_bool Z3_API Z3_is_seq_sort(Z3_context c, Z3_sort s) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_is_seq_sort(c, s);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        bool result = mk_c(c)->sutil().is_seq(to_sort(s));
 | 
			
		||||
        return result?Z3_TRUE:Z3_FALSE;        
 | 
			
		||||
        Z3_CATCH_RETURN(Z3_FALSE);        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_bool Z3_API Z3_is_re_sort(Z3_context c, Z3_sort s) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_is_re_sort(c, s);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        bool result = mk_c(c)->sutil().is_re(to_sort(s));
 | 
			
		||||
        return result?Z3_TRUE:Z3_FALSE;        
 | 
			
		||||
        Z3_CATCH_RETURN(Z3_FALSE);        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_bool Z3_API Z3_is_string_sort(Z3_context c, Z3_sort s) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_is_string_sort(c, s);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        bool result = mk_c(c)->sutil().is_string(to_sort(s));
 | 
			
		||||
        return result?Z3_TRUE:Z3_FALSE;        
 | 
			
		||||
        Z3_CATCH_RETURN(Z3_FALSE);        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_bool Z3_API Z3_is_string(Z3_context c, Z3_ast s) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_is_string(c, s);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        bool result = mk_c(c)->sutil().str.is_string(to_expr(s));
 | 
			
		||||
        return result?Z3_TRUE:Z3_FALSE;        
 | 
			
		||||
        Z3_CATCH_RETURN(Z3_FALSE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_string Z3_API Z3_get_string(Z3_context c, Z3_ast s) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_get_string(c, s);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        zstring str;
 | 
			
		||||
        if (!mk_c(c)->sutil().str.is_string(to_expr(s), str)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
        std::string result = str.encode();
 | 
			
		||||
        return mk_c(c)->mk_external_string(result);
 | 
			
		||||
        Z3_CATCH_RETURN("");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_empty(Z3_context c, Z3_sort seq) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_seq_empty(c, seq);
 | 
			
		||||
        RESET_ERROR_CODE();  
 | 
			
		||||
        app* a = mk_c(c)->sutil().str.mk_empty(to_sort(seq));
 | 
			
		||||
        mk_c(c)->save_ast_trail(a);
 | 
			
		||||
        RETURN_Z3(of_ast(a));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MK_UNARY(Z3_mk_seq_unit, mk_c(c)->get_seq_fid(), OP_SEQ_UNIT, SKIP);
 | 
			
		||||
    MK_NARY(Z3_mk_seq_concat, mk_c(c)->get_seq_fid(), OP_SEQ_CONCAT, SKIP);
 | 
			
		||||
    MK_BINARY(Z3_mk_seq_prefix, mk_c(c)->get_seq_fid(), OP_SEQ_PREFIX, SKIP);
 | 
			
		||||
    MK_BINARY(Z3_mk_seq_suffix, mk_c(c)->get_seq_fid(), OP_SEQ_SUFFIX, SKIP);
 | 
			
		||||
    MK_BINARY(Z3_mk_seq_contains, mk_c(c)->get_seq_fid(), OP_SEQ_CONTAINS, SKIP);
 | 
			
		||||
    MK_TERNARY(Z3_mk_seq_extract, mk_c(c)->get_seq_fid(), OP_SEQ_EXTRACT, SKIP);
 | 
			
		||||
    MK_TERNARY(Z3_mk_seq_replace, mk_c(c)->get_seq_fid(), OP_SEQ_REPLACE, SKIP);
 | 
			
		||||
    MK_BINARY(Z3_mk_seq_at, mk_c(c)->get_seq_fid(), OP_SEQ_AT, SKIP);
 | 
			
		||||
    MK_UNARY(Z3_mk_seq_length, mk_c(c)->get_seq_fid(), OP_SEQ_LENGTH, SKIP);
 | 
			
		||||
    MK_TERNARY(Z3_mk_seq_index, mk_c(c)->get_seq_fid(), OP_SEQ_INDEX, SKIP);
 | 
			
		||||
    MK_UNARY(Z3_mk_seq_to_re, mk_c(c)->get_seq_fid(), OP_SEQ_TO_RE, SKIP);
 | 
			
		||||
    MK_BINARY(Z3_mk_seq_in_re, mk_c(c)->get_seq_fid(), OP_SEQ_IN_RE, SKIP);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    MK_UNARY(Z3_mk_re_plus, mk_c(c)->get_seq_fid(), OP_RE_PLUS, SKIP);
 | 
			
		||||
    MK_UNARY(Z3_mk_re_star, mk_c(c)->get_seq_fid(), OP_RE_STAR, SKIP);
 | 
			
		||||
    MK_UNARY(Z3_mk_re_option, mk_c(c)->get_seq_fid(), OP_RE_OPTION, SKIP);
 | 
			
		||||
    MK_NARY(Z3_mk_re_union, mk_c(c)->get_seq_fid(), OP_RE_UNION, SKIP);
 | 
			
		||||
    MK_NARY(Z3_mk_re_concat, mk_c(c)->get_seq_fid(), OP_RE_CONCAT, SKIP);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +135,23 @@ Z3_ast Z3_API NAME(Z3_context c, Z3_ast n1, Z3_ast n2) {        \
 | 
			
		|||
    MK_BINARY_BODY(NAME, FID, OP, EXTRA_CODE);                  \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MK_TERNARY_BODY(NAME, FID, OP, EXTRA_CODE)               \
 | 
			
		||||
    Z3_TRY;                                                     \
 | 
			
		||||
    RESET_ERROR_CODE();                                         \
 | 
			
		||||
    EXTRA_CODE;                                                 \
 | 
			
		||||
    expr * args[3] = { to_expr(n1), to_expr(n2), to_expr(n3) }; \
 | 
			
		||||
    ast* a = mk_c(c)->m().mk_app(FID, OP, 0, 0, 3, args);       \
 | 
			
		||||
    mk_c(c)->save_ast_trail(a);                                 \
 | 
			
		||||
    check_sorts(c, a);                                          \
 | 
			
		||||
    RETURN_Z3(of_ast(a));                                       \
 | 
			
		||||
    Z3_CATCH_RETURN(0);
 | 
			
		||||
 
 | 
			
		||||
#define MK_TERNARY(NAME, FID, OP, EXTRA_CODE)                            \
 | 
			
		||||
    Z3_ast Z3_API NAME(Z3_context c, Z3_ast n1, Z3_ast n2, Z3_ast n3) { \
 | 
			
		||||
    LOG_ ## NAME(c, n1, n2, n3);                                        \
 | 
			
		||||
    MK_TERNARY_BODY(NAME, FID, OP, EXTRA_CODE);                          \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MK_NARY(NAME, FID, OP, EXTRA_CODE)                              \
 | 
			
		||||
Z3_ast Z3_API NAME(Z3_context c, unsigned num_args, Z3_ast const* args) { \
 | 
			
		||||
    Z3_TRY;                                                             \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -205,6 +205,18 @@ namespace z3 {
 | 
			
		|||
           \brief Return the Bit-vector sort of size \c sz. That is, the sort for bit-vectors of size \c sz.
 | 
			
		||||
        */
 | 
			
		||||
        sort bv_sort(unsigned sz);
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return the sort for ASCII strings.
 | 
			
		||||
         */
 | 
			
		||||
        sort string_sort();
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return a sequence sort over base sort \c s.
 | 
			
		||||
         */
 | 
			
		||||
        sort seq_sort(sort& s);
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return a regular expression sort over sequences \c seq_sort.
 | 
			
		||||
         */
 | 
			
		||||
        sort re_sort(sort& seq_sort);
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return an array sort for arrays from \c d to \c r.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -261,6 +273,9 @@ namespace z3 {
 | 
			
		|||
        expr bv_val(__uint64 n, unsigned sz);
 | 
			
		||||
        expr bv_val(char const * n, unsigned sz);
 | 
			
		||||
 | 
			
		||||
        expr string_val(char const* s);
 | 
			
		||||
        expr string_val(std::string const& s);
 | 
			
		||||
 | 
			
		||||
        expr num_val(int n, sort const & s);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
| 
						 | 
				
			
			@ -425,6 +440,14 @@ namespace z3 {
 | 
			
		|||
            \brief Return true if this sort is a Relation sort.
 | 
			
		||||
        */
 | 
			
		||||
        bool is_relation() const { return sort_kind() == Z3_RELATION_SORT; }
 | 
			
		||||
        /**
 | 
			
		||||
            \brief Return true if this sort is a Sequence sort.
 | 
			
		||||
        */
 | 
			
		||||
        bool is_seq() const { return sort_kind() == Z3_SEQ_SORT; }
 | 
			
		||||
        /**
 | 
			
		||||
            \brief Return true if this sort is a regular expression sort.
 | 
			
		||||
        */
 | 
			
		||||
        bool is_re() const { return sort_kind() == Z3_RE_SORT; }
 | 
			
		||||
        /**
 | 
			
		||||
            \brief Return true if this sort is a Finite domain sort.
 | 
			
		||||
        */
 | 
			
		||||
| 
						 | 
				
			
			@ -532,6 +555,15 @@ namespace z3 {
 | 
			
		|||
           \brief Return true if this is a Relation expression.
 | 
			
		||||
        */
 | 
			
		||||
        bool is_relation() const { return get_sort().is_relation(); }
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return true if this is a sequence expression.
 | 
			
		||||
        */
 | 
			
		||||
        bool is_seq() const { return get_sort().is_seq(); }
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return true if this is a regular expression.
 | 
			
		||||
        */
 | 
			
		||||
        bool is_re() const { return get_sort().is_re(); }
 | 
			
		||||
        
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return true if this is a Finite-domain expression.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -663,6 +695,7 @@ namespace z3 {
 | 
			
		|||
 | 
			
		||||
        friend expr distinct(expr_vector const& args);
 | 
			
		||||
        friend expr concat(expr const& a, expr const& b);
 | 
			
		||||
        friend expr concat(expr_vector const& args);
 | 
			
		||||
 | 
			
		||||
        friend expr operator==(expr const & a, expr const & b);
 | 
			
		||||
        friend expr operator==(expr const & a, int b);
 | 
			
		||||
| 
						 | 
				
			
			@ -728,10 +761,50 @@ namespace z3 {
 | 
			
		|||
        friend expr operator|(int a, expr const & b);
 | 
			
		||||
 | 
			
		||||
        friend expr operator~(expr const & a);
 | 
			
		||||
        expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); return expr(ctx(), r); }
 | 
			
		||||
        expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); ctx().check_error(); return expr(ctx(), r); }        
 | 
			
		||||
        unsigned lo() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 1)); }
 | 
			
		||||
        unsigned hi() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 0)); }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief sequence and regular expression operations.
 | 
			
		||||
           + is overloaeded as sequence concatenation and regular expression union.
 | 
			
		||||
           concat is overloaded to handle sequences and regular expressions
 | 
			
		||||
        */
 | 
			
		||||
        expr extract(expr const& offset, expr const& length) const { 
 | 
			
		||||
            check_context(*this, offset); check_context(offset, length);
 | 
			
		||||
            Z3_ast r = Z3_mk_seq_extract(ctx(), *this, offset, length); check_error(); return expr(ctx(), r); 
 | 
			
		||||
        }
 | 
			
		||||
        expr replace(expr const& src, expr const& dst) const {
 | 
			
		||||
            check_context(*this, src); check_context(src, dst);
 | 
			
		||||
            Z3_ast r = Z3_mk_seq_replace(ctx(), *this, src, dst);
 | 
			
		||||
            check_error();
 | 
			
		||||
            return expr(ctx(), r);
 | 
			
		||||
        }
 | 
			
		||||
        expr unit() const {
 | 
			
		||||
            Z3_ast r = Z3_mk_seq_unit(ctx(), *this);
 | 
			
		||||
            check_error();
 | 
			
		||||
            return expr(ctx(), r);
 | 
			
		||||
        }
 | 
			
		||||
        expr contains(expr const& s) {
 | 
			
		||||
            check_context(*this, s);
 | 
			
		||||
            Z3_ast r = Z3_mk_seq_contains(ctx(), *this, s);
 | 
			
		||||
            check_error();
 | 
			
		||||
            return expr(ctx(), r);
 | 
			
		||||
        }
 | 
			
		||||
        expr at(expr const& index) const {
 | 
			
		||||
            check_context(*this, index);
 | 
			
		||||
            Z3_ast r = Z3_mk_seq_at(ctx(), *this, index);
 | 
			
		||||
            check_error();
 | 
			
		||||
            return expr(ctx(), r);
 | 
			
		||||
        }
 | 
			
		||||
        expr length() const {
 | 
			
		||||
            Z3_ast r = Z3_mk_seq_length(ctx(), *this);
 | 
			
		||||
            check_error();
 | 
			
		||||
            return expr(ctx(), r);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return a simplified version of this expression.
 | 
			
		||||
        */
 | 
			
		||||
| 
						 | 
				
			
			@ -835,6 +908,13 @@ namespace z3 {
 | 
			
		|||
        else if (a.is_bv() && b.is_bv()) {
 | 
			
		||||
            r = Z3_mk_bvadd(a.ctx(), a, b);
 | 
			
		||||
        }
 | 
			
		||||
        else if (a.is_seq() && b.is_seq()) {
 | 
			
		||||
            return concat(a, b);
 | 
			
		||||
        }
 | 
			
		||||
        else if (a.is_re() && b.is_re()) {
 | 
			
		||||
            Z3_ast _args[2] = { a, b };
 | 
			
		||||
            r = Z3_mk_re_union(a.ctx(), 2, _args);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            // operator is not supported by given arguments.
 | 
			
		||||
            assert(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -1219,11 +1299,48 @@ namespace z3 {
 | 
			
		|||
 | 
			
		||||
    inline expr concat(expr const& a, expr const& b) {
 | 
			
		||||
        check_context(a, b);
 | 
			
		||||
        Z3_ast r = Z3_mk_concat(a.ctx(), a, b);
 | 
			
		||||
        Z3_ast r;
 | 
			
		||||
        if (Z3_is_seq_sort(a.ctx(), a.get_sort())) {
 | 
			
		||||
            Z3_ast _args[2] = { a, b };
 | 
			
		||||
            r = Z3_mk_seq_concat(a.ctx(), 2, _args);
 | 
			
		||||
        }
 | 
			
		||||
        else if (Z3_is_re_sort(a.ctx(), a.get_sort())) {
 | 
			
		||||
            Z3_ast _args[2] = { a, b };
 | 
			
		||||
            r = Z3_mk_re_concat(a.ctx(), 2, _args);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            r = Z3_mk_concat(a.ctx(), a, b);
 | 
			
		||||
        }
 | 
			
		||||
        a.ctx().check_error();
 | 
			
		||||
        return expr(a.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline expr concat(expr_vector const& args) {
 | 
			
		||||
        Z3_ast r;
 | 
			
		||||
        assert(args.size() > 0);
 | 
			
		||||
        if (args.size() == 1) {
 | 
			
		||||
            return args[0];
 | 
			
		||||
        }
 | 
			
		||||
        context& ctx = args[0].ctx();
 | 
			
		||||
        array<Z3_ast> _args(args);
 | 
			
		||||
        if (Z3_is_seq_sort(ctx, args[0].get_sort())) {
 | 
			
		||||
            r = Z3_mk_seq_concat(ctx, _args.size(), _args.ptr());
 | 
			
		||||
        }
 | 
			
		||||
        else if (Z3_is_re_sort(ctx, args[0].get_sort())) {
 | 
			
		||||
            r = Z3_mk_re_concat(ctx, _args.size(), _args.ptr());
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            r = _args[args.size()-1];
 | 
			
		||||
            for (unsigned i = args.size()-1; i > 0; ) {
 | 
			
		||||
                --i;
 | 
			
		||||
                r = Z3_mk_concat(ctx, _args[i], r);
 | 
			
		||||
                ctx.check_error();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        ctx.check_error();
 | 
			
		||||
        return expr(ctx, r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class func_entry : public object {
 | 
			
		||||
        Z3_func_entry m_entry;
 | 
			
		||||
        void init(Z3_func_entry e) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1762,6 +1879,10 @@ namespace z3 {
 | 
			
		|||
    inline sort context::int_sort() { Z3_sort s = Z3_mk_int_sort(m_ctx); check_error(); return sort(*this, s); }
 | 
			
		||||
    inline sort context::real_sort() { Z3_sort s = Z3_mk_real_sort(m_ctx); check_error(); return sort(*this, s); }
 | 
			
		||||
    inline sort context::bv_sort(unsigned sz) { Z3_sort s = Z3_mk_bv_sort(m_ctx, sz); check_error(); return sort(*this, s); }
 | 
			
		||||
    inline sort context::string_sort() { Z3_sort s = Z3_mk_string_sort(m_ctx); check_error(); return sort(*this, s); }
 | 
			
		||||
    inline sort context::seq_sort(sort& s) { Z3_sort r = Z3_mk_seq_sort(m_ctx, s); check_error(); return sort(*this, r); }
 | 
			
		||||
    inline sort context::re_sort(sort& s) { Z3_sort r = Z3_mk_re_sort(m_ctx, s); check_error(); return sort(*this, r); }
 | 
			
		||||
 | 
			
		||||
    inline sort context::array_sort(sort d, sort r) { Z3_sort s = Z3_mk_array_sort(m_ctx, d, r); check_error(); return sort(*this, s); }
 | 
			
		||||
    inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
 | 
			
		||||
        array<Z3_symbol> _enum_names(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -1885,6 +2006,9 @@ namespace z3 {
 | 
			
		|||
    inline expr context::bv_val(__uint64 n, unsigned sz) { Z3_ast r = Z3_mk_unsigned_int64(m_ctx, n, bv_sort(sz)); check_error(); return expr(*this, r); }
 | 
			
		||||
    inline expr context::bv_val(char const * n, unsigned sz) { Z3_ast r = Z3_mk_numeral(m_ctx, n, bv_sort(sz)); check_error(); return expr(*this, r); }
 | 
			
		||||
 | 
			
		||||
    inline expr context::string_val(char const* s) { Z3_ast r = Z3_mk_string(m_ctx, s); check_error(); return expr(*this, r); }
 | 
			
		||||
    inline expr context::string_val(std::string const& s) { Z3_ast r = Z3_mk_string(m_ctx, s.c_str()); check_error(); return expr(*this, r); }
 | 
			
		||||
 | 
			
		||||
    inline expr context::num_val(int n, sort const & s) { Z3_ast r = Z3_mk_int(m_ctx, n, s); check_error(); return expr(*this, r); }
 | 
			
		||||
 | 
			
		||||
    inline expr func_decl::operator()(unsigned n, expr const * args) const {
 | 
			
		||||
| 
						 | 
				
			
			@ -2017,6 +2141,62 @@ namespace z3 {
 | 
			
		|||
        d.check_error();
 | 
			
		||||
        return expr(d.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // sequence and regular expression operations.
 | 
			
		||||
    // union is +
 | 
			
		||||
    // concat is overloaded to handle sequences and regular expressions
 | 
			
		||||
 | 
			
		||||
    inline expr empty(sort const& s) {
 | 
			
		||||
        Z3_ast r = Z3_mk_seq_empty(s.ctx(), s);
 | 
			
		||||
        s.check_error();
 | 
			
		||||
        return expr(s.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr suffixof(expr const& a, expr const& b) {
 | 
			
		||||
        check_context(a, b);
 | 
			
		||||
        Z3_ast r = Z3_mk_seq_suffix(a.ctx(), a, b);
 | 
			
		||||
        a.check_error();
 | 
			
		||||
        return expr(a.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr prefixof(expr const& a, expr const& b) {
 | 
			
		||||
        check_context(a, b);
 | 
			
		||||
        Z3_ast r = Z3_mk_seq_prefix(a.ctx(), a, b);
 | 
			
		||||
        a.check_error();
 | 
			
		||||
        return expr(a.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr indexof(expr const& s, expr const& substr, expr const& offset) {
 | 
			
		||||
        check_context(s, substr); check_context(s, offset);
 | 
			
		||||
        Z3_ast r = Z3_mk_seq_index(s.ctx(), s, substr, offset);
 | 
			
		||||
        s.check_error();
 | 
			
		||||
        return expr(s.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr to_re(expr const& s) {
 | 
			
		||||
        Z3_ast r = Z3_mk_seq_to_re(s.ctx(), s);
 | 
			
		||||
        s.check_error();
 | 
			
		||||
        return expr(s.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr in_re(expr const& s, expr const& re) {
 | 
			
		||||
        check_context(s, re);
 | 
			
		||||
        Z3_ast r = Z3_mk_seq_in_re(s.ctx(), s, re);
 | 
			
		||||
        s.check_error();
 | 
			
		||||
        return expr(s.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr plus(expr const& re) {
 | 
			
		||||
        Z3_ast r = Z3_mk_re_plus(re.ctx(), re);
 | 
			
		||||
        re.check_error();
 | 
			
		||||
        return expr(re.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr option(expr const& re) {
 | 
			
		||||
        Z3_ast r = Z3_mk_re_option(re.ctx(), re);
 | 
			
		||||
        re.check_error();
 | 
			
		||||
        return expr(re.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr star(expr const& re) {
 | 
			
		||||
        Z3_ast r = Z3_mk_re_star(re.ctx(), re);
 | 
			
		||||
        re.check_error();
 | 
			
		||||
        return expr(re.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    inline expr interpolant(expr const& a) {
 | 
			
		||||
        return expr(a.ctx(), Z3_mk_interpolant(a.ctx(), a));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -125,6 +125,7 @@ namespace Microsoft.Z3
 | 
			
		|||
        private BoolSort m_boolSort = null;
 | 
			
		||||
        private IntSort m_intSort = null;
 | 
			
		||||
        private RealSort m_realSort = null;
 | 
			
		||||
	private SeqSort m_stringSort = null;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Retrieves the Boolean sort of the context.
 | 
			
		||||
| 
						 | 
				
			
			@ -163,6 +164,20 @@ namespace Microsoft.Z3
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Retrieves the String sort of the context.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SeqSort StringSort
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Contract.Ensures(Contract.Result<SeqSort>() != null);
 | 
			
		||||
                if (m_stringSort == null) m_stringSort = new SeqSort(this, Native.Z3_mk_string_sort(nCtx));
 | 
			
		||||
                return m_stringSort;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a new Boolean sort.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -223,6 +238,27 @@ namespace Microsoft.Z3
 | 
			
		|||
            return new BitVecSort(this, Native.Z3_mk_bv_sort(nCtx, size));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a new sequence sort.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SeqSort MkSeqSort(Sort s)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<SeqSort>() != null);
 | 
			
		||||
            return new SeqSort(this, Native.Z3_mk_seq_sort(nCtx, s.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a new regular expression sort.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReSort MkReSort(SeqSort s)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<ReSort>() != null);
 | 
			
		||||
            return new ReSort(this, Native.Z3_mk_re_sort(nCtx, s.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a new array sort.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -2286,6 +2322,230 @@ namespace Microsoft.Z3
 | 
			
		|||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Sequence, string and regular expresions
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create the empty sequence.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SeqExpr MkEmptySeq(Sort s) 
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<SeqExpr>() != null);
 | 
			
		||||
            return new SeqExpr(this, Native.Z3_mk_seq_empty(nCtx, s.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create the singleton sequence.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SeqExpr MkUnit(Expr elem) 
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(elem != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<SeqExpr>() != null);
 | 
			
		||||
            return new SeqExpr(this, Native.Z3_mk_seq_unit(nCtx, elem.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a string constant.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SeqExpr MkString(string s) 
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<SeqExpr>() != null);
 | 
			
		||||
            return new SeqExpr(this, Native.Z3_mk_string(nCtx, s));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Concatentate sequences.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SeqExpr MkConcat(params SeqExpr[] t)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(t != null);
 | 
			
		||||
            Contract.Requires(Contract.ForAll(t, a => a != null));
 | 
			
		||||
            Contract.Ensures(Contract.Result<SeqExpr>() != null);
 | 
			
		||||
 | 
			
		||||
            CheckContextMatch(t);
 | 
			
		||||
            return new SeqExpr(this, Native.Z3_mk_seq_concat(nCtx, (uint)t.Length, AST.ArrayToNative(t)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Retrieve the length of a given sequence.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IntExpr MkLength(SeqExpr s)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<IntExpr>() != null);
 | 
			
		||||
            return (IntExpr) Expr.Create(this, Native.Z3_mk_seq_length(nCtx, s.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Check for sequence prefix.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public BoolExpr MkPrefixOf(SeqExpr s1, SeqExpr s2) 
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s1 != null);
 | 
			
		||||
            Contract.Requires(s2 != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<BoolExpr>() != null);
 | 
			
		||||
            CheckContextMatch(s1, s2);
 | 
			
		||||
            return new BoolExpr(this, Native.Z3_mk_seq_prefix(nCtx, s1.NativeObject, s2.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Check for sequence suffix.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public BoolExpr MkSuffixOf(SeqExpr s1, SeqExpr s2) 
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s1 != null);
 | 
			
		||||
            Contract.Requires(s2 != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<BoolExpr>() != null);
 | 
			
		||||
            CheckContextMatch(s1, s2);
 | 
			
		||||
            return new BoolExpr(this, Native.Z3_mk_seq_suffix(nCtx, s1.NativeObject, s2.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Check for sequence containment of s2 in s1.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public BoolExpr MkContains(SeqExpr s1, SeqExpr s2) 
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s1 != null);
 | 
			
		||||
            Contract.Requires(s2 != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<BoolExpr>() != null);
 | 
			
		||||
            CheckContextMatch(s1, s2);
 | 
			
		||||
            return new BoolExpr(this, Native.Z3_mk_seq_contains(nCtx, s1.NativeObject, s2.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Retrieve sequence of length one at index.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SeqExpr MkAt(SeqExpr s, IntExpr index)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Requires(index != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<SeqExpr>() != null);
 | 
			
		||||
            CheckContextMatch(s, index);
 | 
			
		||||
            return new SeqExpr(this, Native.Z3_mk_seq_at(nCtx, s.NativeObject, index.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Extract subsequence.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SeqExpr MkExtract(SeqExpr s, IntExpr offset, IntExpr length)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Requires(offset != null);
 | 
			
		||||
            Contract.Requires(length != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<SeqExpr>() != null);
 | 
			
		||||
            CheckContextMatch(s, offset, length);
 | 
			
		||||
            return new SeqExpr(this, Native.Z3_mk_seq_extract(nCtx, s.NativeObject, offset.NativeObject, length.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Extract index of sub-string starting at offset.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IntExpr MkIndexOf(SeqExpr s, SeqExpr substr, ArithExpr offset)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Requires(offset != null);
 | 
			
		||||
            Contract.Requires(substr != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<IntExpr>() != null);
 | 
			
		||||
            CheckContextMatch(s, substr, offset);
 | 
			
		||||
            return new IntExpr(this, Native.Z3_mk_seq_index(nCtx, s.NativeObject, substr.NativeObject, offset.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Replace the first occurrence of src by dst in s.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SeqExpr MkReplace(SeqExpr s, SeqExpr src, SeqExpr dst)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Requires(src != null);
 | 
			
		||||
            Contract.Requires(dst != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<SeqExpr>() != null);
 | 
			
		||||
            CheckContextMatch(s, src, dst);
 | 
			
		||||
            return new SeqExpr(this, Native.Z3_mk_seq_replace(nCtx, s.NativeObject, src.NativeObject, dst.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Convert a regular expression that accepts sequence s.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReExpr MkToRe(SeqExpr s) 
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<ReExpr>() != null);
 | 
			
		||||
            return new ReExpr(this, Native.Z3_mk_seq_to_re(nCtx, s.NativeObject));            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Check for regular expression membership.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public BoolExpr MkInRe(SeqExpr s, ReExpr re)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(s != null);
 | 
			
		||||
            Contract.Requires(re != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<BoolExpr>() != null);
 | 
			
		||||
            CheckContextMatch(s, re);
 | 
			
		||||
            return new BoolExpr(this, Native.Z3_mk_seq_in_re(nCtx, s.NativeObject, re.NativeObject));            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Take the Kleene star of a regular expression.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReExpr MkStar(ReExpr re)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(re != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<ReExpr>() != null);
 | 
			
		||||
            return new ReExpr(this, Native.Z3_mk_re_star(nCtx, re.NativeObject));            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Take the Kleene plus of a regular expression.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReExpr MPlus(ReExpr re)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(re != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<ReExpr>() != null);
 | 
			
		||||
            return new ReExpr(this, Native.Z3_mk_re_plus(nCtx, re.NativeObject));            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create the optional regular expression.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReExpr MOption(ReExpr re)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(re != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<ReExpr>() != null);
 | 
			
		||||
            return new ReExpr(this, Native.Z3_mk_re_option(nCtx, re.NativeObject));            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create the concatenation of regular languages.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReExpr MkConcat(params ReExpr[] t)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(t != null);
 | 
			
		||||
            Contract.Requires(Contract.ForAll(t, a => a != null));
 | 
			
		||||
            Contract.Ensures(Contract.Result<ReExpr>() != null);
 | 
			
		||||
 | 
			
		||||
            CheckContextMatch(t);
 | 
			
		||||
            return new ReExpr(this, Native.Z3_mk_re_concat(nCtx, (uint)t.Length, AST.ArrayToNative(t)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create the union of regular languages.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ReExpr MkUnion(params ReExpr[] t)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(t != null);
 | 
			
		||||
            Contract.Requires(Contract.ForAll(t, a => a != null));
 | 
			
		||||
            Contract.Ensures(Contract.Result<ReExpr>() != null);
 | 
			
		||||
 | 
			
		||||
            CheckContextMatch(t);
 | 
			
		||||
            return new ReExpr(this, Native.Z3_mk_re_union(nCtx, (uint)t.Length, AST.ArrayToNative(t)));
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Pseudo-Boolean constraints
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -4448,6 +4708,26 @@ namespace Microsoft.Z3
 | 
			
		|||
                throw new Z3Exception("Context mismatch");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Pure]
 | 
			
		||||
        internal void CheckContextMatch(Z3Object other1, Z3Object other2)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(other1 != null);
 | 
			
		||||
            Contract.Requires(other2 != null);
 | 
			
		||||
            CheckContextMatch(other1);
 | 
			
		||||
            CheckContextMatch(other2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Pure]
 | 
			
		||||
        internal void CheckContextMatch(Z3Object other1, Z3Object other2, Z3Object other3)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(other1 != null);
 | 
			
		||||
            Contract.Requires(other2 != null);
 | 
			
		||||
            Contract.Requires(other3 != null);
 | 
			
		||||
            CheckContextMatch(other1);
 | 
			
		||||
            CheckContextMatch(other2);
 | 
			
		||||
            CheckContextMatch(other3);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Pure]
 | 
			
		||||
        internal void CheckContextMatch(Z3Object[] arr)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -4628,6 +4908,7 @@ namespace Microsoft.Z3
 | 
			
		|||
            m_boolSort = null;
 | 
			
		||||
            m_intSort = null;
 | 
			
		||||
            m_realSort = null;
 | 
			
		||||
            m_stringSort = null;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1826,6 +1826,8 @@ namespace Microsoft.Z3
 | 
			
		|||
                case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPExpr(ctx, obj);
 | 
			
		||||
                case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMExpr(ctx, obj);
 | 
			
		||||
                case Z3_sort_kind.Z3_FINITE_DOMAIN_SORT: return new FiniteDomainExpr(ctx, obj);
 | 
			
		||||
                case Z3_sort_kind.Z3_RE_SORT: return new ReExpr(ctx, obj);
 | 
			
		||||
                case Z3_sort_kind.Z3_SEQ_SORT: return new SeqExpr(ctx, obj);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new Expr(ctx, obj);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -374,7 +374,11 @@
 | 
			
		|||
    <Compile Include="RatNum.cs" />
 | 
			
		||||
    <Compile Include="RealExpr.cs" />
 | 
			
		||||
    <Compile Include="RealSort.cs" />
 | 
			
		||||
    <Compile Include="ReExpr.cs" />
 | 
			
		||||
    <Compile Include="RelationSort.cs" />
 | 
			
		||||
    <Compile Include="ReSort.cs" />
 | 
			
		||||
    <Compile Include="SeqExpr.cs" />
 | 
			
		||||
    <Compile Include="SeqSort.cs" />
 | 
			
		||||
    <Compile Include="SetSort.cs" />
 | 
			
		||||
    <Compile Include="Statistics.cs" />
 | 
			
		||||
    <Compile Include="Status.cs" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										42
									
								
								src/api/dotnet/ReExpr.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/api/dotnet/ReExpr.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (<c>) 2016 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    ReExpr.cs
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Z3 Managed API: Regular Expressions
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Christoph Wintersteiger (cwinter) 2012-11-23
 | 
			
		||||
 | 
			
		||||
Notes:
 | 
			
		||||
    
 | 
			
		||||
--*/
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using System.Diagnostics.Contracts;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.Z3
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Regular expression expressions
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class ReExpr : Expr
 | 
			
		||||
    {
 | 
			
		||||
        #region Internal
 | 
			
		||||
        /// <summary> Constructor for ReExpr </summary>
 | 
			
		||||
        internal ReExpr(Context ctx, IntPtr obj)
 | 
			
		||||
            : base(ctx, obj)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(ctx != null);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								src/api/dotnet/ReSort.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/api/dotnet/ReSort.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2016 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    ReSort.cs
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Z3 Managed API: Regular expression Sorts
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Christoph Wintersteiger (cwinter) 2012-11-23
 | 
			
		||||
 | 
			
		||||
Notes:
 | 
			
		||||
    
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Diagnostics.Contracts;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.Z3
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///  A regular expression sort
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class ReSort : Sort
 | 
			
		||||
    {
 | 
			
		||||
        #region Internal
 | 
			
		||||
        internal ReSort(Context ctx, IntPtr obj)
 | 
			
		||||
            : base(ctx, obj)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(ctx != null);
 | 
			
		||||
        }
 | 
			
		||||
        internal ReSort(Context ctx)
 | 
			
		||||
            : base(ctx, Native.Z3_mk_int_sort(ctx.nCtx))
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(ctx != null);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								src/api/dotnet/SeqExpr.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/api/dotnet/SeqExpr.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (<c>) 2016 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    SeqExpr.cs
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Z3 Managed API: Sequence Expressions
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Christoph Wintersteiger (cwinter) 2012-11-23
 | 
			
		||||
 | 
			
		||||
Notes:
 | 
			
		||||
    
 | 
			
		||||
--*/
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using System.Diagnostics.Contracts;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.Z3
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Sequence expressions
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class SeqExpr : Expr
 | 
			
		||||
    {
 | 
			
		||||
        #region Internal
 | 
			
		||||
        /// <summary> Constructor for SeqExpr </summary>
 | 
			
		||||
        internal SeqExpr(Context ctx, IntPtr obj)
 | 
			
		||||
            : base(ctx, obj)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(ctx != null);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								src/api/dotnet/SeqSort.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/api/dotnet/SeqSort.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2016 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    SeqSort.cs
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Z3 Managed API: Sequence Sorts
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Christoph Wintersteiger (cwinter) 2012-11-23
 | 
			
		||||
 | 
			
		||||
Notes:
 | 
			
		||||
    
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Diagnostics.Contracts;
 | 
			
		||||
 | 
			
		||||
namespace Microsoft.Z3
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    ///  A Sequence sort
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class SeqSort : Sort
 | 
			
		||||
    {
 | 
			
		||||
        #region Internal
 | 
			
		||||
        internal SeqSort(Context ctx, IntPtr obj)
 | 
			
		||||
            : base(ctx, obj)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(ctx != null);
 | 
			
		||||
        }
 | 
			
		||||
        internal SeqSort(Context ctx)
 | 
			
		||||
            : base(ctx, Native.Z3_mk_int_sort(ctx.nCtx))
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(ctx != null);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -147,6 +147,8 @@ namespace Microsoft.Z3
 | 
			
		|||
                case Z3_sort_kind.Z3_RELATION_SORT: return new RelationSort(ctx, obj);
 | 
			
		||||
                case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPSort(ctx, obj);
 | 
			
		||||
                case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMSort(ctx, obj);
 | 
			
		||||
                case Z3_sort_kind.Z3_SEQ_SORT: return new SeqSort(ctx, obj);
 | 
			
		||||
                case Z3_sort_kind.Z3_RE_SORT: return new ReSort(ctx, obj);
 | 
			
		||||
                default:
 | 
			
		||||
                    throw new Z3Exception("Unknown sort kind");
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,6 +103,7 @@ public class Context extends IDisposable
 | 
			
		|||
    private BoolSort m_boolSort = null;
 | 
			
		||||
    private IntSort m_intSort = null;
 | 
			
		||||
    private RealSort m_realSort = null;
 | 
			
		||||
    private SeqSort m_stringSort = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieves the Boolean sort of the context.
 | 
			
		||||
| 
						 | 
				
			
			@ -142,6 +143,16 @@ public class Context extends IDisposable
 | 
			
		|||
        return new BoolSort(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieves the Integer sort of the context.
 | 
			
		||||
     **/
 | 
			
		||||
    public SeqSort getStringSort()
 | 
			
		||||
    {
 | 
			
		||||
        if (m_stringSort == null)
 | 
			
		||||
            m_stringSort = mkStringSort();
 | 
			
		||||
        return m_stringSort;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new uninterpreted sort.
 | 
			
		||||
     **/
 | 
			
		||||
| 
						 | 
				
			
			@ -193,6 +204,31 @@ public class Context extends IDisposable
 | 
			
		|||
        return new ArraySort(this, domain, range);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new string sort
 | 
			
		||||
     **/
 | 
			
		||||
    public SeqSort mkStringSort()
 | 
			
		||||
    {
 | 
			
		||||
        return new SeqSort(this, Native.mkStringSort(nCtx()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new sequence sort
 | 
			
		||||
     **/
 | 
			
		||||
    public SeqSort mkSeqSort(Sort s)
 | 
			
		||||
    {
 | 
			
		||||
        return new SeqSort(this, Native.mkSeqSort(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new regular expression sort
 | 
			
		||||
     **/
 | 
			
		||||
    public ReSort mkReSort(Sort s)
 | 
			
		||||
    {
 | 
			
		||||
        return new ReSort(this, Native.mkReSort(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new tuple sort.
 | 
			
		||||
     **/
 | 
			
		||||
| 
						 | 
				
			
			@ -1849,6 +1885,184 @@ public class Context extends IDisposable
 | 
			
		|||
                        arg2.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sequences, Strings and regular expressions.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create the empty sequence.
 | 
			
		||||
    */
 | 
			
		||||
    public SeqExpr MkEmptySeq(Sort s) 
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s);
 | 
			
		||||
	return new SeqExpr(this, Native.mkSeqEmpty(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create the singleton sequence.
 | 
			
		||||
     */
 | 
			
		||||
    public SeqExpr MkUnit(Expr elem) 
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(elem);
 | 
			
		||||
	return new SeqExpr(this, Native.mkSeqUnit(nCtx(), elem.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a string constant.
 | 
			
		||||
     */
 | 
			
		||||
    public SeqExpr MkString(String s) 
 | 
			
		||||
    {
 | 
			
		||||
	return new SeqExpr(this, Native.mkString(nCtx(), s));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Concatentate sequences.
 | 
			
		||||
     */
 | 
			
		||||
    public SeqExpr MkConcat(SeqExpr... t)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(t);
 | 
			
		||||
	return new SeqExpr(this, Native.mkSeqConcat(nCtx(), (int)t.length, AST.arrayToNative(t)));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieve the length of a given sequence.
 | 
			
		||||
     */
 | 
			
		||||
    public IntExpr MkLength(SeqExpr s)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s);
 | 
			
		||||
	return (IntExpr) Expr.create(this, Native.mkSeqLength(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Check for sequence prefix.
 | 
			
		||||
     */
 | 
			
		||||
    public BoolExpr MkPrefixOf(SeqExpr s1, SeqExpr s2) 
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s1, s2);
 | 
			
		||||
	return new BoolExpr(this, Native.mkSeqPrefix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Check for sequence suffix.
 | 
			
		||||
     */
 | 
			
		||||
    public BoolExpr MkSuffixOf(SeqExpr s1, SeqExpr s2) 
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s1, s2);
 | 
			
		||||
	return new BoolExpr(this, Native.mkSeqSuffix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Check for sequence containment of s2 in s1.
 | 
			
		||||
     */
 | 
			
		||||
    public BoolExpr MkContains(SeqExpr s1, SeqExpr s2) 
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s1, s2);
 | 
			
		||||
	return new BoolExpr(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieve sequence of length one at index.
 | 
			
		||||
     */
 | 
			
		||||
    public SeqExpr MkAt(SeqExpr s, IntExpr index)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s, index);
 | 
			
		||||
	return new SeqExpr(this, Native.mkSeqAt(nCtx(), s.getNativeObject(), index.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Extract subsequence.
 | 
			
		||||
     */
 | 
			
		||||
    public SeqExpr MkExtract(SeqExpr s, IntExpr offset, IntExpr length)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s, offset, length);
 | 
			
		||||
	return new SeqExpr(this, Native.mkSeqExtract(nCtx(), s.getNativeObject(), offset.getNativeObject(), length.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Extract index of sub-string starting at offset.
 | 
			
		||||
     */
 | 
			
		||||
    public IntExpr MkIndexOf(SeqExpr s, SeqExpr substr, ArithExpr offset)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s, substr, offset);
 | 
			
		||||
	return new IntExpr(this, Native.mkSeqIndex(nCtx(), s.getNativeObject(), substr.getNativeObject(), offset.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Replace the first occurrence of src by dst in s.
 | 
			
		||||
     */
 | 
			
		||||
    public SeqExpr MkReplace(SeqExpr s, SeqExpr src, SeqExpr dst)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s, src, dst);
 | 
			
		||||
	return new SeqExpr(this, Native.mkSeqReplace(nCtx(), s.getNativeObject(), src.getNativeObject(), dst.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Convert a regular expression that accepts sequence s.
 | 
			
		||||
     */
 | 
			
		||||
    public ReExpr MkToRe(SeqExpr s) 
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s);
 | 
			
		||||
	return new ReExpr(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));            
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Check for regular expression membership.
 | 
			
		||||
     */
 | 
			
		||||
    public BoolExpr MkInRe(SeqExpr s, ReExpr re)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(s, re);
 | 
			
		||||
	return new BoolExpr(this, Native.mkSeqInRe(nCtx(), s.getNativeObject(), re.getNativeObject()));            
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Take the Kleene star of a regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public ReExpr MkStar(ReExpr re)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(re);
 | 
			
		||||
	return new ReExpr(this, Native.mkReStar(nCtx(), re.getNativeObject()));            
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Take the Kleene plus of a regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public ReExpr MPlus(ReExpr re)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(re);
 | 
			
		||||
	return new ReExpr(this, Native.mkRePlus(nCtx(), re.getNativeObject()));            
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Create the optional regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public ReExpr MOption(ReExpr re)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(re);
 | 
			
		||||
	return new ReExpr(this, Native.mkReOption(nCtx(), re.getNativeObject()));            
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Create the concatenation of regular languages.
 | 
			
		||||
     */
 | 
			
		||||
    public ReExpr MkConcat(ReExpr... t)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(t);
 | 
			
		||||
	return new ReExpr(this, Native.mkReConcat(nCtx(), (int)t.length, AST.arrayToNative(t)));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Create the union of regular languages.
 | 
			
		||||
     */
 | 
			
		||||
    public ReExpr MkUnion(ReExpr... t)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(t);
 | 
			
		||||
	return new ReExpr(this, Native.mkReUnion(nCtx(), (int)t.length, AST.arrayToNative(t)));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a Term of a given sort. 
 | 
			
		||||
     * @param v A string representing the term value in decimal notation. If the given sort is a real, then the
 | 
			
		||||
| 
						 | 
				
			
			@ -3683,6 +3897,19 @@ public class Context extends IDisposable
 | 
			
		|||
            throw new Z3Exception("Context mismatch");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void checkContextMatch(Z3Object other1, Z3Object other2)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(other1);
 | 
			
		||||
	checkContextMatch(other2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void checkContextMatch(Z3Object other1, Z3Object other2, Z3Object other3)
 | 
			
		||||
    {
 | 
			
		||||
	checkContextMatch(other1);
 | 
			
		||||
	checkContextMatch(other2);
 | 
			
		||||
	checkContextMatch(other3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void checkContextMatch(Z3Object[] arr)
 | 
			
		||||
    {
 | 
			
		||||
        if (arr != null)
 | 
			
		||||
| 
						 | 
				
			
			@ -3822,6 +4049,7 @@ public class Context extends IDisposable
 | 
			
		|||
        m_Params_DRQ.clear(this);
 | 
			
		||||
        m_Probe_DRQ.clear(this);
 | 
			
		||||
        m_Solver_DRQ.clear(this);
 | 
			
		||||
	m_Optimize_DRQ.clear(this);
 | 
			
		||||
        m_Statistics_DRQ.clear(this);
 | 
			
		||||
        m_Tactic_DRQ.clear(this);
 | 
			
		||||
        m_Fixedpoint_DRQ.clear(this);
 | 
			
		||||
| 
						 | 
				
			
			@ -3829,6 +4057,7 @@ public class Context extends IDisposable
 | 
			
		|||
        m_boolSort = null;
 | 
			
		||||
        m_intSort = null;
 | 
			
		||||
        m_realSort = null;
 | 
			
		||||
        m_stringSort = null;
 | 
			
		||||
 | 
			
		||||
        synchronized (creation_lock) {
 | 
			
		||||
            if (m_refCount.get() == 0 && m_ctx != 0) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2186,6 +2186,10 @@ public class Expr extends AST
 | 
			
		|||
            return new FPRMExpr(ctx, obj);
 | 
			
		||||
        case Z3_FINITE_DOMAIN_SORT:
 | 
			
		||||
            return new FiniteDomainExpr(ctx, obj);
 | 
			
		||||
	case Z3_SEQ_SORT:
 | 
			
		||||
	    return new SeqExpr(ctx, obj);
 | 
			
		||||
	case Z3_RE_SORT:
 | 
			
		||||
	    return new ReExpr(ctx, obj);
 | 
			
		||||
        default: ;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								src/api/java/ReExpr.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/api/java/ReExpr.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
/**
 | 
			
		||||
Copyright (c) 2012-2016 Microsoft Corporation
 | 
			
		||||
   
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    ReExpr.java
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    @author Christoph Wintersteiger (cwinter) 2012-03-15
 | 
			
		||||
 | 
			
		||||
Notes:
 | 
			
		||||
    
 | 
			
		||||
**/ 
 | 
			
		||||
 | 
			
		||||
package com.microsoft.z3;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Re expressions
 | 
			
		||||
 **/
 | 
			
		||||
public class ReExpr extends Expr
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for ReExpr
 | 
			
		||||
     * @throws Z3Exception on error
 | 
			
		||||
     **/
 | 
			
		||||
    ReExpr(Context ctx, long obj)
 | 
			
		||||
    {
 | 
			
		||||
        super(ctx, obj);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								src/api/java/ReSort.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/api/java/ReSort.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/**
 | 
			
		||||
Copyright (c) 2012-2014 Microsoft Corporation
 | 
			
		||||
   
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    ReSort.java
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    @author Christoph Wintersteiger (cwinter) 2012-03-15
 | 
			
		||||
 | 
			
		||||
Notes:
 | 
			
		||||
    
 | 
			
		||||
**/ 
 | 
			
		||||
 | 
			
		||||
package com.microsoft.z3;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A Regular expression sort
 | 
			
		||||
 **/
 | 
			
		||||
public class ReSort extends Sort
 | 
			
		||||
{
 | 
			
		||||
    ReSort(Context ctx, long obj)
 | 
			
		||||
    {
 | 
			
		||||
        super(ctx, obj);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								src/api/java/SeqExpr.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/api/java/SeqExpr.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
/**
 | 
			
		||||
Copyright (c) 2012-2016 Microsoft Corporation
 | 
			
		||||
   
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    SeqExpr.java
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    @author Christoph Wintersteiger (cwinter) 2012-03-15
 | 
			
		||||
 | 
			
		||||
Notes:
 | 
			
		||||
    
 | 
			
		||||
**/ 
 | 
			
		||||
 | 
			
		||||
package com.microsoft.z3;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Seq expressions
 | 
			
		||||
 **/
 | 
			
		||||
public class SeqExpr extends Expr
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for SeqExpr
 | 
			
		||||
     * @throws Z3Exception on error
 | 
			
		||||
     **/
 | 
			
		||||
    SeqExpr(Context ctx, long obj)
 | 
			
		||||
    {
 | 
			
		||||
        super(ctx, obj);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								src/api/java/SeqSort.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/api/java/SeqSort.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/**
 | 
			
		||||
Copyright (c) 2012-2014 Microsoft Corporation
 | 
			
		||||
   
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    SeqSort.java
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    @author Christoph Wintersteiger (cwinter) 2012-03-15
 | 
			
		||||
 | 
			
		||||
Notes:
 | 
			
		||||
    
 | 
			
		||||
**/ 
 | 
			
		||||
 | 
			
		||||
package com.microsoft.z3;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A Sequence sort
 | 
			
		||||
 **/
 | 
			
		||||
public class SeqSort extends Sort
 | 
			
		||||
{
 | 
			
		||||
    SeqSort(Context ctx, long obj)
 | 
			
		||||
    {
 | 
			
		||||
        super(ctx, obj);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -141,6 +141,10 @@ public class Sort extends AST
 | 
			
		|||
            return new FPSort(ctx, obj);
 | 
			
		||||
        case Z3_ROUNDING_MODE_SORT:
 | 
			
		||||
            return new FPRMSort(ctx, obj);
 | 
			
		||||
	case Z3_SEQ_SORT:
 | 
			
		||||
	    return new SeqSort(ctx, obj);
 | 
			
		||||
	case Z3_RE_SORT:
 | 
			
		||||
	    return new ReSort(ctx, obj);
 | 
			
		||||
        default:
 | 
			
		||||
            throw new Z3Exception("Unknown sort kind");
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										766
									
								
								src/api/ml/z3.ml
									
										
									
									
									
								
							
							
						
						
									
										766
									
								
								src/api/ml/z3.ml
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -68,8 +68,8 @@ _z3_op_to_fpa_normal_str = {
 | 
			
		|||
    Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN : 'RoundNearestTiesToEven()', Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY : 'RoundNearestTiesToAway()',
 | 
			
		||||
    Z3_OP_FPA_RM_TOWARD_POSITIVE : 'RoundTowardPositive()', Z3_OP_FPA_RM_TOWARD_NEGATIVE : 'RoundTowardNegative()',
 | 
			
		||||
    Z3_OP_FPA_RM_TOWARD_ZERO : 'RoundTowardZero()',
 | 
			
		||||
    Z3_OP_FPA_PLUS_INF : '+oo', Z3_OP_FPA_MINUS_INF : '-oo',
 | 
			
		||||
    Z3_OP_FPA_NAN : 'NaN', Z3_OP_FPA_PLUS_ZERO : 'PZero', Z3_OP_FPA_MINUS_ZERO : 'NZero',
 | 
			
		||||
    Z3_OP_FPA_PLUS_INF : 'fpPlusInfinity', Z3_OP_FPA_MINUS_INF : 'fpMinusInfinity',
 | 
			
		||||
    Z3_OP_FPA_NAN : 'fpNaN', Z3_OP_FPA_PLUS_ZERO : 'fpPZero', Z3_OP_FPA_MINUS_ZERO : 'fpNZero',
 | 
			
		||||
    Z3_OP_FPA_ADD : 'fpAdd', Z3_OP_FPA_SUB : 'fpSub', Z3_OP_FPA_NEG : 'fpNeg', Z3_OP_FPA_MUL : 'fpMul',
 | 
			
		||||
    Z3_OP_FPA_DIV : 'fpDiv', Z3_OP_FPA_REM : 'fpRem', Z3_OP_FPA_ABS : 'fpAbs',
 | 
			
		||||
    Z3_OP_FPA_MIN : 'fpMin', Z3_OP_FPA_MAX : 'fpMax',
 | 
			
		||||
| 
						 | 
				
			
			@ -570,6 +570,9 @@ class Formatter:
 | 
			
		|||
    def pp_algebraic(self, a):
 | 
			
		||||
        return to_format(a.as_decimal(self.precision))
 | 
			
		||||
 | 
			
		||||
    def pp_string(self, a):
 | 
			
		||||
        return to_format(a.as_string())
 | 
			
		||||
 | 
			
		||||
    def pp_bv(self, a):
 | 
			
		||||
        return to_format(a.as_string())
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -586,13 +589,23 @@ class Formatter:
 | 
			
		|||
    def pp_fp_value(self, a):
 | 
			
		||||
        z3._z3_assert(isinstance(a, z3.FPNumRef), 'type mismatch')
 | 
			
		||||
        if not self.fpa_pretty:
 | 
			
		||||
            r = []
 | 
			
		||||
            if (a.isNaN()):
 | 
			
		||||
                return to_format('NaN')
 | 
			
		||||
                r.append(to_format(_z3_op_to_fpa_normal_str[Z3_OP_FPA_NAN]))
 | 
			
		||||
                r.append(to_format('('))
 | 
			
		||||
                r.append(to_format(a.sort()))
 | 
			
		||||
                r.append(to_format(')'))
 | 
			
		||||
                return compose(r)
 | 
			
		||||
            elif (a.isInf()):
 | 
			
		||||
                if (a.isNegative()):
 | 
			
		||||
                    return to_format('-oo')
 | 
			
		||||
                    r.append(to_format(_z3_op_to_fpa_normal_str[Z3_OP_FPA_MINUS_INF]))
 | 
			
		||||
                else:
 | 
			
		||||
                    return to_format('+oo')
 | 
			
		||||
                    r.append(to_format(_z3_op_to_fpa_normal_str[Z3_OP_FPA_PLUS_INF]))                
 | 
			
		||||
                r.append(to_format('('))
 | 
			
		||||
                r.append(to_format(a.sort()))
 | 
			
		||||
                r.append(to_format(')'))
 | 
			
		||||
                return compose(r)
 | 
			
		||||
 | 
			
		||||
            elif (a.isZero()):
 | 
			
		||||
                if (a.isNegative()):
 | 
			
		||||
                    return to_format('-zero')
 | 
			
		||||
| 
						 | 
				
			
			@ -875,6 +888,8 @@ class Formatter:
 | 
			
		|||
            return self.pp_fp_value(a)
 | 
			
		||||
        elif z3.is_fp(a):
 | 
			
		||||
            return self.pp_fp(a, d, xs)
 | 
			
		||||
        elif z3.is_string_value(a):
 | 
			
		||||
            return self.pp_string(a)
 | 
			
		||||
        elif z3.is_const(a):
 | 
			
		||||
            return self.pp_const(a)
 | 
			
		||||
        else:
 | 
			
		||||
| 
						 | 
				
			
			@ -1190,6 +1205,10 @@ def set_fpa_pretty(flag=True):
 | 
			
		|||
 | 
			
		||||
set_fpa_pretty(True)
 | 
			
		||||
 | 
			
		||||
def get_fpa_pretty():
 | 
			
		||||
    global Formatter
 | 
			
		||||
    return _Formatter.fpa_pretty
 | 
			
		||||
 | 
			
		||||
def in_html_mode():
 | 
			
		||||
    return isinstance(_Formatter, HTMLFormatter)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										242
									
								
								src/api/z3_api.h
									
										
									
									
									
								
							
							
						
						
									
										242
									
								
								src/api/z3_api.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -161,6 +161,8 @@ typedef enum
 | 
			
		|||
    Z3_FINITE_DOMAIN_SORT,
 | 
			
		||||
    Z3_FLOATING_POINT_SORT,
 | 
			
		||||
    Z3_ROUNDING_MODE_SORT,
 | 
			
		||||
    Z3_SEQ_SORT,
 | 
			
		||||
    Z3_RE_SORT,
 | 
			
		||||
    Z3_UNKNOWN_SORT = 1000
 | 
			
		||||
} Z3_sort_kind;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1098,7 +1100,7 @@ typedef enum {
 | 
			
		|||
    Z3_OP_PR_TH_LEMMA,
 | 
			
		||||
    Z3_OP_PR_HYPER_RESOLVE,
 | 
			
		||||
 | 
			
		||||
    // Sequences
 | 
			
		||||
    // Relational algebra
 | 
			
		||||
    Z3_OP_RA_STORE = 0x600,
 | 
			
		||||
    Z3_OP_RA_EMPTY,
 | 
			
		||||
    Z3_OP_RA_IS_EMPTY,
 | 
			
		||||
| 
						 | 
				
			
			@ -1115,6 +1117,28 @@ typedef enum {
 | 
			
		|||
    Z3_OP_FD_CONSTANT,
 | 
			
		||||
    Z3_OP_FD_LT,
 | 
			
		||||
 | 
			
		||||
    // Sequences
 | 
			
		||||
    Z3_OP_SEQ_UNIT,
 | 
			
		||||
    Z3_OP_SEQ_EMPTY,
 | 
			
		||||
    Z3_OP_SEQ_CONCAT,
 | 
			
		||||
    Z3_OP_SEQ_PREFIX,
 | 
			
		||||
    Z3_OP_SEQ_SUFFIX,
 | 
			
		||||
    Z3_OP_SEQ_CONTAINS,
 | 
			
		||||
    Z3_OP_SEQ_EXTRACT,
 | 
			
		||||
    Z3_OP_SEQ_REPLACE,
 | 
			
		||||
    Z3_OP_SEQ_AT,
 | 
			
		||||
    Z3_OP_SEQ_LENGTH,    
 | 
			
		||||
    Z3_OP_SEQ_INDEX,
 | 
			
		||||
    Z3_OP_SEQ_TO_RE,
 | 
			
		||||
    Z3_OP_SEQ_IN_RE,
 | 
			
		||||
 | 
			
		||||
    // regular expressions
 | 
			
		||||
    Z3_OP_RE_PLUS,
 | 
			
		||||
    Z3_OP_RE_STAR,
 | 
			
		||||
    Z3_OP_RE_OPTION,
 | 
			
		||||
    Z3_OP_RE_CONCAT,
 | 
			
		||||
    Z3_OP_RE_UNION,
 | 
			
		||||
 | 
			
		||||
    // Auxiliary
 | 
			
		||||
    Z3_OP_LABEL = 0x700,
 | 
			
		||||
    Z3_OP_LABEL_LIT,
 | 
			
		||||
| 
						 | 
				
			
			@ -3093,6 +3117,222 @@ extern "C" {
 | 
			
		|||
 | 
			
		||||
    /*@}*/
 | 
			
		||||
 | 
			
		||||
    /** @name Sequences and regular expressions */
 | 
			
		||||
    /*@{*/
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create a sequence sort out of the sort for the elements.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_sort', SORT, (_in(CONTEXT), _in(SORT)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_sort Z3_API Z3_mk_seq_sort(Z3_context c, Z3_sort s);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Check if \c s is a sequence sort.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_is_seq_sort', BOOL, (_in(CONTEXT), _in(SORT)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_bool Z3_API Z3_is_seq_sort(Z3_context c, Z3_sort s);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create a regular expression sort out of a sequence sort.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_re_sort', SORT, (_in(CONTEXT), _in(SORT)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_sort Z3_API Z3_mk_re_sort(Z3_context c, Z3_sort seq);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Check if \c s is a regular expression sort.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_is_re_sort', BOOL, (_in(CONTEXT), _in(SORT)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_bool Z3_API Z3_is_re_sort(Z3_context c, Z3_sort s);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create a sort for 8 bit strings.
 | 
			
		||||
 | 
			
		||||
       This function creates a sort for ASCII strings.
 | 
			
		||||
       Each character is 8 bits.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_string_sort', SORT ,(_in(CONTEXT), ))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_sort Z3_API Z3_mk_string_sort(Z3_context c);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Check if \c s is a string sort.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_is_string_sort', BOOL, (_in(CONTEXT), _in(SORT)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_bool Z3_API Z3_is_string_sort(Z3_context c, Z3_sort s);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create a string constant out of the string that is passed in
 | 
			
		||||
       def_API('Z3_mk_string' ,AST ,(_in(CONTEXT), _in(STRING)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_string(Z3_context c, Z3_string s);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Determine if \c s is a string constant.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_is_string', BOOL, (_in(CONTEXT), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_bool Z3_API Z3_is_string(Z3_context c, Z3_ast s); 
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Retrieve the string constant stored in \c s.
 | 
			
		||||
       
 | 
			
		||||
       \pre  Z3_is_string(c, s)
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_get_string' ,STRING ,(_in(CONTEXT), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_string Z3_API Z3_get_string(Z3_context c, Z3_ast s);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create an empty sequence of the sequence sort \c seq.
 | 
			
		||||
 | 
			
		||||
       \pre s is a sequence sort.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_empty' ,AST ,(_in(CONTEXT), _in(SORT)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_empty(Z3_context c, Z3_sort seq);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create a unit sequence of \c a.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_unit' ,AST ,(_in(CONTEXT), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_unit(Z3_context c, Z3_ast a);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Concatenate sequences.
 | 
			
		||||
 | 
			
		||||
       \pre n > 0
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_concat' ,AST ,(_in(CONTEXT), _in(UINT), _in_array(1, AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_concat(Z3_context c, unsigned n, Z3_ast const args[]);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Check if \c prefix is a prefix of \c s.
 | 
			
		||||
 | 
			
		||||
       \pre prefix and s are the same sequence sorts.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_prefix' ,AST ,(_in(CONTEXT), _in(AST), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_prefix(Z3_context c, Z3_ast prefix, Z3_ast s);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Check if \c suffix is a suffix of \c s.
 | 
			
		||||
 | 
			
		||||
       \pre \c suffix and \c s are the same sequence sorts.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_suffix' ,AST ,(_in(CONTEXT), _in(AST), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_suffix(Z3_context c, Z3_ast suffix, Z3_ast s);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Check if \c container contains \c containee.
 | 
			
		||||
 | 
			
		||||
       \pre \c container and \c containee are the same sequence sorts.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_contains' ,AST ,(_in(CONTEXT), _in(AST), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_contains(Z3_context c, Z3_ast container, Z3_ast containee);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Extract subsequence starting at \c offset of \c length.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_extract' ,AST ,(_in(CONTEXT), _in(AST), _in(AST), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_extract(Z3_context c, Z3_ast s, Z3_ast offset, Z3_ast length);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Replace the first occurrence of \c src with \c dst in \c s.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_replace' ,AST ,(_in(CONTEXT), _in(AST), _in(AST), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_replace(Z3_context c, Z3_ast s, Z3_ast src, Z3_ast dst);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Retrieve from \s the unit sequence positioned at position \c index.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_at' ,AST ,(_in(CONTEXT), _in(AST), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_at(Z3_context c, Z3_ast s, Z3_ast index);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Return the length of the sequence \c s.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_length' ,AST ,(_in(CONTEXT), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_length(Z3_context c, Z3_ast s);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Return index of first occurrence of \c substr in \c s starting from offset \c offset.
 | 
			
		||||
       If \c s does not contain \c substr, then the value is -1, if \c offset is the length of \c s, then the value is -1 as well.
 | 
			
		||||
       The function is under-specified if \c offset is negative or larger than the length of \c s.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_index' ,AST ,(_in(CONTEXT), _in(AST), _in(AST), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_index(Z3_context c, Z3_ast s, Z3_ast substr, Z3_ast offset);
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create a regular expression that accepts the sequence \c seq.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_to_re' ,AST ,(_in(CONTEXT), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_to_re(Z3_context c, Z3_ast seq);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Check if \c seq is in the language generated by the regular expression \c re.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_seq_in_re' ,AST ,(_in(CONTEXT), _in(AST), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_seq_in_re(Z3_context c, Z3_ast seq, Z3_ast re);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create the regular language \c re+.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_re_plus' ,AST ,(_in(CONTEXT), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_re_plus(Z3_context c, Z3_ast re);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create the regular language \c re*.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_re_star' ,AST ,(_in(CONTEXT), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_re_star(Z3_context c, Z3_ast re);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create the regular language \c [re].
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_re_option' ,AST ,(_in(CONTEXT), _in(AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_re_option(Z3_context c, Z3_ast re);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create the union of the regular languages.
 | 
			
		||||
 | 
			
		||||
       \pre n > 0
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_re_union' ,AST ,(_in(CONTEXT), _in(UINT), _in_array(1, AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_re_union(Z3_context c, unsigned n, Z3_ast const args[]);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create the concatenation of the regular languages.
 | 
			
		||||
 | 
			
		||||
       \pre n > 0
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_re_concat' ,AST ,(_in(CONTEXT), _in(UINT), _in_array(1, AST)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_re_concat(Z3_context c, unsigned n, Z3_ast const args[]);
 | 
			
		||||
 | 
			
		||||
    /*@}*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /** @name Quantifiers */
 | 
			
		||||
    /*@{*/
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,7 @@ struct z3_replayer::imp {
 | 
			
		|||
    size_t                   m_ptr;
 | 
			
		||||
    size_t_map<void *>       m_heap;
 | 
			
		||||
    svector<z3_replayer_cmd> m_cmds;
 | 
			
		||||
    vector<std::string>      m_cmds_names;
 | 
			
		||||
 | 
			
		||||
    enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, INT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY, FLOAT };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -509,6 +510,7 @@ struct z3_replayer::imp {
 | 
			
		|||
                if (idx >= m_cmds.size())
 | 
			
		||||
                    throw z3_replayer_exception("invalid command");
 | 
			
		||||
                try {
 | 
			
		||||
                    TRACE("z3_replayer_cmd", tout << m_cmds_names[idx] << "\n";);
 | 
			
		||||
                    m_cmds[idx](m_owner);
 | 
			
		||||
                }
 | 
			
		||||
                catch (z3_error & ex) {
 | 
			
		||||
| 
						 | 
				
			
			@ -672,9 +674,11 @@ struct z3_replayer::imp {
 | 
			
		|||
        m_result = obj;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void register_cmd(unsigned id, z3_replayer_cmd cmd) {
 | 
			
		||||
    void register_cmd(unsigned id, z3_replayer_cmd cmd, char const* name) {
 | 
			
		||||
        m_cmds.reserve(id+1, 0);
 | 
			
		||||
        m_cmds_names.reserve(id+1, "");
 | 
			
		||||
        m_cmds[id] = cmd;
 | 
			
		||||
        m_cmds_names[id] = name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset() {
 | 
			
		||||
| 
						 | 
				
			
			@ -786,8 +790,8 @@ void z3_replayer::store_result(void * obj) {
 | 
			
		|||
    return m_imp->store_result(obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void z3_replayer::register_cmd(unsigned id, z3_replayer_cmd cmd) {
 | 
			
		||||
    return m_imp->register_cmd(id, cmd);
 | 
			
		||||
void z3_replayer::register_cmd(unsigned id, z3_replayer_cmd cmd, char const* name) {
 | 
			
		||||
    return m_imp->register_cmd(id, cmd, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void z3_replayer::parse() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ public:
 | 
			
		|||
    void ** get_obj_addr(unsigned pos);
 | 
			
		||||
 | 
			
		||||
    void store_result(void * obj);
 | 
			
		||||
    void register_cmd(unsigned id, z3_replayer_cmd cmd);
 | 
			
		||||
    void register_cmd(unsigned id, z3_replayer_cmd cmd, char const* name);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1656,6 +1656,7 @@ ast * ast_manager::register_node_core(ast * n) {
 | 
			
		|||
 | 
			
		||||
    n->m_id   = is_decl(n) ? m_decl_id_gen.mk() : m_expr_id_gen.mk();
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    TRACE("ast", tout << "Object " << n->m_id << " was created.\n";);
 | 
			
		||||
    TRACE("mk_var_bug", tout << "mk_ast: " << n->m_id << "\n";);
 | 
			
		||||
    // increment reference counters
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,6 +49,7 @@ void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const*
 | 
			
		|||
        case AST_APP: {
 | 
			
		||||
            app* a = to_app(curr);
 | 
			
		||||
            bool all_visited = true;
 | 
			
		||||
            bool changed = false;
 | 
			
		||||
            m_args.reset();
 | 
			
		||||
            for (unsigned i = 0; i < a->get_num_args(); ++i) {
 | 
			
		||||
                if (!m_map.find(a->get_arg(i), b)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -56,12 +57,17 @@ void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const*
 | 
			
		|||
                    all_visited = false;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    changed |= b != a->get_arg(i);
 | 
			
		||||
                    m_args.push_back(b);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (all_visited) {
 | 
			
		||||
                b = m.mk_app(a->get_decl(), m_args.size(), m_args.c_ptr());
 | 
			
		||||
                m_pinned.push_back(b);
 | 
			
		||||
                if (changed) {
 | 
			
		||||
                    b = m.mk_app(a->get_decl(), m_args.size(), m_args.c_ptr());
 | 
			
		||||
                    m_pinned.push_back(b);
 | 
			
		||||
                } else {
 | 
			
		||||
                    b = curr;
 | 
			
		||||
                }
 | 
			
		||||
                m_map.insert(curr, b);
 | 
			
		||||
                m_stack.pop_back();
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2490,12 +2490,12 @@ void fpa2bv_converter::mk_to_fp_real_int(func_decl * f, unsigned num, expr * con
 | 
			
		|||
    SASSERT(is_app_of(args[0], m_util.get_family_id(), OP_FPA_INTERNAL_RM));
 | 
			
		||||
    expr * bv_rm = to_app(args[0])->get_arg(0);
 | 
			
		||||
 | 
			
		||||
    rational q;
 | 
			
		||||
    if (!m_arith_util.is_numeral(args[1], q))
 | 
			
		||||
    rational e;
 | 
			
		||||
    if (!m_arith_util.is_numeral(args[1], e))
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
 | 
			
		||||
    rational e;
 | 
			
		||||
    if (!m_arith_util.is_numeral(args[2], e))
 | 
			
		||||
    rational q;
 | 
			
		||||
    if (!m_arith_util.is_numeral(args[2], q))
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
 | 
			
		||||
    SASSERT(e.is_int64());
 | 
			
		||||
| 
						 | 
				
			
			@ -2505,11 +2505,11 @@ void fpa2bv_converter::mk_to_fp_real_int(func_decl * f, unsigned num, expr * con
 | 
			
		|||
        return mk_pzero(f, result);
 | 
			
		||||
    else {
 | 
			
		||||
        scoped_mpf nte(m_mpf_manager), nta(m_mpf_manager), tp(m_mpf_manager), tn(m_mpf_manager), tz(m_mpf_manager);
 | 
			
		||||
        m_mpf_manager.set(nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        m_mpf_manager.set(nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        m_mpf_manager.set(tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        m_mpf_manager.set(tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        m_mpf_manager.set(nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, e.to_mpq().numerator(), q.to_mpq());
 | 
			
		||||
        m_mpf_manager.set(nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, e.to_mpq().numerator(), q.to_mpq());
 | 
			
		||||
        m_mpf_manager.set(tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, e.to_mpq().numerator(), q.to_mpq());
 | 
			
		||||
        m_mpf_manager.set(tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, e.to_mpq().numerator(), q.to_mpq());
 | 
			
		||||
        m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, e.to_mpq().numerator(), q.to_mpq());
 | 
			
		||||
 | 
			
		||||
        app_ref a_nte(m), a_nta(m), a_tp(m), a_tn(m), a_tz(m);
 | 
			
		||||
        a_nte = m_plugin->mk_numeral(nte);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,28 +69,30 @@ void fpa_decl_plugin::recycled_id(unsigned id) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func_decl * fpa_decl_plugin::mk_numeral_decl(mpf const & v) {
 | 
			
		||||
    parameter p(mk_id(v), true);
 | 
			
		||||
    SASSERT(p.is_external());
 | 
			
		||||
    sort * s = mk_float_sort(v.get_ebits(), v.get_sbits());
 | 
			
		||||
    return m_manager->mk_const_decl(symbol("fp.numeral"),  s, func_decl_info(m_family_id, OP_FPA_NUM, 1, &p));
 | 
			
		||||
    func_decl * r = 0;
 | 
			
		||||
    if (m_fm.is_nan(v))
 | 
			
		||||
        r = m_manager->mk_const_decl(symbol("NaN"), s, func_decl_info(m_family_id, OP_FPA_NAN));
 | 
			
		||||
    else if (m_fm.is_pinf(v))
 | 
			
		||||
        r = m_manager->mk_const_decl(symbol("+oo"), s, func_decl_info(m_family_id, OP_FPA_PLUS_INF));
 | 
			
		||||
    else if (m_fm.is_ninf(v))
 | 
			
		||||
        r = m_manager->mk_const_decl(symbol("-oo"), s, func_decl_info(m_family_id, OP_FPA_MINUS_INF));
 | 
			
		||||
    else if (m_fm.is_pzero(v))
 | 
			
		||||
        r = m_manager->mk_const_decl(symbol("+zero"), s, func_decl_info(m_family_id, OP_FPA_PLUS_ZERO));
 | 
			
		||||
    else if (m_fm.is_nzero(v))
 | 
			
		||||
        r = m_manager->mk_const_decl(symbol("-zero"), s, func_decl_info(m_family_id, OP_FPA_MINUS_ZERO));
 | 
			
		||||
    else {
 | 
			
		||||
        SASSERT(m_fm.is_regular(v));
 | 
			
		||||
        parameter p(mk_id(v), true);
 | 
			
		||||
        SASSERT(p.is_external());
 | 
			
		||||
        sort * s = mk_float_sort(v.get_ebits(), v.get_sbits());
 | 
			
		||||
        r = m_manager->mk_const_decl(symbol("fp.numeral"), s, func_decl_info(m_family_id, OP_FPA_NUM, 1, &p));
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
app * fpa_decl_plugin::mk_numeral(mpf const & v) {
 | 
			
		||||
    sort * s = mk_float_sort(v.get_ebits(), v.get_sbits());
 | 
			
		||||
    func_decl * d;
 | 
			
		||||
    if (m_fm.is_nan(v))
 | 
			
		||||
        d = m_manager->mk_const_decl(symbol("NaN"), s, func_decl_info(m_family_id, OP_FPA_NAN));
 | 
			
		||||
    else if (m_fm.is_pinf(v))
 | 
			
		||||
        d = m_manager->mk_const_decl(symbol("+oo"), s, func_decl_info(m_family_id, OP_FPA_PLUS_INF));
 | 
			
		||||
    else if (m_fm.is_ninf(v))
 | 
			
		||||
        d = m_manager->mk_const_decl(symbol("-oo"), s, func_decl_info(m_family_id, OP_FPA_MINUS_INF));
 | 
			
		||||
    else if (m_fm.is_pzero(v))
 | 
			
		||||
        d = m_manager->mk_const_decl(symbol("+zero"), s, func_decl_info(m_family_id, OP_FPA_PLUS_ZERO));
 | 
			
		||||
    else if (m_fm.is_nzero(v))
 | 
			
		||||
        d = m_manager->mk_const_decl(symbol("-zero"), s, func_decl_info(m_family_id, OP_FPA_MINUS_ZERO));
 | 
			
		||||
    else
 | 
			
		||||
        d = mk_numeral_decl(v);
 | 
			
		||||
    return m_manager->mk_const(d);
 | 
			
		||||
    return m_manager->mk_const(mk_numeral_decl(v));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool fpa_decl_plugin::is_numeral(expr * n, mpf & val) {
 | 
			
		||||
| 
						 | 
				
			
			@ -488,11 +490,24 @@ func_decl * fpa_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, para
 | 
			
		|||
        return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
 | 
			
		||||
    }
 | 
			
		||||
    else if (arity == 3 &&
 | 
			
		||||
             is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
 | 
			
		||||
             is_sort_of(domain[1], m_arith_fid, REAL_SORT) &&
 | 
			
		||||
             is_sort_of(domain[2], m_arith_fid, INT_SORT))
 | 
			
		||||
        is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
 | 
			
		||||
        is_sort_of(domain[1], m_arith_fid, REAL_SORT) &&
 | 
			
		||||
        is_sort_of(domain[2], m_arith_fid, INT_SORT))
 | 
			
		||||
    {
 | 
			
		||||
        // Rounding + 1 Real + 1 Int -> 1 FP
 | 
			
		||||
        // Rounding +  1 Real + 1 Int -> 1 FP
 | 
			
		||||
        if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
 | 
			
		||||
            m_manager->raise_exception("expecting two integer parameters to to_fp");
 | 
			
		||||
 | 
			
		||||
        sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
 | 
			
		||||
        symbol name("to_fp");
 | 
			
		||||
        return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
 | 
			
		||||
    }
 | 
			
		||||
    else if (arity == 3 &&
 | 
			
		||||
             is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) &&
 | 
			
		||||
             is_sort_of(domain[1], m_arith_fid, INT_SORT) &&
 | 
			
		||||
             is_sort_of(domain[2], m_arith_fid, REAL_SORT))
 | 
			
		||||
    {
 | 
			
		||||
        // Rounding +  1 Int + 1 Real -> 1 FP
 | 
			
		||||
        if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
 | 
			
		||||
            m_manager->raise_exception("expecting two integer parameters to to_fp");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -543,6 +558,7 @@ func_decl * fpa_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, para
 | 
			
		|||
                                   "(Real), "
 | 
			
		||||
                                   "(RoundingMode (_ BitVec (eb+sb))), "
 | 
			
		||||
                                   "(RoundingMode (_ FloatingPoint eb' sb')), "
 | 
			
		||||
                                   "(RoundingMode Int Real), "
 | 
			
		||||
                                   "(RoundingMode Real Int), "
 | 
			
		||||
                                   "(RoundingMode Int), and "
 | 
			
		||||
                                   "(RoundingMode Real)."
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -276,7 +276,7 @@ public:
 | 
			
		|||
    bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_pzero(v); }
 | 
			
		||||
    bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_nzero(v); }
 | 
			
		||||
 | 
			
		||||
    app * mk_fp(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_FP, arg1, arg2, arg3); }
 | 
			
		||||
    app * mk_fp(expr * sgn, expr * exp, expr * sig) { return m().mk_app(m_fid, OP_FPA_FP, sgn, exp, sig); }
 | 
			
		||||
    app * mk_to_fp(sort * s, expr * bv_t) {
 | 
			
		||||
        SASSERT(is_float(s) && s->get_num_parameters() == 2);
 | 
			
		||||
        return m().mk_app(m_fid, OP_FPA_TO_FP, 2, s->get_parameters(), 1, &bv_t);
 | 
			
		||||
| 
						 | 
				
			
			@ -286,9 +286,9 @@ public:
 | 
			
		|||
        expr * args[] = { rm, t };
 | 
			
		||||
        return m().mk_app(m_fid, OP_FPA_TO_FP, 2, s->get_parameters(), 2, args);
 | 
			
		||||
    }
 | 
			
		||||
    app * mk_to_fp(sort * s, expr * rm, expr * sig, expr * exp) {
 | 
			
		||||
    app * mk_to_fp(sort * s, expr * rm, expr * exp, expr * sig) {
 | 
			
		||||
        SASSERT(is_float(s) && s->get_num_parameters() == 2);
 | 
			
		||||
        expr * args[] = { rm, sig, exp };
 | 
			
		||||
        expr * args[] = { rm, exp, sig};
 | 
			
		||||
        return m().mk_app(m_fid, OP_FPA_TO_FP, 2, s->get_parameters(), 3, args);
 | 
			
		||||
    }
 | 
			
		||||
    app * mk_to_fp_unsigned(sort * s, expr * rm, expr * t) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,8 +121,11 @@ public:
 | 
			
		|||
    void mk_comp(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
 | 
			
		||||
 | 
			
		||||
    void mk_carry_save_adder(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr * const * c_bits, expr_ref_vector & sum_bits, expr_ref_vector & carry_bits);
 | 
			
		||||
    void mk_const_multiplier(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
 | 
			
		||||
    bool mk_const_multiplier(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
 | 
			
		||||
    bool mk_const_case_multiplier(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits);
 | 
			
		||||
    void mk_const_case_multiplier(bool is_a, unsigned i, unsigned sz, ptr_buffer<expr, 128>& a_bits, ptr_buffer<expr, 128>& b_bits, expr_ref_vector & out_bits);
 | 
			
		||||
 | 
			
		||||
    bool is_bool_const(expr* e) const { return m().is_true(e) || m().is_false(e); }
 | 
			
		||||
    void mk_abs(unsigned sz, expr * const * a_bits, expr_ref_vector & out_bits);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ void bit_blaster_tpl<Cfg>::checkpoint() {
 | 
			
		|||
template<typename Cfg>
 | 
			
		||||
bool bit_blaster_tpl<Cfg>::is_numeral(unsigned sz, expr * const * bits) const {
 | 
			
		||||
    for (unsigned i = 0; i < sz; i++)
 | 
			
		||||
        if (!m().is_true(bits[i]) && !m().is_false(bits[i]))
 | 
			
		||||
        if (!is_bool_const(bits[i])) 
 | 
			
		||||
            return false;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -158,32 +158,31 @@ void bit_blaster_tpl<Cfg>::mk_subtracter(unsigned sz, expr * const * a_bits, exp
 | 
			
		|||
template<typename Cfg>
 | 
			
		||||
void bit_blaster_tpl<Cfg>::mk_multiplier(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits) {
 | 
			
		||||
    SASSERT(sz > 0);
 | 
			
		||||
    
 | 
			
		||||
    if (!m_use_bcm) {
 | 
			
		||||
        numeral n_a, n_b;
 | 
			
		||||
        if (is_numeral(sz, a_bits, n_b))
 | 
			
		||||
            std::swap(a_bits, b_bits);
 | 
			
		||||
        if (is_minus_one(sz, b_bits)) {
 | 
			
		||||
            mk_neg(sz, a_bits, out_bits);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (is_numeral(sz, a_bits, n_a)) {
 | 
			
		||||
            n_a *= n_b;
 | 
			
		||||
            num2bits(n_a, sz, out_bits);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    numeral n_a, n_b;
 | 
			
		||||
    out_bits.reset();
 | 
			
		||||
    if (is_numeral(sz, a_bits, n_b))
 | 
			
		||||
        std::swap(a_bits, b_bits);
 | 
			
		||||
    if (is_minus_one(sz, b_bits)) {
 | 
			
		||||
        mk_neg(sz, a_bits, out_bits);
 | 
			
		||||
        SASSERT(sz == out_bits.size());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        numeral n_a, n_b;
 | 
			
		||||
        if (is_numeral(sz, a_bits, n_a)) {
 | 
			
		||||
            mk_const_multiplier(sz, a_bits, b_bits, out_bits);
 | 
			
		||||
            return;
 | 
			
		||||
        } else if (is_numeral(sz, b_bits, n_b)) {
 | 
			
		||||
            mk_const_multiplier(sz, b_bits, a_bits, out_bits);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    if (is_numeral(sz, a_bits, n_a)) {
 | 
			
		||||
        n_a *= n_b;
 | 
			
		||||
        num2bits(n_a, sz, out_bits);
 | 
			
		||||
        SASSERT(sz == out_bits.size());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (mk_const_multiplier(sz, a_bits, b_bits, out_bits)) {
 | 
			
		||||
        SASSERT(sz == out_bits.size());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (mk_const_multiplier(sz, b_bits, a_bits, out_bits)) {
 | 
			
		||||
        SASSERT(sz == out_bits.size());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    out_bits.reset();
 | 
			
		||||
    if (!m_use_wtm) {
 | 
			
		||||
#if 0
 | 
			
		||||
    static unsigned counter = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1171,20 +1170,84 @@ void bit_blaster_tpl<Cfg>::mk_carry_save_adder(unsigned sz, expr * const * a_bit
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
template<typename Cfg>
 | 
			
		||||
void bit_blaster_tpl<Cfg>::mk_const_multiplier(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits) {
 | 
			
		||||
    DEBUG_CODE({
 | 
			
		||||
        numeral x;
 | 
			
		||||
        SASSERT(is_numeral(sz, a_bits, x));
 | 
			
		||||
        SASSERT(out_bits.empty());        
 | 
			
		||||
    });    
 | 
			
		||||
bool bit_blaster_tpl<Cfg>::mk_const_case_multiplier(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits) {
 | 
			
		||||
    unsigned nb = 0;
 | 
			
		||||
    unsigned case_size = 1;
 | 
			
		||||
    unsigned circuit_size = sz*sz*5;
 | 
			
		||||
    for (unsigned i = 0; case_size < circuit_size && i < sz; ++i) {
 | 
			
		||||
        if (!is_bool_const(a_bits[i])) {
 | 
			
		||||
            case_size *= 2;
 | 
			
		||||
        }
 | 
			
		||||
        if (!is_bool_const(b_bits[i])) {
 | 
			
		||||
            case_size *= 2;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (case_size >= circuit_size) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    SASSERT(out_bits.empty());
 | 
			
		||||
    
 | 
			
		||||
    ptr_buffer<expr, 128> na_bits;
 | 
			
		||||
    na_bits.append(sz, a_bits);
 | 
			
		||||
    ptr_buffer<expr, 128> nb_bits;
 | 
			
		||||
    nb_bits.append(sz, b_bits);
 | 
			
		||||
    mk_const_case_multiplier(true, 0, sz, na_bits, nb_bits, out_bits); 
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
template<typename Cfg>
 | 
			
		||||
void bit_blaster_tpl<Cfg>::mk_const_case_multiplier(bool is_a, unsigned i, unsigned sz, ptr_buffer<expr, 128>& a_bits, ptr_buffer<expr, 128>& b_bits, expr_ref_vector & out_bits) {
 | 
			
		||||
    while (is_a && i < sz && is_bool_const(a_bits[i])) ++i;
 | 
			
		||||
    if (is_a && i == sz) { is_a = false; i = 0; }
 | 
			
		||||
    while (!is_a && i < sz && is_bool_const(b_bits[i])) ++i;
 | 
			
		||||
    if (i < sz) {
 | 
			
		||||
        expr_ref_vector out1(m()), out2(m());
 | 
			
		||||
        expr_ref x(m());
 | 
			
		||||
        x = is_a?a_bits[i]:b_bits[i];
 | 
			
		||||
        if (is_a) a_bits[i] = m().mk_true(); else b_bits[i] = m().mk_true();
 | 
			
		||||
        mk_const_case_multiplier(is_a, i+1, sz, a_bits, b_bits, out1);
 | 
			
		||||
        if (is_a) a_bits[i] = m().mk_false(); else b_bits[i] = m().mk_false();
 | 
			
		||||
        mk_const_case_multiplier(is_a, i+1, sz, a_bits, b_bits, out2);
 | 
			
		||||
        if (is_a) a_bits[i] = x; else b_bits[i] = x;
 | 
			
		||||
        SASSERT(out_bits.empty());
 | 
			
		||||
        for (unsigned j = 0; j < sz; ++j) {
 | 
			
		||||
            out_bits.push_back(m().mk_ite(x, out1[j].get(), out2[j].get()));
 | 
			
		||||
        }        
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        numeral n_a, n_b;
 | 
			
		||||
        SASSERT(i == sz && !is_a);
 | 
			
		||||
        VERIFY(is_numeral(sz, a_bits.c_ptr(), n_a));
 | 
			
		||||
        VERIFY(is_numeral(sz, b_bits.c_ptr(), n_b));
 | 
			
		||||
        n_a *= n_b;
 | 
			
		||||
        num2bits(n_a, sz, out_bits);
 | 
			
		||||
    }
 | 
			
		||||
    SASSERT(out_bits.size() == sz);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Cfg>
 | 
			
		||||
bool bit_blaster_tpl<Cfg>::mk_const_multiplier(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits) {
 | 
			
		||||
    numeral n_a;
 | 
			
		||||
    if (!is_numeral(sz, a_bits, n_a)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    SASSERT(out_bits.empty());
 | 
			
		||||
    
 | 
			
		||||
    if (mk_const_case_multiplier(sz, a_bits, b_bits, out_bits)) {
 | 
			
		||||
        SASSERT(sz == out_bits.size());
 | 
			
		||||
        return true;
 | 
			
		||||
    }    
 | 
			
		||||
    out_bits.reset();
 | 
			
		||||
    if (!m_use_bcm) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    expr_ref_vector minus_b_bits(m()), tmp(m());
 | 
			
		||||
    mk_neg(sz, b_bits, minus_b_bits);
 | 
			
		||||
        
 | 
			
		||||
    out_bits.resize(sz, m().mk_false());
 | 
			
		||||
    
 | 
			
		||||
#if 1
 | 
			
		||||
    bool last=false, now;
 | 
			
		||||
    bool last = false, now;
 | 
			
		||||
    for (unsigned i = 0; i < sz; i++) {
 | 
			
		||||
        now = m().is_true(a_bits[i]);
 | 
			
		||||
        SASSERT(now || m().is_false(a_bits[i]));
 | 
			
		||||
| 
						 | 
				
			
			@ -1255,4 +1318,7 @@ void bit_blaster_tpl<Cfg>::mk_const_multiplier(unsigned sz, expr * const * a_bit
 | 
			
		|||
 | 
			
		||||
    TRACE("bit_blaster_tpl_booth", for (unsigned i=0; i<out_bits.size(); i++)
 | 
			
		||||
                                     tout << "Booth encoding: " << mk_pp(out_bits[i].get(), m()) << "\n"; );
 | 
			
		||||
 | 
			
		||||
    SASSERT(out_bits.size() == sz);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1968,7 +1968,63 @@ void bv_rewriter::mk_t1_add_t2_eq_c(expr * t1, expr * t2, expr * c, expr_ref & r
 | 
			
		|||
        result = m().mk_eq(t1, m_util.mk_bv_sub(c, t2));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "ast_pp.h"
 | 
			
		||||
 | 
			
		||||
bool bv_rewriter::isolate_term(expr* lhs, expr* rhs, expr_ref& result) {
 | 
			
		||||
    if (!m_util.is_numeral(lhs) || !is_add(rhs)) {
 | 
			
		||||
        std::swap(lhs, rhs);
 | 
			
		||||
    }
 | 
			
		||||
    if (!m_util.is_numeral(lhs) || !is_add(rhs)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    unsigned sz = to_app(rhs)->get_num_args();
 | 
			
		||||
    expr_ref t1(m()), t2(m());
 | 
			
		||||
    t1 = to_app(rhs)->get_arg(0);
 | 
			
		||||
    if (sz > 2) {
 | 
			
		||||
        t2 = m().mk_app(get_fid(), OP_BADD, sz-1, to_app(rhs)->get_args()+1);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        SASSERT(sz == 2);
 | 
			
		||||
        t2 = to_app(rhs)->get_arg(1);
 | 
			
		||||
    }
 | 
			
		||||
    mk_t1_add_t2_eq_c(t1, t2, lhs, result);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool bv_rewriter::is_add_mul_const(expr* e) const {
 | 
			
		||||
    if (!m_util.is_bv_add(e)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    unsigned num = to_app(e)->get_num_args();
 | 
			
		||||
    for (unsigned i = 0; i < num; i++) {
 | 
			
		||||
        expr * arg = to_app(e)->get_arg(i);
 | 
			
		||||
        expr * c2, * x2;
 | 
			
		||||
        if (m_util.is_numeral(arg))
 | 
			
		||||
            continue;
 | 
			
		||||
        if (m_util.is_bv_mul(arg, c2, x2) && m_util.is_numeral(c2))
 | 
			
		||||
            continue;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool bv_rewriter::is_concat_target(expr* lhs, expr* rhs) const {
 | 
			
		||||
    return
 | 
			
		||||
        (m_util.is_concat(lhs) && (is_concat_split_target(rhs) || has_numeral(to_app(lhs)))) ||
 | 
			
		||||
        (m_util.is_concat(rhs) && (is_concat_split_target(lhs) || has_numeral(to_app(rhs))));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool bv_rewriter::has_numeral(app* a) const {
 | 
			
		||||
    for (unsigned i = 0; i < a->get_num_args(); ++i) {
 | 
			
		||||
        if (is_numeral(a->get_arg(i))) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_mul_eq(expr * lhs, expr * rhs, expr_ref & result) {
 | 
			
		||||
        
 | 
			
		||||
    expr * c, * x;
 | 
			
		||||
    numeral c_val, c_inv_val;
 | 
			
		||||
    unsigned sz;
 | 
			
		||||
| 
						 | 
				
			
			@ -2001,24 +2057,30 @@ br_status bv_rewriter::mk_mul_eq(expr * lhs, expr * rhs, expr_ref & result) {
 | 
			
		|||
 | 
			
		||||
        // c * x =  t_1 + ... + t_n
 | 
			
		||||
        // and t_i's have non-unary coefficients (this condition is used to make sure we are actually reducing the number of multipliers).
 | 
			
		||||
        if (m_util.is_bv_add(rhs)) {
 | 
			
		||||
        if (is_add_mul_const(rhs)) {
 | 
			
		||||
            // Potential problem: this simplification may increase the number of adders by reducing the amount of sharing.
 | 
			
		||||
            unsigned num = to_app(rhs)->get_num_args();
 | 
			
		||||
            unsigned i;
 | 
			
		||||
            for (i = 0; i < num; i++) {
 | 
			
		||||
                expr * arg = to_app(rhs)->get_arg(i);
 | 
			
		||||
                expr * c2, * x2;
 | 
			
		||||
                if (m_util.is_numeral(arg))
 | 
			
		||||
                    continue;
 | 
			
		||||
                if (m_util.is_bv_mul(arg, c2, x2) && m_util.is_numeral(c2))
 | 
			
		||||
                    continue;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if (i == num) {
 | 
			
		||||
                result = m().mk_eq(x, m_util.mk_bv_mul(m_util.mk_numeral(c_inv_val, sz), rhs));
 | 
			
		||||
                return BR_REWRITE2;
 | 
			
		||||
            result = m().mk_eq(x, m_util.mk_bv_mul(m_util.mk_numeral(c_inv_val, sz), rhs));
 | 
			
		||||
            return BR_REWRITE2;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.is_numeral(lhs, c_val, sz) && is_add_mul_const(rhs)) {
 | 
			
		||||
        unsigned num_args = to_app(rhs)->get_num_args();
 | 
			
		||||
        unsigned i = 0;
 | 
			
		||||
        expr* c2, *x2;
 | 
			
		||||
        numeral c2_val, c2_inv_val;
 | 
			
		||||
        bool found = false;
 | 
			
		||||
        for (; !found && i < num_args; ++i) {
 | 
			
		||||
            expr* arg = to_app(rhs)->get_arg(i);
 | 
			
		||||
            if (m_util.is_bv_mul(arg, c2, x2) && m_util.is_numeral(c2, c2_val, sz) &&
 | 
			
		||||
                m_util.mult_inverse(c2_val, sz, c2_inv_val)) {
 | 
			
		||||
                found = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (found) {
 | 
			
		||||
            result = m().mk_eq(m_util.mk_numeral(c2_inv_val*c_val, sz), 
 | 
			
		||||
                               m_util.mk_bv_mul(m_util.mk_numeral(c2_inv_val, sz), rhs));
 | 
			
		||||
            return BR_REWRITE3;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2065,9 +2127,10 @@ br_status bv_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
 | 
			
		|||
            return st;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expr_ref new_lhs(m());
 | 
			
		||||
    expr_ref new_rhs(m());
 | 
			
		||||
 | 
			
		||||
    if (m_util.is_bv_add(lhs) || m_util.is_bv_mul(lhs) || m_util.is_bv_add(rhs) || m_util.is_bv_mul(rhs)) {
 | 
			
		||||
        expr_ref new_lhs(m());
 | 
			
		||||
        expr_ref new_rhs(m());
 | 
			
		||||
        st = cancel_monomials(lhs, rhs, false, new_lhs, new_rhs);
 | 
			
		||||
        if (st != BR_FAILED) {
 | 
			
		||||
            if (is_numeral(new_lhs) && is_numeral(new_rhs)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2080,27 +2143,26 @@ br_status bv_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
 | 
			
		|||
            new_rhs = rhs;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        lhs = new_lhs;
 | 
			
		||||
        rhs = new_rhs;
 | 
			
		||||
        // Try to rewrite t1 + t2 = c --> t1 = c - t2   
 | 
			
		||||
        // Reason: it is much cheaper to bit-blast.
 | 
			
		||||
        expr * t1, * t2;
 | 
			
		||||
        if (m_util.is_bv_add(new_lhs, t1, t2) && is_numeral(new_rhs)) {
 | 
			
		||||
            mk_t1_add_t2_eq_c(t1, t2, new_rhs, result);
 | 
			
		||||
        if (isolate_term(lhs, rhs, result)) {
 | 
			
		||||
            return BR_REWRITE2;
 | 
			
		||||
        }
 | 
			
		||||
        if (m_util.is_bv_add(new_rhs, t1, t2) && is_numeral(new_lhs)) {
 | 
			
		||||
            mk_t1_add_t2_eq_c(t1, t2, new_lhs, result);
 | 
			
		||||
            return BR_REWRITE2;
 | 
			
		||||
        if (is_concat_target(lhs, rhs)) {
 | 
			
		||||
            return mk_eq_concat(lhs, rhs, result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (st != BR_FAILED) {
 | 
			
		||||
            result = m().mk_eq(new_lhs, new_rhs); 
 | 
			
		||||
            result = m().mk_eq(lhs, rhs); 
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((m_util.is_concat(lhs) && is_concat_split_target(rhs)) || 
 | 
			
		||||
        (m_util.is_concat(rhs) && is_concat_split_target(lhs)))
 | 
			
		||||
    if (is_concat_target(lhs, rhs)) {
 | 
			
		||||
        return mk_eq_concat(lhs, rhs, result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (swapped) {
 | 
			
		||||
        result = m().mk_eq(lhs, rhs);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -137,6 +137,10 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
 | 
			
		|||
    bool is_concat_split_target(expr * t) const;
 | 
			
		||||
 | 
			
		||||
    br_status mk_mul_eq(expr * lhs, expr * rhs, expr_ref & result);
 | 
			
		||||
    bool is_add_mul_const(expr* e) const;
 | 
			
		||||
    bool isolate_term(expr* lhs, expr* rhs, expr_ref & result);
 | 
			
		||||
    bool has_numeral(app* e) const;
 | 
			
		||||
    bool is_concat_target(expr* lhs, expr* rhs) const;
 | 
			
		||||
 | 
			
		||||
    void updt_local_params(params_ref const & p);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,9 +20,11 @@ Revision History:
 | 
			
		|||
 | 
			
		||||
#include "expr_safe_replace.h"
 | 
			
		||||
#include "rewriter.h"
 | 
			
		||||
#include "ast_pp.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void expr_safe_replace::insert(expr* src, expr* dst) {
 | 
			
		||||
    SASSERT(m.get_sort(src) == m.get_sort(dst));
 | 
			
		||||
    m_src.push_back(src);
 | 
			
		||||
    m_dst.push_back(dst);
 | 
			
		||||
    m_subst.insert(src, dst);
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +32,7 @@ void expr_safe_replace::insert(expr* src, expr* dst) {
 | 
			
		|||
 | 
			
		||||
void expr_safe_replace::operator()(expr* e, expr_ref& res) {
 | 
			
		||||
    m_todo.push_back(e);
 | 
			
		||||
    expr* a, *b, *d;
 | 
			
		||||
    expr* a, *b;
 | 
			
		||||
    
 | 
			
		||||
    while (!m_todo.empty()) {
 | 
			
		||||
        a = m_todo.back();
 | 
			
		||||
| 
						 | 
				
			
			@ -51,18 +53,21 @@ void expr_safe_replace::operator()(expr* e, expr_ref& res) {
 | 
			
		|||
            m_args.reset();
 | 
			
		||||
            bool arg_differs = false;
 | 
			
		||||
            for (unsigned i = 0; i < n; ++i) {
 | 
			
		||||
                if (m_cache.find(c->get_arg(i), d)) {
 | 
			
		||||
                expr* d = 0, *arg = c->get_arg(i);
 | 
			
		||||
                if (m_cache.find(arg, d)) {
 | 
			
		||||
                    m_args.push_back(d);
 | 
			
		||||
                    arg_differs |= c->get_arg(i) != d;
 | 
			
		||||
                    arg_differs |= arg != d;
 | 
			
		||||
                    SASSERT(m.get_sort(arg) == m.get_sort(d));
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    m_todo.push_back(c->get_arg(i));
 | 
			
		||||
                    m_todo.push_back(arg);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (m_args.size() == n) {
 | 
			
		||||
                if (arg_differs) {
 | 
			
		||||
                    b = m.mk_app(c->get_decl(), m_args.size(), m_args.c_ptr());
 | 
			
		||||
                    m_refs.push_back(b);
 | 
			
		||||
                    SASSERT(m.get_sort(a) == m.get_sort(b));
 | 
			
		||||
                } else {
 | 
			
		||||
                    b = a;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -213,7 +213,7 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
 | 
			
		|||
            mpf_exp_t mpf_exp = mpzm.get_int64(exp);
 | 
			
		||||
            mpf_exp = m_fm.unbias_exp(ebits, mpf_exp);
 | 
			
		||||
 | 
			
		||||
            m_fm.set(v, ebits, sbits, !mpzm.is_zero(z), sig, mpf_exp);
 | 
			
		||||
            m_fm.set(v, ebits, sbits, !mpzm.is_zero(z), mpf_exp, sig);
 | 
			
		||||
            TRACE("fp_rewriter",
 | 
			
		||||
                  tout << "sgn: " << !mpzm.is_zero(z) << std::endl;
 | 
			
		||||
                  tout << "sig: " << mpzm.to_string(sig) << std::endl;
 | 
			
		||||
| 
						 | 
				
			
			@ -267,7 +267,21 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
 | 
			
		|||
                return BR_FAILED;
 | 
			
		||||
 | 
			
		||||
            TRACE("fp_rewriter", tout << "r1: " << r1 << ", r2: " << r2 << "\n";);
 | 
			
		||||
            m_fm.set(v, ebits, sbits, rmv, r1.to_mpq(), r2.to_mpq().numerator());
 | 
			
		||||
            m_fm.set(v, ebits, sbits, rmv, r2.to_mpq().numerator(), r1.to_mpq());
 | 
			
		||||
            result = m_util.mk_value(v);
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
        else if (m_util.is_rm_numeral(args[0], rmv) &&
 | 
			
		||||
                 m_util.au().is_int(args[1]) &&
 | 
			
		||||
                 m_util.au().is_real(args[2])) {
 | 
			
		||||
            // rm + int + real -> float
 | 
			
		||||
            if (!m_util.is_rm_numeral(args[0], rmv) ||
 | 
			
		||||
                !m_util.au().is_numeral(args[1], r1) ||
 | 
			
		||||
                !m_util.au().is_numeral(args[2], r2))
 | 
			
		||||
                return BR_FAILED;
 | 
			
		||||
 | 
			
		||||
            TRACE("fp_rewriter", tout << "r1: " << r1 << ", r2: " << r2 << "\n";);
 | 
			
		||||
            m_fm.set(v, ebits, sbits, rmv, r1.to_mpq().numerator(), r2.to_mpq());
 | 
			
		||||
            result = m_util.mk_value(v);
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -281,8 +295,8 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
 | 
			
		|||
            mpf_exp_t biased_exp = m_fm.mpz_manager().get_int64(r2.to_mpq().numerator());
 | 
			
		||||
            m_fm.set(v, bvs2, bvs3 + 1,
 | 
			
		||||
                            r1.is_one(),
 | 
			
		||||
                            r3.to_mpq().numerator(),
 | 
			
		||||
                            m_fm.unbias_exp(bvs2, biased_exp));
 | 
			
		||||
                            m_fm.unbias_exp(bvs2, biased_exp),
 | 
			
		||||
                            r3.to_mpq().numerator());
 | 
			
		||||
            TRACE("fp_rewriter", tout << "v = " << m_fm.to_string(v) << std::endl;);
 | 
			
		||||
            result = m_util.mk_value(v);
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
| 
						 | 
				
			
			@ -753,24 +767,23 @@ br_status fpa_rewriter::mk_rm(expr * arg, expr_ref & result) {
 | 
			
		|||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status fpa_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
 | 
			
		||||
br_status fpa_rewriter::mk_fp(expr * sgn, expr * exp, expr * sig, expr_ref & result) {
 | 
			
		||||
    unsynch_mpz_manager & mpzm = m_fm.mpz_manager();
 | 
			
		||||
    bv_util bu(m());
 | 
			
		||||
    rational r1, r2, r3;
 | 
			
		||||
    unsigned bvs1, bvs2, bvs3;
 | 
			
		||||
    rational rsgn, rexp, rsig;
 | 
			
		||||
    unsigned bvsz_sgn, bvsz_exp, bvsz_sig;
 | 
			
		||||
 | 
			
		||||
    if (bu.is_numeral(arg1, r1, bvs1) &&
 | 
			
		||||
        bu.is_numeral(arg2, r2, bvs2) &&
 | 
			
		||||
        bu.is_numeral(arg3, r3, bvs3)) {
 | 
			
		||||
        SASSERT(mpzm.is_one(r2.to_mpq().denominator()));
 | 
			
		||||
        SASSERT(mpzm.is_one(r3.to_mpq().denominator()));
 | 
			
		||||
        SASSERT(mpzm.is_int64(r3.to_mpq().numerator()));
 | 
			
		||||
    if (bu.is_numeral(sgn, rsgn, bvsz_sgn) &&
 | 
			
		||||
        bu.is_numeral(sig, rsig, bvsz_sig) &&
 | 
			
		||||
        bu.is_numeral(exp, rexp, bvsz_exp)) {
 | 
			
		||||
        SASSERT(mpzm.is_one(rexp.to_mpq().denominator()));
 | 
			
		||||
        SASSERT(mpzm.is_one(rsig.to_mpq().denominator()));
 | 
			
		||||
        scoped_mpf v(m_fm);
 | 
			
		||||
        mpf_exp_t biased_exp = mpzm.get_int64(r2.to_mpq().numerator());
 | 
			
		||||
        m_fm.set(v, bvs2, bvs3 + 1,
 | 
			
		||||
                        r1.is_one(),
 | 
			
		||||
                        r3.to_mpq().numerator(),
 | 
			
		||||
                        m_fm.unbias_exp(bvs2, biased_exp));
 | 
			
		||||
        mpf_exp_t biased_exp = mpzm.get_int64(rexp.to_mpq().numerator());
 | 
			
		||||
        m_fm.set(v, bvsz_exp, bvsz_sig + 1,
 | 
			
		||||
                        rsgn.is_one(),
 | 
			
		||||
                        m_fm.unbias_exp(bvsz_exp, biased_exp),
 | 
			
		||||
                        rsig.to_mpq().numerator());
 | 
			
		||||
        TRACE("fp_rewriter", tout << "simplified (fp ...) to " << m_fm.to_string(v) << std::endl;);
 | 
			
		||||
        result = m_util.mk_value(v);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,7 +79,7 @@ public:
 | 
			
		|||
    br_status mk_to_fp_unsigned(func_decl * f, expr * arg1, expr * arg2, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    br_status mk_rm(expr * arg, expr_ref & result);
 | 
			
		||||
    br_status mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result);
 | 
			
		||||
    br_status mk_fp(expr * sgn, expr * exp, expr * sig, expr_ref & result);
 | 
			
		||||
    br_status mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result);
 | 
			
		||||
    br_status mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result);
 | 
			
		||||
    br_status mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,30 +22,144 @@ Notes:
 | 
			
		|||
#include"ast_pp.h"
 | 
			
		||||
#include"ast_util.h"
 | 
			
		||||
#include"uint_set.h"
 | 
			
		||||
#include"automaton.h"
 | 
			
		||||
#include"well_sorted.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct display_expr1 {
 | 
			
		||||
    ast_manager& m;
 | 
			
		||||
    display_expr1(ast_manager& m): m(m) {}
 | 
			
		||||
    std::ostream& display(std::ostream& out, expr* e) const {
 | 
			
		||||
        return out << mk_pp(e, m);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
re2automaton::re2automaton(ast_manager& m): m(m), u(m) {}
 | 
			
		||||
 | 
			
		||||
eautomaton* re2automaton::operator()(expr* e) { 
 | 
			
		||||
    eautomaton* r = re2aut(e); 
 | 
			
		||||
    if (r) {
 | 
			
		||||
        //display_expr1 disp(m);
 | 
			
		||||
        //r->display(std::cout, disp);
 | 
			
		||||
        r->compress(); 
 | 
			
		||||
        //r->display(std::cout, disp);
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
} 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
eautomaton* re2automaton::re2aut(expr* e) {
 | 
			
		||||
    SASSERT(u.is_re(e));
 | 
			
		||||
    expr* e1, *e2;
 | 
			
		||||
    scoped_ptr<eautomaton> a, b;
 | 
			
		||||
    if (u.re.is_to_re(e, e1)) {
 | 
			
		||||
        return seq2aut(e1);
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.re.is_concat(e, e1, e2) && (a = re2aut(e1)) && (b = re2aut(e2))) {
 | 
			
		||||
        return eautomaton::mk_concat(*a, *b);
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.re.is_union(e, e1, e2) && (a = re2aut(e1)) && (b = re2aut(e2))) {
 | 
			
		||||
        return eautomaton::mk_union(*a, *b);
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.re.is_star(e, e1) && (a = re2aut(e1))) {
 | 
			
		||||
        a->add_final_to_init_moves();
 | 
			
		||||
        a->add_init_to_final_states();
 | 
			
		||||
        
 | 
			
		||||
        return a.detach();            
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.re.is_plus(e, e1) && (a = re2aut(e1))) {
 | 
			
		||||
        a->add_final_to_init_moves();
 | 
			
		||||
        return a.detach();            
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.re.is_opt(e, e1) && (a = re2aut(e1))) {
 | 
			
		||||
        a = eautomaton::mk_opt(*a);
 | 
			
		||||
        return a.detach();                    
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.re.is_range(e)) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.re.is_loop(e)) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
#if 0
 | 
			
		||||
    else if (u.re.is_intersect(e, e1, e2)) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.re.is_empty(e)) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eautomaton* re2automaton::seq2aut(expr* e) {
 | 
			
		||||
    SASSERT(u.is_seq(e));
 | 
			
		||||
    zstring s;
 | 
			
		||||
    expr* e1, *e2;
 | 
			
		||||
    scoped_ptr<eautomaton> a, b;
 | 
			
		||||
    if (u.str.is_concat(e, e1, e2) && (a = seq2aut(e1)) && (b = seq2aut(e2))) {
 | 
			
		||||
        return eautomaton::mk_concat(*a, *b);
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.str.is_unit(e, e1)) {
 | 
			
		||||
        return alloc(eautomaton, m, e1);
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.str.is_empty(e)) {
 | 
			
		||||
        return eautomaton::mk_epsilon(m);
 | 
			
		||||
    }
 | 
			
		||||
    else if (u.str.is_string(e, s)) {        
 | 
			
		||||
        unsigned init = 0;
 | 
			
		||||
        eautomaton::moves mvs;        
 | 
			
		||||
        unsigned_vector final;
 | 
			
		||||
        final.push_back(s.length());
 | 
			
		||||
        for (unsigned k = 0; k < s.length(); ++k) {
 | 
			
		||||
            // reference count?
 | 
			
		||||
            mvs.push_back(eautomaton::move(m, k, k+1, u.str.mk_char(s, k)));
 | 
			
		||||
        }
 | 
			
		||||
        return alloc(eautomaton, m, init, final, mvs);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(f->get_family_id() == get_fid());
 | 
			
		||||
    
 | 
			
		||||
    switch(f->get_decl_kind()) {
 | 
			
		||||
 | 
			
		||||
    case OP_SEQ_UNIT:
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
    case OP_SEQ_EMPTY:
 | 
			
		||||
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
    case OP_RE_PLUS:
 | 
			
		||||
        SASSERT(num_args == 1);
 | 
			
		||||
        return mk_re_plus(args[0], result);
 | 
			
		||||
    case OP_RE_STAR:
 | 
			
		||||
        SASSERT(num_args == 1);
 | 
			
		||||
        return mk_re_star(args[0], result);
 | 
			
		||||
    case OP_RE_OPTION:
 | 
			
		||||
    case OP_RE_RANGE:
 | 
			
		||||
        SASSERT(num_args == 1);
 | 
			
		||||
        return mk_re_opt(args[0], result);
 | 
			
		||||
    case OP_RE_CONCAT:
 | 
			
		||||
        SASSERT(num_args == 2);
 | 
			
		||||
        return mk_re_concat(args[0], args[1], result);
 | 
			
		||||
    case OP_RE_UNION:
 | 
			
		||||
        SASSERT(num_args == 2);
 | 
			
		||||
        return mk_re_union(args[0], args[1], result);
 | 
			
		||||
    case OP_RE_RANGE:
 | 
			
		||||
        return BR_FAILED;    
 | 
			
		||||
    case OP_RE_INTERSECT:
 | 
			
		||||
        return BR_FAILED;    
 | 
			
		||||
    case OP_RE_LOOP:
 | 
			
		||||
        return BR_FAILED;    
 | 
			
		||||
    case OP_RE_EMPTY_SET:
 | 
			
		||||
        return BR_FAILED;    
 | 
			
		||||
    case OP_RE_FULL_SET:
 | 
			
		||||
        return BR_FAILED;    
 | 
			
		||||
    case OP_RE_OF_PRED:
 | 
			
		||||
        return BR_FAILED;    
 | 
			
		||||
    case _OP_SEQ_SKOLEM:
 | 
			
		||||
        return BR_FAILED;    
 | 
			
		||||
    
 | 
			
		||||
    case OP_SEQ_CONCAT: 
 | 
			
		||||
        if (num_args == 1) {
 | 
			
		||||
            result = args[0];
 | 
			
		||||
| 
						 | 
				
			
			@ -83,10 +197,11 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
 | 
			
		|||
        SASSERT(num_args == 3);
 | 
			
		||||
        return mk_seq_replace(args[0], args[1], args[2], result);
 | 
			
		||||
    case OP_SEQ_TO_RE:
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
        SASSERT(num_args == 1);
 | 
			
		||||
        return mk_str_to_regexp(args[0], result);
 | 
			
		||||
    case OP_SEQ_IN_RE:
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
 | 
			
		||||
        SASSERT(num_args == 2);
 | 
			
		||||
        return mk_str_in_regexp(args[0], args[1], result);
 | 
			
		||||
    case OP_STRING_CONST:
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
    case OP_STRING_ITOS: 
 | 
			
		||||
| 
						 | 
				
			
			@ -129,8 +244,8 @@ br_status seq_rewriter::mk_seq_concat(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
        result = m_util.str.mk_string(s1 + s2);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.str.is_concat(b, c, d)) {
 | 
			
		||||
        result = m_util.str.mk_concat(m_util.str.mk_concat(a, c), d);
 | 
			
		||||
    if (m_util.str.is_concat(a, c, d)) {
 | 
			
		||||
        result = m_util.str.mk_concat(c, m_util.str.mk_concat(d, b));
 | 
			
		||||
        return BR_REWRITE2;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.str.is_empty(a)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -141,11 +256,15 @@ br_status seq_rewriter::mk_seq_concat(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.str.is_concat(a, c, d) && 
 | 
			
		||||
        m_util.str.is_string(d, s1) && isc2) {
 | 
			
		||||
    // TBD concatenation is right-associative
 | 
			
		||||
    if (isc2 && m_util.str.is_concat(a, c, d) && m_util.str.is_string(d, s1)) {
 | 
			
		||||
        result = m_util.str.mk_concat(c, m_util.str.mk_string(s1 + s2));
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (isc1 && m_util.str.is_concat(b, c, d) && m_util.str.is_string(c, s2)) {
 | 
			
		||||
        result = m_util.str.mk_concat(m_util.str.mk_string(s1 + s2), d);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -156,17 +275,17 @@ br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) {
 | 
			
		|||
    unsigned len = 0;
 | 
			
		||||
    unsigned j = 0;
 | 
			
		||||
    for (unsigned i = 0; i < m_es.size(); ++i) {
 | 
			
		||||
        if (m_util.str.is_string(m_es[i], b)) {
 | 
			
		||||
        if (m_util.str.is_string(m_es[i].get(), b)) {
 | 
			
		||||
            len += b.length();
 | 
			
		||||
        }
 | 
			
		||||
        else if (m_util.str.is_unit(m_es[i])) {
 | 
			
		||||
        else if (m_util.str.is_unit(m_es[i].get())) {
 | 
			
		||||
            len += 1;
 | 
			
		||||
        }
 | 
			
		||||
        else if (m_util.str.is_empty(m_es[i])) {
 | 
			
		||||
        else if (m_util.str.is_empty(m_es[i].get())) {
 | 
			
		||||
            // skip
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            m_es[j] = m_es[i];
 | 
			
		||||
            m_es[j] = m_es[i].get();
 | 
			
		||||
            ++j;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +296,7 @@ br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) {
 | 
			
		|||
    if (j != m_es.size() || j != 1) {
 | 
			
		||||
        expr_ref_vector es(m());        
 | 
			
		||||
        for (unsigned i = 0; i < j; ++i) {
 | 
			
		||||
            es.push_back(m_util.str.mk_length(m_es[i]));
 | 
			
		||||
            es.push_back(m_util.str.mk_length(m_es[i].get()));
 | 
			
		||||
        }
 | 
			
		||||
        if (len != 0) {
 | 
			
		||||
            es.push_back(m_autil.mk_numeral(rational(len, rational::ui64()), true));
 | 
			
		||||
| 
						 | 
				
			
			@ -207,20 +326,31 @@ br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    // check if subsequence of b is in a.
 | 
			
		||||
    ptr_vector<expr> as, bs;
 | 
			
		||||
    expr_ref_vector as(m()), bs(m());
 | 
			
		||||
    m_util.str.get_concat(a, as);
 | 
			
		||||
    m_util.str.get_concat(b, bs);
 | 
			
		||||
    bool all_values = true;
 | 
			
		||||
    
 | 
			
		||||
    for (unsigned i = 0; all_values && i < bs.size(); ++i) { 
 | 
			
		||||
        all_values = m().is_value(bs[i].get());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool found = false;
 | 
			
		||||
    for (unsigned i = 0; !found && i < as.size(); ++i) {
 | 
			
		||||
        if (bs.size() > as.size() - i) break;
 | 
			
		||||
        all_values &= m().is_value(as[i].get());
 | 
			
		||||
        unsigned j = 0;
 | 
			
		||||
        for (; j < bs.size() && as[j+i] == bs[j]; ++j) {};
 | 
			
		||||
        for (; j < bs.size() && as[j+i].get() == bs[j].get(); ++j) {};
 | 
			
		||||
        found = j == bs.size();
 | 
			
		||||
    }
 | 
			
		||||
    if (found) {
 | 
			
		||||
        result = m().mk_true();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (all_values) {
 | 
			
		||||
        result = m().mk_false();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -292,7 +422,7 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
    expr* b1 = m_util.str.get_leftmost_concat(b);
 | 
			
		||||
    isc1 = m_util.str.is_string(a1, s1);
 | 
			
		||||
    isc2 = m_util.str.is_string(b1, s2);
 | 
			
		||||
    ptr_vector<expr> as, bs;
 | 
			
		||||
    expr_ref_vector as(m()), bs(m());
 | 
			
		||||
 | 
			
		||||
    if (a1 != b1 && isc1 && isc2) {
 | 
			
		||||
        if (s1.length() <= s2.length()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -342,15 +472,26 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
    m_util.str.get_concat(a, as);
 | 
			
		||||
    m_util.str.get_concat(b, bs);
 | 
			
		||||
    unsigned i = 0;
 | 
			
		||||
    for (; i < as.size() && i < bs.size() && as[i] == bs[i]; ++i) {};
 | 
			
		||||
    bool all_values = true;    
 | 
			
		||||
    for (; i < as.size() && i < bs.size(); ++i) {
 | 
			
		||||
        all_values &= m().is_value(as[i].get()) && m().is_value(bs[i].get());
 | 
			
		||||
        if (as[i].get() != bs[i].get()) {
 | 
			
		||||
            if (all_values) {
 | 
			
		||||
                result = m().mk_false();
 | 
			
		||||
                return BR_DONE;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    if (i == as.size()) {
 | 
			
		||||
        result = m().mk_true();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    SASSERT(i < as.size());
 | 
			
		||||
    if (i == bs.size()) {
 | 
			
		||||
        expr_ref_vector es(m());
 | 
			
		||||
        for (unsigned j = i; j < as.size(); ++j) {
 | 
			
		||||
            es.push_back(m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), as[j]));
 | 
			
		||||
            es.push_back(m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), as[j].get()));
 | 
			
		||||
        }
 | 
			
		||||
        result = mk_and(es);
 | 
			
		||||
        return BR_REWRITE3;
 | 
			
		||||
| 
						 | 
				
			
			@ -380,20 +521,10 @@ br_status seq_rewriter::mk_seq_suffix(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
        result = m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), a);
 | 
			
		||||
        return BR_REWRITE3;
 | 
			
		||||
    }
 | 
			
		||||
    // concatenation is left-associative, so a2, b2 are not concatenations
 | 
			
		||||
    expr* a1, *a2, *b1, *b2;
 | 
			
		||||
    if (m_util.str.is_concat(a, a1, a2) && 
 | 
			
		||||
        m_util.str.is_concat(b, b1, b2) && a2 == b2) {
 | 
			
		||||
        result = m_util.str.mk_suffix(a1, b1);
 | 
			
		||||
        return BR_REWRITE1;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.str.is_concat(b, b1, b2) && b2 == a) {
 | 
			
		||||
        result = m().mk_true();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool isc1 = false;
 | 
			
		||||
    bool isc2 = false;
 | 
			
		||||
    
 | 
			
		||||
    expr* a1, *a2, *b1, *b2;
 | 
			
		||||
    if (m_util.str.is_concat(a, a1, a2) && m_util.str.is_string(a2, s1)) {
 | 
			
		||||
        isc1 = true;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -453,6 +584,37 @@ br_status seq_rewriter::mk_seq_suffix(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
            }            
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    expr_ref_vector as(m()), bs(m());
 | 
			
		||||
    m_util.str.get_concat(a, as);
 | 
			
		||||
    m_util.str.get_concat(b, bs);
 | 
			
		||||
    bool change = false;
 | 
			
		||||
    while (as.size() > 0 && bs.size() > 0 && as.back() == bs.back()) {
 | 
			
		||||
        as.pop_back();
 | 
			
		||||
        bs.pop_back();
 | 
			
		||||
        change = true;
 | 
			
		||||
    }
 | 
			
		||||
    if (as.size() > 0 && bs.size() > 0 && m().is_value(as.back()) && m().is_value(bs.back())) {
 | 
			
		||||
        result = m().mk_false();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (change) {
 | 
			
		||||
        // suffix("", bs) <- true
 | 
			
		||||
        if (as.empty()) {
 | 
			
		||||
            result = m().mk_true();
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
        // suffix(as, "") iff as = ""
 | 
			
		||||
        if (bs.empty()) {            
 | 
			
		||||
            for (unsigned j = 0; j < as.size(); ++j) {
 | 
			
		||||
                bs.push_back(m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), as[j].get()));
 | 
			
		||||
            }
 | 
			
		||||
            result = mk_and(bs);
 | 
			
		||||
            return BR_REWRITE3;
 | 
			
		||||
        }
 | 
			
		||||
        result = m_util.str.mk_suffix(m_util.str.mk_concat(as.size(), as.c_ptr()),
 | 
			
		||||
                                     m_util.str.mk_concat(bs.size(), bs.c_ptr()));
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -480,26 +642,190 @@ br_status seq_rewriter::mk_str_stoi(expr* a, expr_ref& result) {
 | 
			
		|||
    }
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void seq_rewriter::add_next(u_map<expr*>& next, unsigned idx, expr* cond) {
 | 
			
		||||
    expr* acc;
 | 
			
		||||
    if (m().is_true(cond) || !next.find(idx, acc)) {              
 | 
			
		||||
        next.insert(idx, cond);                   
 | 
			
		||||
    }                                                   
 | 
			
		||||
    else {                                              
 | 
			
		||||
        next.insert(idx, m().mk_or(cond, acc));   
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool seq_rewriter::is_sequence(expr* e, expr_ref_vector& seq) {
 | 
			
		||||
    zstring s;
 | 
			
		||||
    ptr_vector<expr> todo;
 | 
			
		||||
    expr *e1, *e2;
 | 
			
		||||
    todo.push_back(e);
 | 
			
		||||
    while (!todo.empty()) {
 | 
			
		||||
        e = todo.back();
 | 
			
		||||
        todo.pop_back();
 | 
			
		||||
        if (m_util.str.is_string(e, s)) {
 | 
			
		||||
            for (unsigned i = s.length(); i > 0; ) {
 | 
			
		||||
                --i;
 | 
			
		||||
                seq.push_back(m_util.str.mk_char(s, i));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (m_util.str.is_empty(e)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        else if (m_util.str.is_unit(e)) {
 | 
			
		||||
            seq.push_back(e);
 | 
			
		||||
        }
 | 
			
		||||
        else if (m_util.str.is_concat(e, e1, e2)) {
 | 
			
		||||
            todo.push_back(e1);
 | 
			
		||||
            todo.push_back(e2);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    seq.reverse();
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
 | 
			
		||||
    scoped_ptr<eautomaton> aut;
 | 
			
		||||
    expr_ref_vector seq(m());
 | 
			
		||||
    if (is_sequence(a, seq) && (aut = re2automaton(m())(b))) {
 | 
			
		||||
        expr_ref_vector trail(m());
 | 
			
		||||
        u_map<expr*> maps[2];
 | 
			
		||||
        bool select_map = false;
 | 
			
		||||
        expr_ref ch(m()), cond(m());
 | 
			
		||||
        eautomaton::moves mvs;
 | 
			
		||||
        maps[0].insert(aut->init(), m().mk_true());
 | 
			
		||||
        // is_accepted(a, aut) & some state in frontier is final.
 | 
			
		||||
 | 
			
		||||
        for (unsigned i = 0; i < seq.size(); ++i) {
 | 
			
		||||
            u_map<expr*>& frontier = maps[select_map];
 | 
			
		||||
            u_map<expr*>& next = maps[!select_map];
 | 
			
		||||
            select_map = !select_map;
 | 
			
		||||
            ch = seq[i].get();
 | 
			
		||||
            next.reset();
 | 
			
		||||
            u_map<expr*>::iterator it = frontier.begin(), end = frontier.end();
 | 
			
		||||
            for (; it != end; ++it) {
 | 
			
		||||
                mvs.reset();
 | 
			
		||||
                unsigned state = it->m_key;
 | 
			
		||||
                expr*    acc  = it->m_value;
 | 
			
		||||
                aut->get_moves_from(state, mvs, false);
 | 
			
		||||
                for (unsigned j = 0; j < mvs.size(); ++j) {
 | 
			
		||||
                    eautomaton::move const& mv = mvs[j];
 | 
			
		||||
                    if (m().is_value(mv.t()) && m().is_value(ch)) {
 | 
			
		||||
                        if (mv.t() == ch) {
 | 
			
		||||
                            add_next(next, mv.dst(), acc);
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        cond = m().mk_eq(mv.t(), ch);
 | 
			
		||||
                        if (!m().is_true(acc)) cond = m().mk_and(acc, cond);
 | 
			
		||||
                        add_next(next, mv.dst(), cond);
 | 
			
		||||
                    }
 | 
			
		||||
                }                
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        u_map<expr*> const& frontier = maps[select_map];
 | 
			
		||||
        u_map<expr*>::iterator it = frontier.begin(), end = frontier.end();
 | 
			
		||||
        expr_ref_vector ors(m());
 | 
			
		||||
        for (; it != end; ++it) {
 | 
			
		||||
            unsigned_vector states;
 | 
			
		||||
            bool has_final = false;
 | 
			
		||||
            aut->get_epsilon_closure(it->m_key, states);
 | 
			
		||||
            for (unsigned i = 0; i < states.size() && !has_final; ++i) {
 | 
			
		||||
                has_final = aut->is_final_state(states[i]);
 | 
			
		||||
            }
 | 
			
		||||
            if (has_final) {
 | 
			
		||||
                ors.push_back(it->m_value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        result = mk_or(ors);
 | 
			
		||||
        return BR_REWRITE_FULL;
 | 
			
		||||
    }
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
br_status seq_rewriter::mk_str_to_regexp(expr* a, expr_ref& result) {
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
br_status seq_rewriter::mk_re_concat(expr* a, expr* b, expr_ref& result) {
 | 
			
		||||
    if (is_epsilon(a)) {
 | 
			
		||||
        result = b;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (is_epsilon(b)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
  (a + a) = a
 | 
			
		||||
  (a + eps) = a
 | 
			
		||||
  (eps + a) = a
 | 
			
		||||
*/
 | 
			
		||||
br_status seq_rewriter::mk_re_union(expr* a, expr* b, expr_ref& result) {
 | 
			
		||||
    if (a == b) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_star(a) && is_epsilon(b)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_star(b) && is_epsilon(a)) {
 | 
			
		||||
        result = b;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
  a** = a*
 | 
			
		||||
  (a* + b)* = (a + b)*
 | 
			
		||||
  (a + b*)* = (a + b)*
 | 
			
		||||
  (a*b*)*   = (a + b)*
 | 
			
		||||
*/
 | 
			
		||||
br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
 | 
			
		||||
    expr* b, *c, *b1, *c1;
 | 
			
		||||
    if (m_util.re.is_star(a)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_union(a, b, c)) {
 | 
			
		||||
        if (m_util.re.is_star(b, b1)) {
 | 
			
		||||
            result = m_util.re.mk_star(m_util.re.mk_union(b1, c));
 | 
			
		||||
            return BR_REWRITE2;
 | 
			
		||||
        }
 | 
			
		||||
        if (m_util.re.is_star(c, c1)) {
 | 
			
		||||
            result = m_util.re.mk_star(m_util.re.mk_union(b, c1));
 | 
			
		||||
            return BR_REWRITE2;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_concat(a, b, c) &&
 | 
			
		||||
        m_util.re.is_star(b, b1) && m_util.re.is_star(c, c1)) {
 | 
			
		||||
        result = m_util.re.mk_star(m_util.re.mk_union(b1, c1));
 | 
			
		||||
        return BR_REWRITE2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
   a+ = aa*
 | 
			
		||||
*/
 | 
			
		||||
br_status seq_rewriter::mk_re_plus(expr* a, expr_ref& result) {
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
//  result = m_util.re.mk_concat(a, m_util.re.mk_star(a));
 | 
			
		||||
//  return BR_REWRITE2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status seq_rewriter::mk_re_opt(expr* a, expr_ref& result) {
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
    sort* s;
 | 
			
		||||
    VERIFY(m_util.is_re(a, s));
 | 
			
		||||
    sort_ref seq(m_util.str.mk_seq(s), m());
 | 
			
		||||
    result = m_util.re.mk_union(m_util.re.mk_to_re(m_util.str.mk_empty(seq)), a);
 | 
			
		||||
    return BR_REWRITE1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status seq_rewriter::mk_eq_core(expr * l, expr * r, expr_ref & result) {
 | 
			
		||||
| 
						 | 
				
			
			@ -518,38 +844,33 @@ br_status seq_rewriter::mk_eq_core(expr * l, expr * r, expr_ref & result) {
 | 
			
		|||
    return BR_REWRITE3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_vector& rhs) {
 | 
			
		||||
bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_vector& lhs, expr_ref_vector& rhs) {
 | 
			
		||||
    expr* a, *b;
 | 
			
		||||
    zstring s;
 | 
			
		||||
    bool change = false;
 | 
			
		||||
    expr_ref_vector trail(m());
 | 
			
		||||
    m_lhs.reset();
 | 
			
		||||
    m_rhs.reset();
 | 
			
		||||
    m_util.str.get_concat(l, m_lhs);
 | 
			
		||||
    m_util.str.get_concat(r, m_rhs);
 | 
			
		||||
 
 | 
			
		||||
    // solve from back
 | 
			
		||||
    while (true) {
 | 
			
		||||
        while (!m_rhs.empty() && m_util.str.is_empty(m_rhs.back())) {
 | 
			
		||||
            m_rhs.pop_back();
 | 
			
		||||
        while (!rs.empty() && m_util.str.is_empty(rs.back())) {
 | 
			
		||||
            rs.pop_back();
 | 
			
		||||
            change = true;
 | 
			
		||||
        }
 | 
			
		||||
        while (!m_lhs.empty() && m_util.str.is_empty(m_lhs.back())) {
 | 
			
		||||
            m_lhs.pop_back();
 | 
			
		||||
        while (!ls.empty() && m_util.str.is_empty(ls.back())) {
 | 
			
		||||
            ls.pop_back();
 | 
			
		||||
            change = true;
 | 
			
		||||
        }
 | 
			
		||||
        if (m_lhs.empty() || m_rhs.empty()) {
 | 
			
		||||
        if (ls.empty() || rs.empty()) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        expr* l = m_lhs.back();
 | 
			
		||||
        expr* r = m_rhs.back();
 | 
			
		||||
        expr* l = ls.back();
 | 
			
		||||
        expr* r = rs.back();
 | 
			
		||||
        if (m_util.str.is_unit(r) && m_util.str.is_string(l)) {
 | 
			
		||||
            std::swap(l, r);
 | 
			
		||||
            std::swap(m_lhs, m_rhs);
 | 
			
		||||
            ls.swap(rs);
 | 
			
		||||
        }
 | 
			
		||||
        if (l == r) {
 | 
			
		||||
            m_lhs.pop_back();
 | 
			
		||||
            m_rhs.pop_back();
 | 
			
		||||
            ls.pop_back();
 | 
			
		||||
            rs.pop_back();
 | 
			
		||||
        }
 | 
			
		||||
        else if(m_util.str.is_unit(l, a) &&
 | 
			
		||||
                m_util.str.is_unit(r, b)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -558,8 +879,8 @@ bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_ve
 | 
			
		|||
            }
 | 
			
		||||
            lhs.push_back(a);
 | 
			
		||||
            rhs.push_back(b);
 | 
			
		||||
            m_lhs.pop_back();
 | 
			
		||||
            m_rhs.pop_back();
 | 
			
		||||
            ls.pop_back();
 | 
			
		||||
            rs.pop_back();
 | 
			
		||||
        }
 | 
			
		||||
        else if (m_util.str.is_unit(l, a) && m_util.str.is_string(r, s)) {
 | 
			
		||||
            SASSERT(s.length() > 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -568,14 +889,13 @@ bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_ve
 | 
			
		|||
            SASSERT(m().get_sort(ch) == m().get_sort(a));
 | 
			
		||||
            lhs.push_back(ch);
 | 
			
		||||
            rhs.push_back(a);
 | 
			
		||||
            m_lhs.pop_back();
 | 
			
		||||
            ls.pop_back();
 | 
			
		||||
            if (s.length() == 1) {
 | 
			
		||||
                m_rhs.pop_back();
 | 
			
		||||
                rs.pop_back();
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                expr_ref s2(m_util.str.mk_string(s.extract(0, s.length()-2)), m());
 | 
			
		||||
                m_rhs[m_rhs.size()-1] = s2;
 | 
			
		||||
                trail.push_back(s2);
 | 
			
		||||
                rs[rs.size()-1] = s2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
| 
						 | 
				
			
			@ -587,22 +907,22 @@ bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_ve
 | 
			
		|||
    // solve from front
 | 
			
		||||
    unsigned head1 = 0, head2 = 0;
 | 
			
		||||
    while (true) {
 | 
			
		||||
        while (head1 < m_lhs.size() && m_util.str.is_empty(m_lhs[head1])) {
 | 
			
		||||
        while (head1 < ls.size() && m_util.str.is_empty(ls[head1].get())) {
 | 
			
		||||
            ++head1;
 | 
			
		||||
        }
 | 
			
		||||
        while (head2 < m_rhs.size() && m_util.str.is_empty(m_rhs[head2])) {
 | 
			
		||||
        while (head2 < rs.size() && m_util.str.is_empty(rs[head2].get())) {
 | 
			
		||||
            ++head2;
 | 
			
		||||
        }
 | 
			
		||||
        if (head1 == m_lhs.size() || head2 == m_rhs.size()) {
 | 
			
		||||
        if (head1 == ls.size() || head2 == rs.size()) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        SASSERT(head1 < m_lhs.size() && head2 < m_rhs.size());
 | 
			
		||||
        SASSERT(head1 < ls.size() && head2 < rs.size());
 | 
			
		||||
 | 
			
		||||
        expr* l = m_lhs[head1];
 | 
			
		||||
        expr* r = m_rhs[head2];
 | 
			
		||||
        expr* l = ls[head1].get();
 | 
			
		||||
        expr* r = rs[head2].get();
 | 
			
		||||
        if (m_util.str.is_unit(r) && m_util.str.is_string(l)) {
 | 
			
		||||
            std::swap(l, r);
 | 
			
		||||
            std::swap(m_lhs, m_rhs);
 | 
			
		||||
            ls.swap(rs);
 | 
			
		||||
        }
 | 
			
		||||
        if (l == r) {
 | 
			
		||||
            ++head1;
 | 
			
		||||
| 
						 | 
				
			
			@ -624,14 +944,13 @@ bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_ve
 | 
			
		|||
            SASSERT(m().get_sort(ch) == m().get_sort(a));
 | 
			
		||||
            lhs.push_back(ch);
 | 
			
		||||
            rhs.push_back(a);
 | 
			
		||||
            m_lhs.pop_back();
 | 
			
		||||
            ls.pop_back();
 | 
			
		||||
            if (s.length() == 1) {
 | 
			
		||||
                m_rhs.pop_back();
 | 
			
		||||
                rs.pop_back();
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                expr_ref s2(m_util.str.mk_string(s.extract(1, s.length()-1)), m());
 | 
			
		||||
                m_rhs[m_rhs.size()-1] = s2;
 | 
			
		||||
                trail.push_back(s2);
 | 
			
		||||
                rs[rs.size()-1] = s2;
 | 
			
		||||
            }            
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
| 
						 | 
				
			
			@ -641,10 +960,10 @@ bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_ve
 | 
			
		|||
    }
 | 
			
		||||
    // reduce strings
 | 
			
		||||
    zstring s1, s2;
 | 
			
		||||
    while (head1 < m_lhs.size() && 
 | 
			
		||||
           head2 < m_rhs.size() && 
 | 
			
		||||
           m_util.str.is_string(m_lhs[head1], s1) &&
 | 
			
		||||
           m_util.str.is_string(m_rhs[head2], s2)) {
 | 
			
		||||
    while (head1 < ls.size() && 
 | 
			
		||||
           head2 < rs.size() && 
 | 
			
		||||
           m_util.str.is_string(ls[head1].get(), s1) &&
 | 
			
		||||
           m_util.str.is_string(rs[head2].get(), s2)) {
 | 
			
		||||
        unsigned l = std::min(s1.length(), s2.length());
 | 
			
		||||
        for (unsigned i = 0; i < l; ++i) {
 | 
			
		||||
            if (s1[i] != s2[i]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -655,68 +974,88 @@ bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_ve
 | 
			
		|||
            ++head1;            
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            m_lhs[head1] = m_util.str.mk_string(s1.extract(l, s1.length()-l));
 | 
			
		||||
            trail.push_back(m_lhs[head1]);
 | 
			
		||||
            ls[head1] = m_util.str.mk_string(s1.extract(l, s1.length()-l));
 | 
			
		||||
        }
 | 
			
		||||
        if (l == s2.length()) {
 | 
			
		||||
            ++head2;            
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            m_rhs[head2] = m_util.str.mk_string(s2.extract(l, s2.length()-l));
 | 
			
		||||
            trail.push_back(m_rhs[head2]);
 | 
			
		||||
            rs[head2] = m_util.str.mk_string(s2.extract(l, s2.length()-l));
 | 
			
		||||
        }
 | 
			
		||||
        change = true;
 | 
			
		||||
    }
 | 
			
		||||
    while (head1 < m_lhs.size() && 
 | 
			
		||||
           head2 < m_rhs.size() &&
 | 
			
		||||
           m_util.str.is_string(m_lhs.back(), s1) &&
 | 
			
		||||
           m_util.str.is_string(m_rhs.back(), s2)) {
 | 
			
		||||
    while (head1 < ls.size() && 
 | 
			
		||||
           head2 < rs.size() &&
 | 
			
		||||
           m_util.str.is_string(ls.back(), s1) &&
 | 
			
		||||
           m_util.str.is_string(rs.back(), s2)) {
 | 
			
		||||
        unsigned l = std::min(s1.length(), s2.length());
 | 
			
		||||
        for (unsigned i = 0; i < l; ++i) {
 | 
			
		||||
            if (s1[s1.length()-i-1] != s2[s2.length()-i-1]) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        m_lhs.pop_back();          
 | 
			
		||||
        m_rhs.pop_back();
 | 
			
		||||
        ls.pop_back();          
 | 
			
		||||
        rs.pop_back();
 | 
			
		||||
        if (l < s1.length()) {
 | 
			
		||||
            m_lhs.push_back(m_util.str.mk_string(s1.extract(0, s1.length()-l)));
 | 
			
		||||
            trail.push_back(m_lhs.back());
 | 
			
		||||
            ls.push_back(m_util.str.mk_string(s1.extract(0, s1.length()-l)));
 | 
			
		||||
        }
 | 
			
		||||
        if (l < s2.length()) {
 | 
			
		||||
            m_rhs.push_back(m_util.str.mk_string(s2.extract(0, s2.length()-l)));
 | 
			
		||||
            trail.push_back(m_rhs.back());
 | 
			
		||||
            rs.push_back(m_util.str.mk_string(s2.extract(0, s2.length()-l)));
 | 
			
		||||
        }        
 | 
			
		||||
        change = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_sat;
 | 
			
		||||
    unsigned szl = m_lhs.size() - head1, szr = m_rhs.size() - head2;
 | 
			
		||||
    expr* const* ls = m_lhs.c_ptr() + head1, * const*rs = m_rhs.c_ptr() + head2;
 | 
			
		||||
    if (length_constrained(szl, ls, szr, rs, lhs, rhs, is_sat)) {
 | 
			
		||||
    unsigned szl = ls.size() - head1, szr = rs.size() - head2;
 | 
			
		||||
    expr* const* _ls = ls.c_ptr() + head1, * const* _rs = rs.c_ptr() + head2;
 | 
			
		||||
    if (length_constrained(szl, _ls, szr, _rs, lhs, rhs, is_sat)) {
 | 
			
		||||
        ls.reset(); rs.reset();
 | 
			
		||||
        return is_sat;
 | 
			
		||||
    }
 | 
			
		||||
    if (is_subsequence(szl, ls, szr, rs, lhs, rhs, is_sat)) {
 | 
			
		||||
    if (is_subsequence(szl, _ls, szr, _rs, lhs, rhs, is_sat)) {
 | 
			
		||||
        ls.reset(); rs.reset();
 | 
			
		||||
        return is_sat;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	if (szl == 0 && szr == 0) {
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
    if (szl == 0 && szr == 0) {
 | 
			
		||||
        ls.reset(); rs.reset();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else if (!change) {
 | 
			
		||||
        lhs.push_back(l);
 | 
			
		||||
        rhs.push_back(r);
 | 
			
		||||
        // skip
 | 
			
		||||
        SASSERT(lhs.empty());
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        // could solve if either side is fixed size.
 | 
			
		||||
        SASSERT(szl > 0 && szr > 0);
 | 
			
		||||
 | 
			
		||||
        lhs.push_back(m_util.str.mk_concat(szl, ls));
 | 
			
		||||
        rhs.push_back(m_util.str.mk_concat(szr, rs));
 | 
			
		||||
        lhs.push_back(m_util.str.mk_concat(szl, ls.c_ptr() + head1));
 | 
			
		||||
        rhs.push_back(m_util.str.mk_concat(szr, rs.c_ptr() + head2));
 | 
			
		||||
        ls.reset();
 | 
			
		||||
        rs.reset();
 | 
			
		||||
    }
 | 
			
		||||
    SASSERT(lhs.empty() || ls.empty());
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_vector& rhs) {
 | 
			
		||||
    m_lhs.reset();
 | 
			
		||||
    m_rhs.reset();
 | 
			
		||||
    m_util.str.get_concat(l, m_lhs);
 | 
			
		||||
    m_util.str.get_concat(r, m_rhs);
 | 
			
		||||
    if (reduce_eq(m_lhs, m_rhs, lhs, rhs)) {
 | 
			
		||||
        SASSERT(lhs.size() == rhs.size());
 | 
			
		||||
        if (lhs.empty()) {
 | 
			
		||||
            lhs.push_back(l);
 | 
			
		||||
            rhs.push_back(r);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        TRACE("seq", tout << mk_pp(l, m()) << " != " << mk_pp(r, m()) << "\n";);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr* seq_rewriter::concat_non_empty(unsigned n, expr* const* as) {
 | 
			
		||||
    SASSERT(n > 0);
 | 
			
		||||
    ptr_vector<expr> bs;
 | 
			
		||||
| 
						 | 
				
			
			@ -812,6 +1151,11 @@ bool seq_rewriter::length_constrained(unsigned szl, expr* const* l, unsigned szr
 | 
			
		|||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool seq_rewriter::is_epsilon(expr* e) const {
 | 
			
		||||
    expr* e1;
 | 
			
		||||
    return m_util.re.is_to_re(e, e1) && m_util.str.is_empty(e1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool seq_rewriter::is_subsequence(unsigned szl, expr* const* l, unsigned szr, expr* const* r, 
 | 
			
		||||
                                  expr_ref_vector& lhs, expr_ref_vector& rhs, bool& is_sat) {
 | 
			
		||||
    is_sat = true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,15 +24,27 @@ Notes:
 | 
			
		|||
#include"rewriter_types.h"
 | 
			
		||||
#include"params.h"
 | 
			
		||||
#include"lbool.h"
 | 
			
		||||
#include"automaton.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef automaton<expr, ast_manager> eautomaton;
 | 
			
		||||
class re2automaton {
 | 
			
		||||
    ast_manager& m;
 | 
			
		||||
    seq_util     u;       
 | 
			
		||||
    eautomaton* re2aut(expr* e);
 | 
			
		||||
    eautomaton* seq2aut(expr* e);
 | 
			
		||||
 public:
 | 
			
		||||
    re2automaton(ast_manager& m);
 | 
			
		||||
    eautomaton* operator()(expr* e);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   \brief Cheap rewrite rules for seq constraints
 | 
			
		||||
*/
 | 
			
		||||
class seq_rewriter {
 | 
			
		||||
    seq_util       m_util;
 | 
			
		||||
    arith_util     m_autil;
 | 
			
		||||
    ptr_vector<expr> m_es, m_lhs, m_rhs;
 | 
			
		||||
    expr_ref_vector m_es, m_lhs, m_rhs;
 | 
			
		||||
 | 
			
		||||
    br_status mk_seq_concat(expr* a, expr* b, expr_ref& result);
 | 
			
		||||
    br_status mk_seq_length(expr* a, expr_ref& result);
 | 
			
		||||
| 
						 | 
				
			
			@ -61,9 +73,13 @@ class seq_rewriter {
 | 
			
		|||
    bool min_length(unsigned n, expr* const* es, unsigned& len);
 | 
			
		||||
    expr* concat_non_empty(unsigned n, expr* const* es);
 | 
			
		||||
 | 
			
		||||
    void add_next(u_map<expr*>& next, unsigned idx, expr* cond);
 | 
			
		||||
    bool is_sequence(expr* e, expr_ref_vector& seq);
 | 
			
		||||
    bool is_epsilon(expr* e) const;
 | 
			
		||||
 | 
			
		||||
public:    
 | 
			
		||||
    seq_rewriter(ast_manager & m, params_ref const & p = params_ref()):
 | 
			
		||||
        m_util(m), m_autil(m) {
 | 
			
		||||
        m_util(m), m_autil(m), m_es(m), m_lhs(m), m_rhs(m) {
 | 
			
		||||
    }
 | 
			
		||||
    ast_manager & m() const { return m_util.get_manager(); }
 | 
			
		||||
    family_id get_fid() const { return m_util.get_family_id(); }
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +92,8 @@ public:
 | 
			
		|||
 | 
			
		||||
    bool reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_vector& rhs);
 | 
			
		||||
 | 
			
		||||
    bool reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_vector& lhs, expr_ref_vector& rhs);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,6 @@ Revision History:
 | 
			
		|||
zstring::zstring(encoding enc): m_encoding(enc) {}
 | 
			
		||||
 | 
			
		||||
zstring::zstring(char const* s, encoding enc): m_encoding(enc) {
 | 
			
		||||
    // TBD: epply decoding
 | 
			
		||||
    while (*s) {
 | 
			
		||||
        m_buffer.push_back(*s);
 | 
			
		||||
        ++s;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +41,7 @@ zstring::zstring(unsigned num_bits, bool const* ch) {
 | 
			
		|||
    m_encoding = (num_bits == 8)?ascii:unicode;
 | 
			
		||||
    unsigned n = 0;    
 | 
			
		||||
    for (unsigned i = 0; i < num_bits; ++i) {
 | 
			
		||||
        n |= (((unsigned)ch[i]) << num_bits);
 | 
			
		||||
        n |= (((unsigned)ch[i]) << i);
 | 
			
		||||
    }
 | 
			
		||||
    m_buffer.push_back(n);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -81,12 +80,24 @@ zstring zstring::replace(zstring const& src, zstring const& dst) const {
 | 
			
		|||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char esc_table[32][3] =
 | 
			
		||||
    { "\\0", "^A", "^B", "^C", "^D", "^E", "^F", "\\a", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "^N",
 | 
			
		||||
      "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V","^W","^X","^Y","^Z","\\e","^\\","^]","^^","^_"};
 | 
			
		||||
 
 | 
			
		||||
std::string zstring::encode() const {
 | 
			
		||||
    // TBD apply encodings.
 | 
			
		||||
    SASSERT(m_encoding == ascii);
 | 
			
		||||
    std::ostringstream strm;
 | 
			
		||||
    for (unsigned i = 0; i < m_buffer.size(); ++i) {
 | 
			
		||||
        strm << (char)(m_buffer[i]);
 | 
			
		||||
        unsigned char ch = m_buffer[i];
 | 
			
		||||
        if (0 <= ch && ch < 32) {
 | 
			
		||||
            strm << esc_table[ch];
 | 
			
		||||
        }
 | 
			
		||||
        else if (ch == 127) {
 | 
			
		||||
            strm << "^?";
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            strm << (char)(ch);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return strm.str();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -163,6 +174,7 @@ std::ostream& zstring::operator<<(std::ostream& out) const {
 | 
			
		|||
 | 
			
		||||
seq_decl_plugin::seq_decl_plugin(): m_init(false), 
 | 
			
		||||
                                    m_stringc_sym("String"),
 | 
			
		||||
                                    m_charc_sym("Char"),
 | 
			
		||||
                                    m_string(0),
 | 
			
		||||
                                    m_char(0) {}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -211,9 +223,9 @@ bool seq_decl_plugin::match(ptr_vector<sort>& binding, sort* s, sort* sP) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  \brief match left associative operator.
 | 
			
		||||
  \brief match right associative operator.
 | 
			
		||||
*/
 | 
			
		||||
void seq_decl_plugin::match_left_assoc(psig& sig, unsigned dsz, sort *const* dom, sort* range, sort_ref& range_out) {
 | 
			
		||||
void seq_decl_plugin::match_right_assoc(psig& sig, unsigned dsz, sort *const* dom, sort* range, sort_ref& range_out) {
 | 
			
		||||
    ptr_vector<sort> binding;
 | 
			
		||||
    ast_manager& m = *m_manager;
 | 
			
		||||
    TRACE("seq_verbose", 
 | 
			
		||||
| 
						 | 
				
			
			@ -369,7 +381,8 @@ void seq_decl_plugin::init() {
 | 
			
		|||
 | 
			
		||||
void seq_decl_plugin::set_manager(ast_manager* m, family_id id) {
 | 
			
		||||
    decl_plugin::set_manager(m, id);
 | 
			
		||||
    m_char = m->mk_sort(symbol("Char"), sort_info(m_family_id, _CHAR_SORT, 0, (parameter const*)0));
 | 
			
		||||
    bv_util bv(*m);
 | 
			
		||||
    m_char = bv.mk_sort(8);
 | 
			
		||||
    m->inc_ref(m_char);
 | 
			
		||||
    parameter param(m_char);
 | 
			
		||||
    m_string = m->mk_sort(symbol("String"), sort_info(m_family_id, SEQ_SORT, 1, ¶m));
 | 
			
		||||
| 
						 | 
				
			
			@ -391,18 +404,18 @@ sort * seq_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter
 | 
			
		|||
            return m_string;
 | 
			
		||||
        }
 | 
			
		||||
        return m.mk_sort(symbol("Seq"), sort_info(m_family_id, SEQ_SORT, num_parameters, parameters));
 | 
			
		||||
    case RE_SORT:
 | 
			
		||||
    case RE_SORT: {
 | 
			
		||||
        if (num_parameters != 1) {
 | 
			
		||||
            m.raise_exception("Invalid regex sort, expecting one parameter");
 | 
			
		||||
        }
 | 
			
		||||
        if (!parameters[0].is_ast() || !is_sort(parameters[0].get_ast())) {
 | 
			
		||||
            m.raise_exception("invalid regex sort, parameter is not a sort");
 | 
			
		||||
        }
 | 
			
		||||
        sort * s = to_sort(parameters[0].get_ast());
 | 
			
		||||
        return m.mk_sort(symbol("RegEx"), sort_info(m_family_id, RE_SORT, num_parameters, parameters));
 | 
			
		||||
    }
 | 
			
		||||
    case _STRING_SORT:
 | 
			
		||||
        return m_string;
 | 
			
		||||
    case _CHAR_SORT:
 | 
			
		||||
        return m_char;
 | 
			
		||||
    default:
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
        return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -430,9 +443,9 @@ func_decl* seq_decl_plugin::mk_assoc_fun(decl_kind k, unsigned arity, sort* cons
 | 
			
		|||
    if (arity == 0) {
 | 
			
		||||
        m.raise_exception("Invalid function application. At least one argument expected");
 | 
			
		||||
    }
 | 
			
		||||
    match_left_assoc(*m_sigs[k], arity, domain, range, rng);
 | 
			
		||||
    match_right_assoc(*m_sigs[k], arity, domain, range, rng);
 | 
			
		||||
    func_decl_info info(m_family_id, k_seq);
 | 
			
		||||
    info.set_left_associative();
 | 
			
		||||
    info.set_right_associative();
 | 
			
		||||
    return m.mk_func_decl(m_sigs[(rng == m_string)?k_string:k_seq]->m_name, rng, rng, rng, info);    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -470,6 +483,8 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
 | 
			
		|||
        }
 | 
			
		||||
        return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, k, num_parameters, parameters));   
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    case OP_STRING_CONST:
 | 
			
		||||
        if (!(num_parameters == 1 && arity == 0 && parameters[0].is_symbol())) {
 | 
			
		||||
            m.raise_exception("invalid string declaration");
 | 
			
		||||
| 
						 | 
				
			
			@ -583,7 +598,7 @@ void seq_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbol
 | 
			
		|||
app* seq_decl_plugin::mk_string(symbol const& s) {
 | 
			
		||||
    parameter param(s);
 | 
			
		||||
    func_decl* f = m_manager->mk_const_decl(m_stringc_sym, m_string,
 | 
			
		||||
                                   func_decl_info(m_family_id, OP_STRING_CONST, 1, ¶m));
 | 
			
		||||
                                            func_decl_info(m_family_id, OP_STRING_CONST, 1, ¶m));
 | 
			
		||||
    return m_manager->mk_const(f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -591,12 +606,16 @@ app* seq_decl_plugin::mk_string(zstring const& s) {
 | 
			
		|||
    symbol sym(s.encode().c_str());
 | 
			
		||||
    parameter param(sym);
 | 
			
		||||
    func_decl* f = m_manager->mk_const_decl(m_stringc_sym, m_string,
 | 
			
		||||
                                   func_decl_info(m_family_id, OP_STRING_CONST, 1, ¶m));
 | 
			
		||||
                                            func_decl_info(m_family_id, OP_STRING_CONST, 1, ¶m));
 | 
			
		||||
    return m_manager->mk_const(f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool seq_decl_plugin::is_value(app* e) const {
 | 
			
		||||
    return is_app_of(e, m_family_id, OP_STRING_CONST);
 | 
			
		||||
    return 
 | 
			
		||||
        is_app_of(e, m_family_id, OP_SEQ_EMPTY) || 
 | 
			
		||||
        (is_app_of(e, m_family_id, OP_SEQ_UNIT) &&
 | 
			
		||||
         m_manager->is_value(e->get_arg(0)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
app* seq_util::mk_skolem(symbol const& name, unsigned n, expr* const* args, sort* range) {
 | 
			
		||||
| 
						 | 
				
			
			@ -609,11 +628,26 @@ app* seq_util::mk_skolem(symbol const& name, unsigned n, expr* const* args, sort
 | 
			
		|||
app* seq_util::str::mk_string(zstring const& s) { return u.seq.mk_string(s); }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
app*  seq_util::str::mk_char(zstring const& s, unsigned idx) {
 | 
			
		||||
    bv_util bvu(m);
 | 
			
		||||
    return bvu.mk_numeral(s[idx], s.num_bits());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
app*  seq_util::str::mk_char(char ch) {
 | 
			
		||||
    zstring s(ch, zstring::ascii);
 | 
			
		||||
    return mk_char(s, 0);
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
bool seq_util::str::is_char(expr* n, zstring& c) const {
 | 
			
		||||
    if (u.is_char(n)) {
 | 
			
		||||
        c = zstring(to_app(n)->get_decl()->get_parameter(0).get_symbol().bare_str());
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool seq_util::str::is_string(expr const* n, zstring& s) const {
 | 
			
		||||
    if (is_string(n)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -626,7 +660,7 @@ bool seq_util::str::is_string(expr const* n, zstring& s) const {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void seq_util::str::get_concat(expr* e, ptr_vector<expr>& es) const {
 | 
			
		||||
void seq_util::str::get_concat(expr* e, expr_ref_vector& es) const {
 | 
			
		||||
    expr* e1, *e2;
 | 
			
		||||
    while (is_concat(e, e1, e2)) {
 | 
			
		||||
        get_concat(e1, es);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,13 +22,13 @@ Revision History:
 | 
			
		|||
#define SEQ_DECL_PLUGIN_H_
 | 
			
		||||
 | 
			
		||||
#include "ast.h"
 | 
			
		||||
#include "bv_decl_plugin.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
enum seq_sort_kind {
 | 
			
		||||
    SEQ_SORT,
 | 
			
		||||
    RE_SORT,
 | 
			
		||||
    _STRING_SORT,  // internal only
 | 
			
		||||
    _CHAR_SORT     // internal only
 | 
			
		||||
    _STRING_SORT  // internal only
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum seq_op_kind {
 | 
			
		||||
| 
						 | 
				
			
			@ -131,12 +131,13 @@ class seq_decl_plugin : public decl_plugin {
 | 
			
		|||
    ptr_vector<psig> m_sigs;
 | 
			
		||||
    bool             m_init;
 | 
			
		||||
    symbol           m_stringc_sym;
 | 
			
		||||
    symbol           m_charc_sym;
 | 
			
		||||
    sort*            m_string;
 | 
			
		||||
    sort*            m_char;
 | 
			
		||||
 | 
			
		||||
    void match(psig& sig, unsigned dsz, sort* const* dom, sort* range, sort_ref& rng);
 | 
			
		||||
 | 
			
		||||
    void match_left_assoc(psig& sig, unsigned dsz, sort* const* dom, sort* range, sort_ref& rng);
 | 
			
		||||
    void match_right_assoc(psig& sig, unsigned dsz, sort* const* dom, sort* range, sort_ref& rng);
 | 
			
		||||
 | 
			
		||||
    bool match(ptr_vector<sort>& binding, sort* s, sort* sP);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -187,6 +188,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    ast_manager& get_manager() const { return m; }
 | 
			
		||||
 | 
			
		||||
    bool is_char(sort* s) const { return seq.is_char(s); }
 | 
			
		||||
    bool is_string(sort* s) const { return is_seq(s) && seq.is_char(s->get_parameter(0).get_ast()); }
 | 
			
		||||
    bool is_seq(sort* s) const { return is_sort_of(s, m_fid, SEQ_SORT); }
 | 
			
		||||
    bool is_re(sort* s) const { return is_sort_of(s, m_fid, RE_SORT); }
 | 
			
		||||
| 
						 | 
				
			
			@ -195,6 +197,7 @@ public:
 | 
			
		|||
    bool is_seq(sort* s, sort*& seq) { return is_seq(s) && (seq = to_sort(s->get_parameter(0).get_ast()), true); }
 | 
			
		||||
    bool is_re(expr* e) const { return is_re(m.get_sort(e)); }
 | 
			
		||||
    bool is_re(expr* e, sort*& seq) const { return is_re(m.get_sort(e), seq); }
 | 
			
		||||
    bool is_char(expr* e) const { return is_char(m.get_sort(e)); }
 | 
			
		||||
 | 
			
		||||
    app* mk_skolem(symbol const& name, unsigned n, expr* const* args, sort* range);
 | 
			
		||||
    bool is_skolem(expr const* e) const { return is_app_of(e, m_fid, _OP_SEQ_SKOLEM); }
 | 
			
		||||
| 
						 | 
				
			
			@ -212,13 +215,13 @@ public:
 | 
			
		|||
        str(seq_util& u): u(u), m(u.m), m_fid(u.m_fid) {}
 | 
			
		||||
 | 
			
		||||
        sort* mk_seq(sort* s) { parameter param(s); return m.mk_sort(m_fid, SEQ_SORT, 1, ¶m); }
 | 
			
		||||
        sort* mk_string_sort() { return m.mk_sort(m_fid, _STRING_SORT, 0, 0); }
 | 
			
		||||
        app* mk_empty(sort* s) { return m.mk_const(m.mk_func_decl(m_fid, OP_SEQ_EMPTY, 0, 0, 0, (expr*const*)0, s)); }
 | 
			
		||||
        app* mk_string(zstring const& s);
 | 
			
		||||
        app* mk_string(symbol const& s) { return u.seq.mk_string(s); }
 | 
			
		||||
        app* mk_char(char ch);
 | 
			
		||||
        app* mk_concat(expr* a, expr* b) { expr* es[2] = { a, b }; return m.mk_app(m_fid, OP_SEQ_CONCAT, 2, es); }
 | 
			
		||||
        app* mk_concat(expr* a, expr* b, expr* c) {
 | 
			
		||||
            return mk_concat(mk_concat(a, b), c);
 | 
			
		||||
        }
 | 
			
		||||
        app* mk_concat(expr* a, expr* b, expr* c) { return mk_concat(a, mk_concat(b, c)); }
 | 
			
		||||
        expr* mk_concat(unsigned n, expr* const* es) { if (n == 1) return es[0]; SASSERT(n > 1); return m.mk_app(m_fid, OP_SEQ_CONCAT, n, es); }
 | 
			
		||||
        app* mk_length(expr* a) { return m.mk_app(m_fid, OP_SEQ_LENGTH, 1, &a); }
 | 
			
		||||
        app* mk_substr(expr* a, expr* b, expr* c) { expr* es[3] = { a, b, c }; return m.mk_app(m_fid, OP_SEQ_EXTRACT, 3, es); }
 | 
			
		||||
| 
						 | 
				
			
			@ -229,8 +232,6 @@ public:
 | 
			
		|||
        app* mk_unit(expr* u) { return m.mk_app(m_fid, OP_SEQ_UNIT, 1, &u); }
 | 
			
		||||
        app* mk_char(zstring const& s, unsigned idx);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        bool is_string(expr const * n) const { return is_app_of(n, m_fid, OP_STRING_CONST); }
 | 
			
		||||
 | 
			
		||||
        bool is_string(expr const* n, symbol& s) const {
 | 
			
		||||
| 
						 | 
				
			
			@ -238,6 +239,7 @@ public:
 | 
			
		|||
        }
 | 
			
		||||
        
 | 
			
		||||
        bool is_string(expr const* n, zstring& s) const;
 | 
			
		||||
        bool is_char(expr* n, zstring& s) const;
 | 
			
		||||
 | 
			
		||||
        bool is_empty(expr const* n) const { symbol s; 
 | 
			
		||||
            return is_app_of(n, m_fid, OP_SEQ_EMPTY) || (is_string(n, s) && !s.is_numerical() && *s.bare_str() == 0); 
 | 
			
		||||
| 
						 | 
				
			
			@ -271,8 +273,9 @@ public:
 | 
			
		|||
        MATCH_BINARY(is_in_re);        
 | 
			
		||||
        MATCH_UNARY(is_unit);
 | 
			
		||||
 | 
			
		||||
        void get_concat(expr* e, ptr_vector<expr>& es) const;
 | 
			
		||||
        void get_concat(expr* e, expr_ref_vector& es) const;
 | 
			
		||||
        expr* get_leftmost_concat(expr* e) const { expr* e1, *e2; while (is_concat(e, e1, e2)) e = e1; return e; }
 | 
			
		||||
        expr* get_rightmost_concat(expr* e) const { expr* e1, *e2; while (is_concat(e, e1, e2)) e = e2; return e; }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class re {
 | 
			
		||||
| 
						 | 
				
			
			@ -281,6 +284,8 @@ public:
 | 
			
		|||
    public:
 | 
			
		||||
        re(seq_util& u): m(u.m), m_fid(u.m_fid) {}
 | 
			
		||||
 | 
			
		||||
        sort* mk_re(sort* seq) { parameter param(seq); return m.mk_sort(m_fid, RE_SORT, 1, ¶m); }
 | 
			
		||||
 | 
			
		||||
        app* mk_to_re(expr* s) { return m.mk_app(m_fid, OP_SEQ_TO_RE, 1, &s); }
 | 
			
		||||
        app* mk_in_re(expr* s, expr* r) { return m.mk_app(m_fid, OP_SEQ_IN_RE, s, r); }
 | 
			
		||||
        app* mk_concat(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_CONCAT, r1, r2); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,6 +110,7 @@ void elim_bounds::operator()(quantifier * q, expr_ref & r) {
 | 
			
		|||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    expr * n = q->get_expr();
 | 
			
		||||
    unsigned num_vars = q->get_num_decls();
 | 
			
		||||
    ptr_buffer<expr> atoms;
 | 
			
		||||
    if (m_manager.is_or(n))
 | 
			
		||||
        atoms.append(to_app(n)->get_num_args(), to_app(n)->get_args());
 | 
			
		||||
| 
						 | 
				
			
			@ -138,11 +139,11 @@ void elim_bounds::operator()(quantifier * q, expr_ref & r) {
 | 
			
		|||
        var * lower = 0;
 | 
			
		||||
        var * upper = 0;
 | 
			
		||||
        if (is_bound(a, lower, upper)) {
 | 
			
		||||
            if (lower != 0 && !m_used_vars.contains(lower->get_idx())) {
 | 
			
		||||
            if (lower != 0 && !m_used_vars.contains(lower->get_idx()) && lower->get_idx() < num_vars) {
 | 
			
		||||
                ADD_CANDIDATE(lower);
 | 
			
		||||
                m_lowers.insert(lower);
 | 
			
		||||
            }
 | 
			
		||||
            if (upper != 0 && !m_used_vars.contains(upper->get_idx())) {
 | 
			
		||||
            if (upper != 0 && !m_used_vars.contains(upper->get_idx()) && upper->get_idx() < num_vars) {
 | 
			
		||||
                ADD_CANDIDATE(upper);
 | 
			
		||||
                m_uppers.insert(upper);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -176,6 +177,7 @@ void elim_bounds::operator()(quantifier * q, expr_ref & r) {
 | 
			
		|||
    switch (atoms.size()) {
 | 
			
		||||
    case 0:
 | 
			
		||||
        r = m_manager.mk_false();
 | 
			
		||||
        TRACE("elim_bounds", tout << mk_pp(q, m_manager) << "\n" << mk_pp(r, m_manager) << "\n";);
 | 
			
		||||
        return;
 | 
			
		||||
    case 1:
 | 
			
		||||
        new_body = atoms[0];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,6 @@
 | 
			
		|||
#pragma warning(disable:4101)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2023,8 +2023,8 @@ public:
 | 
			
		|||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
                pfgoto(proof);
 | 
			
		||||
                assert(0 && "translate_main: unsupported proof rule");
 | 
			
		||||
                //                pfgoto(proof);                
 | 
			
		||||
                // SASSERT(0 && "translate_main: unsupported proof rule");
 | 
			
		||||
                throw unsupported();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										23
									
								
								src/math/automata/automaton.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/math/automata/automaton.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2015 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    automaton.cpp
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Symbolic Automaton, a la Margus Veanes Automata library.
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Nikolaj Bjorner (nbjorner) 2015-12-23.
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
#include "automaton.h"
 | 
			
		||||
 | 
			
		||||
template class automaton<unsigned>;
 | 
			
		||||
							
								
								
									
										608
									
								
								src/math/automata/automaton.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										608
									
								
								src/math/automata/automaton.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,608 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2015 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    automaton.h
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Symbolic Automaton, a la Margus Veanes Automata library.
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Nikolaj Bjorner (nbjorner) 2015-12-23.
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
#ifndef AUTOMATON_H_
 | 
			
		||||
#define AUTOMATON_H_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "vector.h"
 | 
			
		||||
#include "uint_set.h"
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
class default_value_manager {
 | 
			
		||||
public:
 | 
			
		||||
    void inc_ref(T* t) {}
 | 
			
		||||
    void dec_ref(T* t) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class T, class M = default_value_manager<T> >
 | 
			
		||||
class automaton {
 | 
			
		||||
public:
 | 
			
		||||
    class move {
 | 
			
		||||
        M&       m;
 | 
			
		||||
        T*       m_t;
 | 
			
		||||
        unsigned m_src;
 | 
			
		||||
        unsigned m_dst;        
 | 
			
		||||
    public:
 | 
			
		||||
        move(M& m, unsigned s, unsigned d, T* t = 0): m(m), m_t(t), m_src(s), m_dst(d) {
 | 
			
		||||
            if (t) m.inc_ref(t);
 | 
			
		||||
        }
 | 
			
		||||
        ~move() {
 | 
			
		||||
            if (m_t) m.dec_ref(m_t);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        move(move const& other): m(other.m), m_t(other.m_t), m_src(other.m_src), m_dst(other.m_dst) {
 | 
			
		||||
            if (m_t) m.inc_ref(m_t);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        move& operator=(move const& other) {
 | 
			
		||||
            SASSERT(&m == &other.m);
 | 
			
		||||
            T* t = other.m_t;
 | 
			
		||||
            if (t) m.inc_ref(t);
 | 
			
		||||
            if (m_t) m.dec_ref(m_t);
 | 
			
		||||
            m_t = t;
 | 
			
		||||
            m_src = other.m_src;
 | 
			
		||||
            m_dst = other.m_dst;
 | 
			
		||||
            return *this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        unsigned dst() const { return m_dst; }
 | 
			
		||||
        unsigned src() const { return m_src; }
 | 
			
		||||
        T* t() const { return m_t; }
 | 
			
		||||
 | 
			
		||||
        bool is_epsilon() const { return m_t == 0; }
 | 
			
		||||
    };
 | 
			
		||||
    typedef vector<move> moves;
 | 
			
		||||
private:
 | 
			
		||||
    M&              m;
 | 
			
		||||
    vector<moves>   m_delta;
 | 
			
		||||
    vector<moves>   m_delta_inv;
 | 
			
		||||
    unsigned        m_init;
 | 
			
		||||
    uint_set        m_final_set;
 | 
			
		||||
    unsigned_vector m_final_states;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // local data-structures
 | 
			
		||||
    mutable uint_set        m_visited;
 | 
			
		||||
    mutable unsigned_vector m_todo;
 | 
			
		||||
 | 
			
		||||
    struct default_display {
 | 
			
		||||
        std::ostream& display(std::ostream& out, T* t) {
 | 
			
		||||
            return out << t;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    // The empty automaton:
 | 
			
		||||
    automaton(M& m):
 | 
			
		||||
        m(m), 
 | 
			
		||||
        m_init(0)
 | 
			
		||||
    {
 | 
			
		||||
        m_delta.push_back(moves());
 | 
			
		||||
        m_delta_inv.push_back(moves());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // create an automaton from initial state, final states, and moves
 | 
			
		||||
    automaton(M& m, unsigned init, unsigned_vector const& final, moves const& mvs): m(m) {
 | 
			
		||||
        m_init = init;
 | 
			
		||||
        for (unsigned i = 0; i < final.size(); ++i) {
 | 
			
		||||
            add_to_final_states(final[i]);
 | 
			
		||||
        }
 | 
			
		||||
        for (unsigned i = 0; i < mvs.size(); ++i) {
 | 
			
		||||
            move const& mv = mvs[i];
 | 
			
		||||
            unsigned n = std::max(mv.src(), mv.dst());
 | 
			
		||||
            if (n >= m_delta.size()) {
 | 
			
		||||
                m_delta.resize(n+1, moves());
 | 
			
		||||
                m_delta_inv.resize(n+1, moves());
 | 
			
		||||
            }
 | 
			
		||||
            add(mv);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // create an automaton that accepts a sequence.
 | 
			
		||||
    automaton(M& m, ptr_vector<T> const& seq):
 | 
			
		||||
        m(m),
 | 
			
		||||
        m_init(0) {
 | 
			
		||||
        m_delta.resize(seq.size()+1, moves());
 | 
			
		||||
        m_delta_inv.resize(seq.size()+1, moves());
 | 
			
		||||
        for (unsigned i = 0; i < seq.size(); ++i) {
 | 
			
		||||
            m_delta[i].push_back(move(m, i, i + 1, seq[i]));
 | 
			
		||||
            m_delta[i + 1].push_back(move(m, i, i + 1, seq[i]));
 | 
			
		||||
        }
 | 
			
		||||
        add_to_final_states(seq.size());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // The automaton that accepts t
 | 
			
		||||
    automaton(M& m, T* t):
 | 
			
		||||
        m(m), 
 | 
			
		||||
        m_init(0) {
 | 
			
		||||
        m_delta.resize(2, moves());
 | 
			
		||||
        m_delta_inv.resize(2, moves());
 | 
			
		||||
        add_to_final_states(1);
 | 
			
		||||
        add(move(m, 0, 1, t));
 | 
			
		||||
    }    
 | 
			
		||||
 | 
			
		||||
    automaton(automaton const& other):
 | 
			
		||||
        m(other.m), 
 | 
			
		||||
        m_delta(other.m_delta),
 | 
			
		||||
        m_delta_inv(other.m_delta_inv),        
 | 
			
		||||
        m_init(other.m_init),
 | 
			
		||||
        m_final_set(other.m_final_set),
 | 
			
		||||
        m_final_states(other.m_final_states)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    // create the automaton that accepts the empty string only.
 | 
			
		||||
    static automaton* mk_epsilon(M& m) {
 | 
			
		||||
        moves mvs;
 | 
			
		||||
        unsigned_vector final;
 | 
			
		||||
        final.push_back(0);        
 | 
			
		||||
        return alloc(automaton, m, 0, final, mvs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // create the automaton with a single state on condition t.
 | 
			
		||||
    static automaton* mk_loop(M& m, T* t) {
 | 
			
		||||
        moves mvs;
 | 
			
		||||
        unsigned_vector final;
 | 
			
		||||
        final.push_back(0);       
 | 
			
		||||
        mvs.push_back(move(m, 0, 0, t));
 | 
			
		||||
        return alloc(automaton, m, 0, final, mvs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // create the sum of disjoint automata
 | 
			
		||||
    static automaton* mk_union(automaton const& a, automaton const& b) {
 | 
			
		||||
        SASSERT(&a.m == &b.m);
 | 
			
		||||
        M& m = a.m;
 | 
			
		||||
        moves mvs;
 | 
			
		||||
        unsigned_vector final;
 | 
			
		||||
        unsigned offset1 = 1;
 | 
			
		||||
        unsigned offset2 = a.num_states() + 1;
 | 
			
		||||
        mvs.push_back(move(m, 0, a.init() + offset1));
 | 
			
		||||
        mvs.push_back(move(m, 0, b.init() + offset2));
 | 
			
		||||
        append_moves(offset1, a, mvs);
 | 
			
		||||
        append_moves(offset2, b, mvs);
 | 
			
		||||
        append_final(offset1, a, final);
 | 
			
		||||
        append_final(offset2, b, final);
 | 
			
		||||
        return alloc(automaton, m, 0, final, mvs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static automaton* mk_opt(automaton const& a) {       
 | 
			
		||||
        M& m = a.m;
 | 
			
		||||
        moves mvs;
 | 
			
		||||
        unsigned_vector final;
 | 
			
		||||
        unsigned offset = 0;
 | 
			
		||||
        unsigned init = a.init();
 | 
			
		||||
        if (!a.initial_state_is_source()) {
 | 
			
		||||
            offset = 1;
 | 
			
		||||
            init = 0;
 | 
			
		||||
            mvs.push_back(move(m, 0, a.init() + offset));
 | 
			
		||||
        }
 | 
			
		||||
        mvs.push_back(move(m, init, a.final_state() + offset));
 | 
			
		||||
        append_moves(offset, a, mvs);
 | 
			
		||||
        append_final(offset, a, final);
 | 
			
		||||
        return alloc(automaton, m, init, final, mvs);        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // concatenate accepting languages
 | 
			
		||||
    static automaton* mk_concat(automaton const& a, automaton const& b) {
 | 
			
		||||
        SASSERT(&a.m == &b.m);
 | 
			
		||||
        M& m = a.m;
 | 
			
		||||
        moves mvs;
 | 
			
		||||
        unsigned_vector final;
 | 
			
		||||
        unsigned init = 0;
 | 
			
		||||
        unsigned offset1 = 1;
 | 
			
		||||
        unsigned offset2 = a.num_states() + offset1;
 | 
			
		||||
        mvs.push_back(move(m, 0, a.init() + offset1));
 | 
			
		||||
        append_moves(offset1, a, mvs);
 | 
			
		||||
        for (unsigned i = 0; i < a.m_final_states.size(); ++i) {
 | 
			
		||||
            mvs.push_back(move(m, a.m_final_states[i] + offset1, b.init() + offset2));
 | 
			
		||||
        }
 | 
			
		||||
        append_moves(offset2, b, mvs);
 | 
			
		||||
        append_final(offset2, b, final);
 | 
			
		||||
        
 | 
			
		||||
        return alloc(automaton, m, init, final, mvs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static automaton* mk_reverse(automaton const& a) {
 | 
			
		||||
        M& m = a.m;
 | 
			
		||||
        if (a.is_empty()) {
 | 
			
		||||
            return alloc(automaton, m);
 | 
			
		||||
        }
 | 
			
		||||
        moves mvs;
 | 
			
		||||
        for (unsigned i = 0; i < a.m_delta.size(); ++i) {
 | 
			
		||||
            moves const& mvs1 = a.m_delta[i];
 | 
			
		||||
            for (unsigned j = 0; j < mvs1.size(); ++j) {
 | 
			
		||||
                move const& mv = mvs1[j];
 | 
			
		||||
                mvs.push_back(move(m, mv.dst(), mv.src(), mv.t()));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        unsigned_vector final;
 | 
			
		||||
        unsigned init;
 | 
			
		||||
        final.push_back(a.init());
 | 
			
		||||
        if (a.m_final_states.size() == 1) {
 | 
			
		||||
            init = a.m_final_states[0];
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            init = a.num_states();
 | 
			
		||||
            for (unsigned i = 0; i < a.m_final_states.size(); ++i) {
 | 
			
		||||
                mvs.push_back(move(m, init, a.m_final_states[i]));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return alloc(automaton, m, init, final, mvs);        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void add_to_final_states(unsigned s) {
 | 
			
		||||
        if (!is_final_state(s)) {
 | 
			
		||||
            m_final_set.insert(s);
 | 
			
		||||
            m_final_states.push_back(s);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void remove_from_final_states(unsigned s) {
 | 
			
		||||
        if (is_final_state(s)) {
 | 
			
		||||
            m_final_set.remove(s);
 | 
			
		||||
            m_final_states.erase(s);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void add_init_to_final_states() {
 | 
			
		||||
        add_to_final_states(init());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void add_final_to_init_moves() {
 | 
			
		||||
        for (unsigned i = 0; i < m_final_states.size(); ++i) {
 | 
			
		||||
            unsigned state = m_final_states[i];
 | 
			
		||||
            bool found = false;
 | 
			
		||||
            moves const& mvs = m_delta[state];
 | 
			
		||||
            for (unsigned j = 0; found && j < mvs.size(); ++j) {
 | 
			
		||||
                found = (mvs[j].dst() == m_init) && mvs[j].is_epsilon();
 | 
			
		||||
            }
 | 
			
		||||
            if (!found && state != m_init) {
 | 
			
		||||
                add(move(m, state, m_init));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // remove epsilon transitions
 | 
			
		||||
    // src - e -> dst
 | 
			
		||||
    // in_degree(src) = 1, final(src) => final(dst), src0 != src
 | 
			
		||||
    //    src0 - t -> src - e -> dst => src0 - t -> dst
 | 
			
		||||
    // out_degree(dst) = 1, final(dst) => final(src), dst != dst1
 | 
			
		||||
    //    src - e -> dst - t -> dst1 => src - t -> dst1
 | 
			
		||||
 | 
			
		||||
    // Generalized: 
 | 
			
		||||
    // Src - E -> dst - t -> dst1 => Src - t -> dst1   if dst is final => each Src is final
 | 
			
		||||
    //
 | 
			
		||||
    // src - e -> dst - ET -> Dst1 => src - ET -> Dst1  if in_degree(dst) = 1, src != dst
 | 
			
		||||
    // Src - E -> dst - et -> dst1 => Src - et -> dst1  if out_degree(dst) = 1, src != dst
 | 
			
		||||
    // 
 | 
			
		||||
    void compress() {
 | 
			
		||||
        for (unsigned i = 0; i < m_delta.size(); ++i) {
 | 
			
		||||
            for (unsigned j = 0; j < m_delta[i].size(); ++j) {
 | 
			
		||||
                move const& mv = m_delta[i][j];
 | 
			
		||||
                unsigned src = mv.src();
 | 
			
		||||
                unsigned dst = mv.dst();
 | 
			
		||||
                SASSERT(src == i);
 | 
			
		||||
                if (mv.is_epsilon()) {
 | 
			
		||||
                    if (src == dst) {
 | 
			
		||||
                        // just remove this edge.                        
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (1 == in_degree(src) && 1 == out_degree(src) && init() != src && (!is_final_state(src) || is_final_state(dst))) {
 | 
			
		||||
                        move const& mv0 = m_delta_inv[src][0];
 | 
			
		||||
                        unsigned src0 = mv0.src();                        
 | 
			
		||||
                        T* t = mv0.t();
 | 
			
		||||
                        SASSERT(mv0.dst() == src);
 | 
			
		||||
                        if (src0 == src) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                        add(move(m, src0, dst, t));
 | 
			
		||||
                        remove(src0, src, t);
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (1 == out_degree(dst) && 1 == in_degree(dst) && init() != dst && (!is_final_state(dst) || is_final_state(src))) {
 | 
			
		||||
                        move const& mv1 = m_delta[dst][0];
 | 
			
		||||
                        unsigned dst1 = mv1.dst();
 | 
			
		||||
                        T* t = mv1.t();
 | 
			
		||||
                        SASSERT(mv1.src() == dst);
 | 
			
		||||
                        if (dst1 == dst) {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                        add(move(m, src, dst1, t));
 | 
			
		||||
                        remove(dst, dst1, t);
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (1 == in_degree(dst) && (!is_final_state(dst) || is_final_state(src)) && init() != dst) {
 | 
			
		||||
                        moves const& mvs = m_delta[dst];
 | 
			
		||||
                        moves mvs1;
 | 
			
		||||
                        for (unsigned k = 0; k < mvs.size(); ++k) {
 | 
			
		||||
                            mvs1.push_back(move(m, src, mvs[k].dst(), mvs[k].t()));
 | 
			
		||||
                        }
 | 
			
		||||
                        for (unsigned k = 0; k < mvs1.size(); ++k) {
 | 
			
		||||
                            remove(dst, mvs1[k].dst(), mvs1[k].t());
 | 
			
		||||
                            add(mvs1[k]);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    //
 | 
			
		||||
                    // Src - E -> dst - et -> dst1 => Src - et -> dst1  if out_degree(dst) = 1, src != dst
 | 
			
		||||
                    //
 | 
			
		||||
                    else if (1 == out_degree(dst) && all_epsilon_in(dst) && init() != dst && !is_final_state(dst)) {
 | 
			
		||||
                        move const& mv = m_delta[dst][0];
 | 
			
		||||
                        unsigned dst1 = mv.dst();
 | 
			
		||||
                        T* t = mv.t();
 | 
			
		||||
                        unsigned_vector src0s;
 | 
			
		||||
                        moves const& mvs = m_delta_inv[dst];
 | 
			
		||||
                        moves mvs1;
 | 
			
		||||
                        for (unsigned k = 0; k < mvs.size(); ++k) {
 | 
			
		||||
                            SASSERT(mvs[k].is_epsilon());
 | 
			
		||||
                            mvs1.push_back(move(m, mvs[k].src(), dst1, t));
 | 
			
		||||
                        }
 | 
			
		||||
                        for (unsigned k = 0; k < mvs1.size(); ++k) {
 | 
			
		||||
                            remove(mvs1[k].src(), dst, 0);
 | 
			
		||||
                            add(mvs1[k]);
 | 
			
		||||
                        }
 | 
			
		||||
                        remove(dst, dst1, t);    
 | 
			
		||||
                        --j;
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    //
 | 
			
		||||
                    // Src1 - ET -> src - e -> dst => Src1 - ET -> dst  if out_degree(src) = 1, src != init() 
 | 
			
		||||
                    //
 | 
			
		||||
                    else if (1 == out_degree(src) && init() != src && (!is_final_state(src) || is_final_state(dst))) {
 | 
			
		||||
                        moves const& mvs = m_delta_inv[src];
 | 
			
		||||
                        moves mvs1;
 | 
			
		||||
                        for (unsigned k = 0; k < mvs.size(); ++k) {
 | 
			
		||||
                            mvs1.push_back(move(m, mvs[k].src(), dst, mvs[k].t()));
 | 
			
		||||
                        }
 | 
			
		||||
                        for (unsigned k = 0; k < mvs1.size(); ++k) {
 | 
			
		||||
                            remove(mvs1[k].src(), src, mvs1[k].t());
 | 
			
		||||
                            add(mvs1[k]);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }                    
 | 
			
		||||
                    remove(src, dst, 0);
 | 
			
		||||
                    --j;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        while (true) {
 | 
			
		||||
            SASSERT(!m_delta.empty());
 | 
			
		||||
            unsigned src = m_delta.size() - 1;            
 | 
			
		||||
            if (in_degree(src) == 0 && init() != src) {
 | 
			
		||||
                remove_from_final_states(src);
 | 
			
		||||
                m_delta.pop_back();
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_sequence(unsigned& length) const {
 | 
			
		||||
        if (is_final_state(m_init) && (out_degree(m_init) == 0 || (out_degree(m_init) == 1 && is_loop_state(m_init)))) {
 | 
			
		||||
            length = 0;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        if (is_empty() || in_degree(m_init) != 0 || out_degree(m_init) != 1) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        length = 1;
 | 
			
		||||
        unsigned s = get_move_from(m_init).dst();
 | 
			
		||||
        while (!is_final_state(s)) {  
 | 
			
		||||
            if (out_degree(s) != 1 || in_degree(s) != 1) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            s = get_move_from(s).dst();
 | 
			
		||||
            ++length;
 | 
			
		||||
        }
 | 
			
		||||
        return out_degree(s) == 0 || (out_degree(s) == 1 && is_loop_state(s));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned init() const { return m_init; }
 | 
			
		||||
    unsigned in_degree(unsigned state) const { return m_delta_inv[state].size(); }
 | 
			
		||||
    unsigned out_degree(unsigned state) const { return m_delta[state].size(); }
 | 
			
		||||
    move const& get_move_from(unsigned state) const { SASSERT(m_delta[state].size() == 1); return m_delta[state][0]; }
 | 
			
		||||
    move const& get_move_to(unsigned state) const { SASSERT(m_delta_inv[state].size() == 1); return m_delta_inv[state][0]; }
 | 
			
		||||
    moves const& get_moves_from(unsigned state) const { return m_delta[state]; }
 | 
			
		||||
    moves const& get_moves_to(unsigned state) const { return m_delta_inv[state]; }
 | 
			
		||||
    bool initial_state_is_source() const { return m_delta_inv[m_init].empty(); }
 | 
			
		||||
    bool is_final_state(unsigned s) const { return m_final_set.contains(s); }
 | 
			
		||||
    bool is_epsilon_free() const {
 | 
			
		||||
        for (unsigned i = 0; i < m_delta.size(); ++i) {
 | 
			
		||||
            moves const& mvs = m_delta[i];
 | 
			
		||||
            for (unsigned j = 0; j < mvs.size(); ++j) {
 | 
			
		||||
                if (!mvs[j].t()) return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool all_epsilon_in(unsigned s) {
 | 
			
		||||
        moves const& mvs = m_delta_inv[s];
 | 
			
		||||
        for (unsigned j = 0; j < mvs.size(); ++j) {
 | 
			
		||||
            if (mvs[j].t()) return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_empty() const { return m_final_states.empty(); }
 | 
			
		||||
    unsigned final_state() const { return m_final_states[0]; }
 | 
			
		||||
    bool has_single_final_sink() const { return m_final_states.size() == 1 && m_delta[final_state()].empty(); }
 | 
			
		||||
    unsigned num_states() const { return m_delta.size(); }
 | 
			
		||||
    bool is_loop_state(unsigned s) const {
 | 
			
		||||
        moves mvs;
 | 
			
		||||
        get_moves_from(s, mvs);
 | 
			
		||||
        for (unsigned i = 0; i < mvs.size(); ++i) {
 | 
			
		||||
            if (s == mvs[i].dst()) return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned move_count() const {
 | 
			
		||||
        unsigned result = 0;
 | 
			
		||||
        for (unsigned i = 0; i < m_delta.size(); result += m_delta[i].size(), ++i) {}
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
    void get_epsilon_closure(unsigned state, unsigned_vector& states) {
 | 
			
		||||
        get_epsilon_closure(state, m_delta, states);
 | 
			
		||||
    }
 | 
			
		||||
    void get_inv_epsilon_closure(unsigned state, unsigned_vector& states) {
 | 
			
		||||
        get_epsilon_closure(state, m_delta_inv, states);
 | 
			
		||||
    }
 | 
			
		||||
    void get_moves_from(unsigned state, moves& mvs, bool epsilon_closure = true) const {
 | 
			
		||||
        get_moves(state, m_delta, mvs, epsilon_closure);
 | 
			
		||||
    }
 | 
			
		||||
    void get_moves_to(unsigned state, moves& mvs, bool epsilon_closure = true) {
 | 
			
		||||
        get_moves(state, m_delta_inv, mvs, epsilon_closure);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class D>
 | 
			
		||||
    std::ostream& display(std::ostream& out, D& displayer = D()) const {
 | 
			
		||||
        out << "init: " << init() << "\n";
 | 
			
		||||
        out << "final: ";
 | 
			
		||||
        for (unsigned i = 0; i < m_final_states.size(); ++i) out << m_final_states[i] << " ";
 | 
			
		||||
        out << "\n";
 | 
			
		||||
        for (unsigned i = 0; i < m_delta.size(); ++i) {
 | 
			
		||||
            moves const& mvs = m_delta[i];
 | 
			
		||||
            for (unsigned j = 0; j < mvs.size(); ++j) {
 | 
			
		||||
                move const& mv = mvs[j];
 | 
			
		||||
                out << i << " -> " << mv.dst() << " ";
 | 
			
		||||
                if (mv.t()) {
 | 
			
		||||
                    out << "if "; 
 | 
			
		||||
                    displayer.display(out, mv.t());
 | 
			
		||||
                }
 | 
			
		||||
                out << "\n";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return out;
 | 
			
		||||
    }
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    void remove_dead_states() {
 | 
			
		||||
        unsigned_vector remap;
 | 
			
		||||
        for (unsigned i = 0; i < m_delta.size(); ++i) {
 | 
			
		||||
            
 | 
			
		||||
        }
 | 
			
		||||
    }    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    void add(move const& mv) {
 | 
			
		||||
        m_delta[mv.src()].push_back(mv);
 | 
			
		||||
        m_delta_inv[mv.dst()].push_back(mv);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    unsigned find_move(unsigned src, unsigned dst, T* t, moves const& mvs) {
 | 
			
		||||
        for (unsigned i = 0; i < mvs.size(); ++i) {
 | 
			
		||||
            move const& mv = mvs[i];
 | 
			
		||||
            if (mv.src() == src && mv.dst() == dst && t == mv.t()) {
 | 
			
		||||
                return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
        return UINT_MAX;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void remove(unsigned src, unsigned dst, T* t, moves& mvs) {
 | 
			
		||||
        remove(find_move(src, dst, t, mvs), mvs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void remove(unsigned src, unsigned dst, T* t) {
 | 
			
		||||
        remove(src, dst, t, m_delta[src]);
 | 
			
		||||
        remove(src, dst, t, m_delta_inv[dst]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void remove(unsigned index, moves& mvs) {
 | 
			
		||||
        mvs[index] = mvs.back();
 | 
			
		||||
        mvs.pop_back();
 | 
			
		||||
    }     
 | 
			
		||||
 | 
			
		||||
    mutable unsigned_vector m_states1, m_states2;
 | 
			
		||||
    
 | 
			
		||||
    void get_moves(unsigned state, vector<moves> const& delta, moves& mvs, bool epsilon_closure) const {
 | 
			
		||||
        m_states1.reset(); 
 | 
			
		||||
        m_states2.reset();
 | 
			
		||||
        get_epsilon_closure(state, delta, m_states1);
 | 
			
		||||
        for (unsigned i = 0; i < m_states1.size(); ++i) {
 | 
			
		||||
            state = m_states1[i];
 | 
			
		||||
            moves const& mv1 = delta[state];
 | 
			
		||||
            for (unsigned j = 0; j < mv1.size(); ++j) {
 | 
			
		||||
                move const& mv = mv1[j];
 | 
			
		||||
                if (!mv.is_epsilon()) {
 | 
			
		||||
                    if (epsilon_closure) {
 | 
			
		||||
                        m_states2.reset();
 | 
			
		||||
                        get_epsilon_closure(mv.dst(), delta, m_states2);
 | 
			
		||||
                        for (unsigned k = 0; k < m_states2.size(); ++k) {
 | 
			
		||||
                            mvs.push_back(move(m, state, m_states2[k], mv.t()));                            
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        mvs.push_back(move(m, state, mv.dst(), mv.t()));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void get_epsilon_closure(unsigned state, vector<moves> const& delta, unsigned_vector& states) const {
 | 
			
		||||
        m_todo.push_back(state);
 | 
			
		||||
        m_visited.insert(state);
 | 
			
		||||
        while (!m_todo.empty()) {
 | 
			
		||||
            state = m_todo.back();
 | 
			
		||||
            states.push_back(state);
 | 
			
		||||
            m_todo.pop_back();
 | 
			
		||||
            moves const& mvs = delta[state];
 | 
			
		||||
            for (unsigned i = 0; i < mvs.size(); ++i) {
 | 
			
		||||
                unsigned tgt = mvs[i].dst();
 | 
			
		||||
                if (mvs[i].is_epsilon() && !m_visited.contains(tgt)) {
 | 
			
		||||
                    m_visited.insert(tgt);
 | 
			
		||||
                    m_todo.push_back(tgt);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        m_visited.reset();
 | 
			
		||||
        SASSERT(m_todo.empty());   
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static void append_moves(unsigned offset, automaton const& a, moves& mvs) {
 | 
			
		||||
        for (unsigned i = 0; i < a.num_states(); ++i) {
 | 
			
		||||
            moves const& mvs1 = a.m_delta[i];
 | 
			
		||||
            for (unsigned j = 0; j < mvs1.size(); ++j) {
 | 
			
		||||
                move const& mv = mvs1[j];
 | 
			
		||||
                mvs.push_back(move(a.m, mv.src() + offset, mv.dst() + offset, mv.t()));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static void append_final(unsigned offset, automaton const& a, unsigned_vector& final) {
 | 
			
		||||
        for (unsigned i = 0; i < a.m_final_states.size(); ++i) {
 | 
			
		||||
            final.push_back(a.m_final_states[i]+offset);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef automaton<unsigned> uautomaton;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif 
 | 
			
		||||
| 
						 | 
				
			
			@ -1158,7 +1158,6 @@ namespace pdr {
 | 
			
		|||
        while (!todo.empty()) {
 | 
			
		||||
            model_node* n = todo.back();
 | 
			
		||||
            model* md = 0;
 | 
			
		||||
            ast_manager& m = n->pt().get_manager();
 | 
			
		||||
            if (!n->get_model_ptr()) {
 | 
			
		||||
                if (models.find(n->state(), md)) {
 | 
			
		||||
                    TRACE("pdr", tout << n->state() << "\n";);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ Abstract:
 | 
			
		|||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Leonardo de Moura (leonardo) 2010-05-20.
 | 
			
		||||
    Krystof Hoder 2010-05-20.
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -301,13 +301,10 @@ namespace datalog {
 | 
			
		|||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        pair_info & get_pair(app_pair key) const {
 | 
			
		||||
            return *m_costs.find(key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void remove_rule_from_pair(app_pair key, rule * r, unsigned original_len) {
 | 
			
		||||
            pair_info * ptr = &get_pair(key);
 | 
			
		||||
            if (ptr->remove_rule(r, original_len)) {
 | 
			
		||||
            pair_info * ptr = 0;
 | 
			
		||||
            if (m_costs.find(key, ptr) && ptr &&
 | 
			
		||||
                ptr->remove_rule(r, original_len)) {
 | 
			
		||||
                SASSERT(ptr->m_rules.empty());
 | 
			
		||||
                m_costs.remove(key);
 | 
			
		||||
                dealloc(ptr);
 | 
			
		||||
| 
						 | 
				
			
			@ -362,7 +359,12 @@ namespace datalog {
 | 
			
		|||
        void join_pair(app_pair pair_key) {
 | 
			
		||||
            app * t1 = pair_key.first;
 | 
			
		||||
            app * t2 = pair_key.second;
 | 
			
		||||
            pair_info & inf = get_pair(pair_key);
 | 
			
		||||
            pair_info* infp = 0;
 | 
			
		||||
            if (!m_costs.find(pair_key, infp) || !infp) {
 | 
			
		||||
                UNREACHABLE();
 | 
			
		||||
                return;
 | 
			
		||||
            }            
 | 
			
		||||
            pair_info & inf = *infp;
 | 
			
		||||
            SASSERT(!inf.m_rules.empty());
 | 
			
		||||
            var_idx_set & output_vars = inf.m_all_nonlocal_vars;
 | 
			
		||||
            expr_ref_vector args(m);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -169,24 +169,16 @@ namespace smt2 {
 | 
			
		|||
            char c = curr();
 | 
			
		||||
            if (c == EOF) 
 | 
			
		||||
                throw scanner_exception("unexpected end of string", m_line, m_spos);
 | 
			
		||||
            if (c == '\"') {
 | 
			
		||||
            if (c == '\n') {
 | 
			
		||||
                new_line();
 | 
			
		||||
            }
 | 
			
		||||
            else if (c == '\"') {
 | 
			
		||||
                next();
 | 
			
		||||
                if (curr() != '\"') {
 | 
			
		||||
                    m_string.push_back(0);
 | 
			
		||||
                    return STRING_TOKEN;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (c == '\n') {
 | 
			
		||||
                new_line();
 | 
			
		||||
            }
 | 
			
		||||
            else if (c == '\\') {
 | 
			
		||||
                next();
 | 
			
		||||
                c = curr();
 | 
			
		||||
                if (c == EOF) 
 | 
			
		||||
                    throw scanner_exception("unexpected end of string", m_line, m_spos);
 | 
			
		||||
                if (c != '\\' && c != '\"')
 | 
			
		||||
                    throw scanner_exception("invalid escape sequence", m_line, m_spos);
 | 
			
		||||
            }
 | 
			
		||||
            m_string.push_back(c);
 | 
			
		||||
            next();
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,8 +78,12 @@ namespace sat {
 | 
			
		|||
        clause_vector::iterator end = s.m_clauses.end();
 | 
			
		||||
        try {
 | 
			
		||||
            for (; it != end; ++it) {
 | 
			
		||||
                if (s.inconsistent())
 | 
			
		||||
                if (s.inconsistent()) {
 | 
			
		||||
                    for (; it != end; ++it, ++it2) {
 | 
			
		||||
                        *it2 = *it;
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                SASSERT(s.m_qhead == s.m_trail.size());
 | 
			
		||||
                if (m_counter < limit || s.inconsistent()) {
 | 
			
		||||
                    *it2 = *it;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -169,6 +169,7 @@ namespace sat {
 | 
			
		|||
#endif
 | 
			
		||||
        void * mem = m_allocator.allocate(size);
 | 
			
		||||
        clause * cls = new (mem) clause(m_id_gen.mk(), num_lits, lits, learned);
 | 
			
		||||
        TRACE("sat", tout << "alloc: " << cls->id() << " " << cls << " " << *cls << " " << (learned?"l":"a") << "\n";);
 | 
			
		||||
        SASSERT(!learned || cls->is_learned());
 | 
			
		||||
        return cls;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,6 @@ Revision History:
 | 
			
		|||
#include"smt_solver.h"
 | 
			
		||||
 | 
			
		||||
extern bool g_display_statistics;
 | 
			
		||||
extern void display_config();
 | 
			
		||||
static clock_t             g_start_time;
 | 
			
		||||
static smtlib::solver*     g_solver      = 0;
 | 
			
		||||
static cmd_context *       g_cmd_context = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3936,7 +3936,7 @@ namespace smt {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        virtual bool is_shared(enode * n) const {
 | 
			
		||||
            return m_shared_enodes.contains(n);
 | 
			
		||||
            return !m_shared_enodes.empty() && m_shared_enodes.contains(n);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // This method is invoked when n becomes relevant.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1382,7 +1382,8 @@ namespace smt {
 | 
			
		|||
            bool_var v = l.var();
 | 
			
		||||
            bool_var_data & d = get_bdata(v);
 | 
			
		||||
            lbool val  = get_assignment(v);
 | 
			
		||||
            TRACE("propagate_atoms", tout << "propagating atom, #" << bool_var2expr(v)->get_id() << ", is_enode(): " << d.is_enode() << " " << l << "\n";);
 | 
			
		||||
            TRACE("propagate_atoms", tout << "propagating atom, #" << bool_var2expr(v)->get_id() << ", is_enode(): " << d.is_enode() 
 | 
			
		||||
                  << " tag: " << (d.is_eq()?"eq":"") << (d.is_theory_atom()?"th":"") << (d.is_quantifier()?"q":"") << " " << l << "\n";);
 | 
			
		||||
            SASSERT(val != l_undef);
 | 
			
		||||
            if (d.is_enode())
 | 
			
		||||
                propagate_bool_var_enode(v);
 | 
			
		||||
| 
						 | 
				
			
			@ -4024,8 +4025,9 @@ namespace smt {
 | 
			
		|||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        case 1: {
 | 
			
		||||
            if (m_qmanager->is_shared(n))
 | 
			
		||||
            if (m_qmanager->is_shared(n)) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // the variabe is shared if the equivalence class of n 
 | 
			
		||||
            // contains a parent application.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,6 +114,7 @@ namespace smt {
 | 
			
		|||
        friend class euf_manager;
 | 
			
		||||
        friend class conflict_resolution;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        theory_var_list * get_th_var_list() { 
 | 
			
		||||
            return m_th_var_list.get_th_var() == null_theory_var ? 0 : &m_th_var_list; 
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -170,6 +171,7 @@ namespace smt {
 | 
			
		|||
            m_interpreted = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        void del_eh(ast_manager & m, bool update_children_parent = true);
 | 
			
		||||
        
 | 
			
		||||
        app * get_owner() const { 
 | 
			
		||||
| 
						 | 
				
			
			@ -192,6 +194,7 @@ namespace smt {
 | 
			
		|||
            return m_owner->hash();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        enode * get_root() const { 
 | 
			
		||||
            return m_root; 
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,7 +90,9 @@ namespace smt {
 | 
			
		|||
                sort * s      = m_manager.get_sort(r->get_owner());
 | 
			
		||||
                model_value_proc * proc = 0;
 | 
			
		||||
                if (m_manager.is_bool(s)) {
 | 
			
		||||
                    SASSERT(m_context->get_assignment(r) == l_true || m_context->get_assignment(r) == l_false);
 | 
			
		||||
                    CTRACE("func_interp_bug", m_context->get_assignment(r) == l_undef, 
 | 
			
		||||
                           tout << mk_pp(r->get_owner(), m_manager) << "\n";);
 | 
			
		||||
                    SASSERT(m_context->get_assignment(r) != l_undef);
 | 
			
		||||
                    if (m_context->get_assignment(r) == l_true)
 | 
			
		||||
                        proc = alloc(expr_wrapper_proc, m_manager.mk_true());
 | 
			
		||||
                    else
 | 
			
		||||
| 
						 | 
				
			
			@ -359,6 +361,7 @@ namespace smt {
 | 
			
		|||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        enode * child = d.get_enode();
 | 
			
		||||
                        TRACE("mg_top_sort", tout << "#" << n->get_owner_id() << " (" << mk_pp(n->get_owner(), m_manager) << "): " << mk_pp(child->get_owner(), m_manager) << " " << mk_pp(child->get_root()->get_owner(), m_manager) << "\n";);
 | 
			
		||||
                        child = child->get_root();
 | 
			
		||||
                        app * val = 0;
 | 
			
		||||
                        m_root2value.find(child, val);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -396,12 +396,14 @@ namespace smt {
 | 
			
		|||
        scoped_ptr<model_checker>   m_model_checker;
 | 
			
		||||
        unsigned                    m_new_enode_qhead;
 | 
			
		||||
        unsigned                    m_lazy_matching_idx;
 | 
			
		||||
        bool                        m_active;
 | 
			
		||||
    public:
 | 
			
		||||
        default_qm_plugin():
 | 
			
		||||
            m_qm(0), 
 | 
			
		||||
            m_context(0), 
 | 
			
		||||
            m_new_enode_qhead(0), 
 | 
			
		||||
            m_lazy_matching_idx(0) {
 | 
			
		||||
            m_lazy_matching_idx(0),
 | 
			
		||||
            m_active(false) {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        virtual ~default_qm_plugin() {
 | 
			
		||||
| 
						 | 
				
			
			@ -443,6 +445,7 @@ namespace smt {
 | 
			
		|||
       */
 | 
			
		||||
        virtual void add(quantifier * q) {
 | 
			
		||||
            if (m_fparams->m_mbqi && mbqi_enabled(q)) {
 | 
			
		||||
                m_active = true;
 | 
			
		||||
                m_model_finder->register_quantifier(q);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -475,6 +478,7 @@ namespace smt {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void assign_eh(quantifier * q) {
 | 
			
		||||
            m_active = true;
 | 
			
		||||
            if (m_fparams->m_ematching) {
 | 
			
		||||
                bool has_unary_pattern = false;
 | 
			
		||||
                unsigned num_patterns = q->get_num_patterns();
 | 
			
		||||
| 
						 | 
				
			
			@ -537,7 +541,7 @@ namespace smt {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        virtual bool is_shared(enode * n) const {
 | 
			
		||||
            return (m_mam->is_shared(n) || m_lazy_mam->is_shared(n));
 | 
			
		||||
            return m_active && (m_mam->is_shared(n) || m_lazy_mam->is_shared(n));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void adjust_model(proto_model * m) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -815,7 +815,7 @@ namespace smt {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    void setup::setup_seq() {
 | 
			
		||||
        m_context.register_plugin(alloc(theory_seq_empty, m_manager));
 | 
			
		||||
        m_context.register_plugin(alloc(theory_seq, m_manager));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void setup::setup_card() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -429,6 +429,7 @@ namespace smt {
 | 
			
		|||
        arith_util              m_util;
 | 
			
		||||
        arith_eq_solver         m_arith_eq_solver;
 | 
			
		||||
        bool                    m_found_unsupported_op;
 | 
			
		||||
        bool                    m_found_underspecified_op;
 | 
			
		||||
        arith_eq_adapter        m_arith_eq_adapter;
 | 
			
		||||
        vector<row>             m_rows;
 | 
			
		||||
        svector<unsigned>       m_dead_rows;
 | 
			
		||||
| 
						 | 
				
			
			@ -510,6 +511,7 @@ namespace smt {
 | 
			
		|||
        virtual theory_var mk_var(enode * n);
 | 
			
		||||
 | 
			
		||||
        void found_unsupported_op(app * n);
 | 
			
		||||
        void found_underspecified_op(app * n);
 | 
			
		||||
 | 
			
		||||
        bool has_var(expr * v) const { return get_context().e_internalized(v) && get_context().get_enode(v)->get_th_var(get_id()) != null_theory_var; }
 | 
			
		||||
        theory_var expr2var(expr * v) const { SASSERT(get_context().e_internalized(v)); return get_context().get_enode(v)->get_th_var(get_id()); }
 | 
			
		||||
| 
						 | 
				
			
			@ -1056,6 +1058,10 @@ namespace smt {
 | 
			
		|||
        // -----------------------------------
 | 
			
		||||
        virtual bool get_value(enode * n, expr_ref & r);
 | 
			
		||||
 | 
			
		||||
        bool get_lower(enode* n, expr_ref& r);
 | 
			
		||||
        bool get_upper(enode* n, expr_ref& r);
 | 
			
		||||
        bool to_expr(inf_numeral const& val, bool is_int, expr_ref& r);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // -----------------------------------
 | 
			
		||||
        //
 | 
			
		||||
| 
						 | 
				
			
			@ -1071,6 +1077,8 @@ namespace smt {
 | 
			
		|||
                          unsigned num_eqs, enode_pair const * eqs,
 | 
			
		||||
                          unsigned num_params, parameter* params);
 | 
			
		||||
        inf_eps_rational<inf_rational> conflict_minimize();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        virtual expr_ref mk_gt(theory_var v);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2153,10 +2153,14 @@ namespace smt {
 | 
			
		|||
    */
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    bool theory_arith<Ext>::is_shared(theory_var v) const {
 | 
			
		||||
        if (!m_found_underspecified_op) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        enode * n      = get_enode(v);
 | 
			
		||||
        enode * r      = n->get_root();
 | 
			
		||||
        enode_vector::const_iterator it  = r->begin_parents();
 | 
			
		||||
        enode_vector::const_iterator end = r->end_parents();
 | 
			
		||||
        TRACE("shared", tout << get_context().get_scope_level() << " " <<  v << " " << r->get_num_parents() << "\n";);
 | 
			
		||||
        for (; it != end; ++it) {
 | 
			
		||||
            enode * parent = *it;
 | 
			
		||||
            app *   o = parent->get_owner();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,15 @@ namespace smt {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    void theory_arith<Ext>::found_underspecified_op(app * n) {
 | 
			
		||||
        if (!m_found_underspecified_op) {
 | 
			
		||||
            TRACE("arith", tout << "found non underspecificed expression:\n" << mk_pp(n, get_manager()) << "\n";);
 | 
			
		||||
            get_context().push_trail(value_trail<context, bool>(m_found_underspecified_op));
 | 
			
		||||
            m_found_underspecified_op = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    bool theory_arith<Ext>::process_atoms() const {
 | 
			
		||||
        if (!adaptive())
 | 
			
		||||
| 
						 | 
				
			
			@ -308,6 +317,7 @@ namespace smt {
 | 
			
		|||
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    theory_var theory_arith<Ext>::internalize_div(app * n) {
 | 
			
		||||
        found_underspecified_op(n);
 | 
			
		||||
        theory_var s      = mk_binary_op(n);
 | 
			
		||||
        context & ctx     = get_context();
 | 
			
		||||
        if (!ctx.relevancy())
 | 
			
		||||
| 
						 | 
				
			
			@ -317,6 +327,7 @@ namespace smt {
 | 
			
		|||
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    theory_var theory_arith<Ext>::internalize_idiv(app * n) {
 | 
			
		||||
        found_underspecified_op(n);
 | 
			
		||||
        theory_var s      = mk_binary_op(n);
 | 
			
		||||
        context & ctx     = get_context();
 | 
			
		||||
        app * mod         = m_util.mk_mod(n->get_arg(0), n->get_arg(1));
 | 
			
		||||
| 
						 | 
				
			
			@ -329,6 +340,7 @@ namespace smt {
 | 
			
		|||
    template<typename Ext>
 | 
			
		||||
    theory_var theory_arith<Ext>::internalize_mod(app * n) {
 | 
			
		||||
        TRACE("arith_mod", tout << "internalizing...\n" << mk_pp(n, get_manager()) << "\n";);
 | 
			
		||||
        found_underspecified_op(n);
 | 
			
		||||
        theory_var s      = mk_binary_op(n);
 | 
			
		||||
        context & ctx     = get_context();
 | 
			
		||||
        if (!ctx.relevancy())
 | 
			
		||||
| 
						 | 
				
			
			@ -338,6 +350,7 @@ namespace smt {
 | 
			
		|||
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    theory_var theory_arith<Ext>::internalize_rem(app * n) {
 | 
			
		||||
        found_underspecified_op(n);
 | 
			
		||||
        theory_var s  = mk_binary_op(n);
 | 
			
		||||
        context & ctx = get_context();
 | 
			
		||||
        if (!ctx.relevancy()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1514,6 +1527,7 @@ namespace smt {
 | 
			
		|||
        m_util(m),
 | 
			
		||||
        m_arith_eq_solver(m),
 | 
			
		||||
        m_found_unsupported_op(false),
 | 
			
		||||
        m_found_underspecified_op(false),
 | 
			
		||||
        m_arith_eq_adapter(*this, params, m_util),
 | 
			
		||||
        m_asserted_qhead(0),
 | 
			
		||||
        m_to_patch(1024),
 | 
			
		||||
| 
						 | 
				
			
			@ -3088,21 +3102,36 @@ namespace smt {
 | 
			
		|||
    //
 | 
			
		||||
    // -----------------------------------
 | 
			
		||||
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    bool theory_arith<Ext>::to_expr(inf_numeral const& val, bool is_int, expr_ref & r) {
 | 
			
		||||
        if (val.get_infinitesimal().is_zero()) {            
 | 
			
		||||
            numeral _val = val.get_rational();
 | 
			
		||||
            r = m_util.mk_numeral(_val.to_rational(), is_int);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    bool theory_arith<Ext>::get_value(enode * n, expr_ref & r) {
 | 
			
		||||
        theory_var v = n->get_th_var(get_id());
 | 
			
		||||
        if (v == null_theory_var) {
 | 
			
		||||
            // TODO: generate fresh value different from other get_value(v) for all v.
 | 
			
		||||
            return false; 
 | 
			
		||||
        }
 | 
			
		||||
        inf_numeral const & val = get_value(v);
 | 
			
		||||
        if (!val.get_infinitesimal().is_zero()) {
 | 
			
		||||
            // TODO: add support for infinitesimals
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        numeral _val = val.get_rational();
 | 
			
		||||
        r = m_util.mk_numeral(_val.to_rational(), is_int(v));
 | 
			
		||||
        return true;
 | 
			
		||||
        return v != null_theory_var && to_expr(get_value(v), is_int(v), r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    bool theory_arith<Ext>::get_lower(enode * n, expr_ref & r) {        
 | 
			
		||||
        theory_var v = n->get_th_var(get_id());
 | 
			
		||||
        bound* b = (v == null_theory_var) ? 0 : lower(v);
 | 
			
		||||
        return b && to_expr(b->get_value(), is_int(v), r);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template<typename Ext>
 | 
			
		||||
    bool theory_arith<Ext>::get_upper(enode * n, expr_ref & r) {        
 | 
			
		||||
        theory_var v = n->get_th_var(get_id());
 | 
			
		||||
        bound* b = (v == null_theory_var) ? 0 : upper(v);
 | 
			
		||||
        return b && to_expr(b->get_value(), is_int(v), r);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // -----------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -424,6 +424,39 @@ namespace smt {
 | 
			
		|||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    void theory_bv::add_fixed_eq(theory_var v1, theory_var v2) {
 | 
			
		||||
        ++m_stats.m_num_eq_dynamic;
 | 
			
		||||
        if (v1 > v2) {
 | 
			
		||||
            std::swap(v1, v2);
 | 
			
		||||
        }
 | 
			
		||||
        unsigned sz = get_bv_size(v1);
 | 
			
		||||
        ast_manager& m = get_manager();
 | 
			
		||||
        context & ctx = get_context();
 | 
			
		||||
        app* o1 = get_enode(v1)->get_owner();
 | 
			
		||||
        app* o2 = get_enode(v2)->get_owner();
 | 
			
		||||
        literal oeq = mk_eq(o1, o2, true);
 | 
			
		||||
        TRACE("bv", 
 | 
			
		||||
              tout << mk_pp(o1, m) << " = " << mk_pp(o2, m) << " " 
 | 
			
		||||
              << ctx.get_scope_level() << "\n";);
 | 
			
		||||
        literal_vector eqs;
 | 
			
		||||
        for (unsigned i = 0; i < sz; ++i) {
 | 
			
		||||
            literal l1 = m_bits[v1][i];
 | 
			
		||||
            literal l2 = m_bits[v2][i];
 | 
			
		||||
            expr_ref e1(m), e2(m);
 | 
			
		||||
            e1 = mk_bit2bool(o1, i);
 | 
			
		||||
            e2 = mk_bit2bool(o2, i);
 | 
			
		||||
            literal eq = mk_eq(e1, e2, true);
 | 
			
		||||
            ctx.mk_th_axiom(get_id(),  l1, ~l2, ~eq);
 | 
			
		||||
            ctx.mk_th_axiom(get_id(), ~l1,  l2, ~eq);
 | 
			
		||||
            ctx.mk_th_axiom(get_id(),  l1,  l2,  eq);
 | 
			
		||||
            ctx.mk_th_axiom(get_id(), ~l1, ~l2,  eq);
 | 
			
		||||
            ctx.mk_th_axiom(get_id(), eq, ~oeq);
 | 
			
		||||
            eqs.push_back(~eq);
 | 
			
		||||
        }
 | 
			
		||||
        eqs.push_back(oeq);
 | 
			
		||||
        ctx.mk_th_axiom(get_id(), eqs.size(), eqs.c_ptr());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void theory_bv::fixed_var_eh(theory_var v) {
 | 
			
		||||
        numeral val;
 | 
			
		||||
        bool r      = get_fixed_value(v, val);
 | 
			
		||||
| 
						 | 
				
			
			@ -443,7 +476,9 @@ namespace smt {
 | 
			
		|||
                          display_var(tout, v);
 | 
			
		||||
                          display_var(tout, v2););
 | 
			
		||||
                    m_stats.m_num_th2core_eq++;
 | 
			
		||||
                    add_fixed_eq(v, v2);
 | 
			
		||||
                    ctx.assign_eq(get_enode(v), get_enode(v2), eq_justification(js));                    
 | 
			
		||||
                    m_fixed_var_table.insert(key, v2);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1177,6 +1212,7 @@ namespace smt {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    void theory_bv::assign_bit(literal consequent, theory_var v1, theory_var v2, unsigned idx, literal antecedent, bool propagate_eqc) {
 | 
			
		||||
 | 
			
		||||
        m_stats.m_num_bit2core++;
 | 
			
		||||
        context & ctx = get_context();
 | 
			
		||||
        SASSERT(ctx.get_assignment(antecedent) == l_true);
 | 
			
		||||
| 
						 | 
				
			
			@ -1192,6 +1228,12 @@ namespace smt {
 | 
			
		|||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            ctx.assign(consequent, mk_bit_eq_justification(v1, v2, consequent, antecedent));
 | 
			
		||||
            literal_vector lits;
 | 
			
		||||
            lits.push_back(~consequent);
 | 
			
		||||
            lits.push_back(antecedent);
 | 
			
		||||
            lits.push_back(~mk_eq(get_enode(v1)->get_owner(), get_enode(v2)->get_owner(), false));
 | 
			
		||||
            ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr());
 | 
			
		||||
     
 | 
			
		||||
            if (m_wpos[v2] == idx)
 | 
			
		||||
                find_wpos(v2);
 | 
			
		||||
            // REMARK: bit_eq_justification is marked as a theory_bv justification.
 | 
			
		||||
| 
						 | 
				
			
			@ -1601,6 +1643,7 @@ namespace smt {
 | 
			
		|||
        st.update("bv dynamic diseqs", m_stats.m_num_diseq_dynamic);
 | 
			
		||||
        st.update("bv bit2core", m_stats.m_num_bit2core);
 | 
			
		||||
        st.update("bv->core eq", m_stats.m_num_th2core_eq);
 | 
			
		||||
        st.update("bv dynamic eqs", m_stats.m_num_eq_dynamic);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef Z3DEBUG
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,7 @@ namespace smt {
 | 
			
		|||
    
 | 
			
		||||
    struct theory_bv_stats {
 | 
			
		||||
        unsigned   m_num_diseq_static, m_num_diseq_dynamic, m_num_bit2core, m_num_th2core_eq, m_num_conflicts;
 | 
			
		||||
        unsigned   m_num_eq_dynamic;
 | 
			
		||||
        void reset() { memset(this, 0, sizeof(theory_bv_stats)); }
 | 
			
		||||
        theory_bv_stats() { reset(); }
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			@ -124,6 +125,7 @@ namespace smt {
 | 
			
		|||
        typedef std::pair<numeral, unsigned> value_sort_pair;
 | 
			
		||||
        typedef pair_hash<obj_hash<numeral>, unsigned_hash> value_sort_pair_hash;
 | 
			
		||||
        typedef map<value_sort_pair, theory_var, value_sort_pair_hash, default_eq<value_sort_pair> > value2var;
 | 
			
		||||
 | 
			
		||||
        value2var                m_fixed_var_table;
 | 
			
		||||
        
 | 
			
		||||
        literal_vector           m_tmp_literals;
 | 
			
		||||
| 
						 | 
				
			
			@ -166,6 +168,7 @@ namespace smt {
 | 
			
		|||
        void find_wpos(theory_var v);
 | 
			
		||||
        friend class fixed_eq_justification;
 | 
			
		||||
        void fixed_var_eh(theory_var v);
 | 
			
		||||
        void add_fixed_eq(theory_var v1, theory_var v2);
 | 
			
		||||
        bool get_fixed_value(theory_var v, numeral & result) const;
 | 
			
		||||
        void internalize_num(app * n);
 | 
			
		||||
        void internalize_add(app * n);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -235,7 +235,7 @@ namespace smt {
 | 
			
		|||
        SASSERT(mpzm.is_int64(exp_u));
 | 
			
		||||
 | 
			
		||||
        scoped_mpf f(mpfm);
 | 
			
		||||
        mpfm.set(f, m_ebits, m_sbits, mpzm.is_one(sgn_z), sig_z, mpzm.get_int64(exp_u));
 | 
			
		||||
        mpfm.set(f, m_ebits, m_sbits, mpzm.is_one(sgn_z), mpzm.get_int64(exp_u), sig_z);
 | 
			
		||||
        result = m_fu.mk_value(f);
 | 
			
		||||
 | 
			
		||||
        TRACE("t_fpa", tout << "fpa_value_proc::mk_value [" <<
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -25,15 +25,24 @@ Revision History:
 | 
			
		|||
#include "th_rewriter.h"
 | 
			
		||||
#include "ast_trail.h"
 | 
			
		||||
#include "scoped_vector.h"
 | 
			
		||||
#include "scoped_ptr_vector.h"
 | 
			
		||||
#include "automaton.h"
 | 
			
		||||
#include "seq_rewriter.h"
 | 
			
		||||
 | 
			
		||||
namespace smt {
 | 
			
		||||
 | 
			
		||||
    class theory_seq : public theory {
 | 
			
		||||
        typedef scoped_dependency_manager<enode_pair> enode_pair_dependency_manager;
 | 
			
		||||
        typedef enode_pair_dependency_manager::dependency enode_pair_dependency;
 | 
			
		||||
        struct assumption {
 | 
			
		||||
            enode* n1, *n2;
 | 
			
		||||
            literal lit;
 | 
			
		||||
            assumption(enode* n1, enode* n2): n1(n1), n2(n2), lit(null_literal) {}
 | 
			
		||||
            assumption(literal lit): n1(0), n2(0), lit(lit) {}
 | 
			
		||||
        };
 | 
			
		||||
        typedef scoped_dependency_manager<assumption> dependency_manager;
 | 
			
		||||
        typedef dependency_manager::dependency dependency;        
 | 
			
		||||
 | 
			
		||||
        typedef trail_stack<theory_seq> th_trail_stack;
 | 
			
		||||
        typedef std::pair<expr*, enode_pair_dependency*> expr_dep;
 | 
			
		||||
        typedef std::pair<expr*, dependency*> expr_dep;
 | 
			
		||||
        typedef obj_map<expr, expr_dep> eqdep_map_t; 
 | 
			
		||||
 | 
			
		||||
        // cache to track evaluations under equalities
 | 
			
		||||
| 
						 | 
				
			
			@ -52,27 +61,30 @@ namespace smt {
 | 
			
		|||
        class solution_map {
 | 
			
		||||
            enum map_update { INS, DEL };
 | 
			
		||||
            ast_manager&                      m;
 | 
			
		||||
            enode_pair_dependency_manager&    m_dm;
 | 
			
		||||
            dependency_manager&    m_dm;
 | 
			
		||||
            eqdep_map_t                       m_map;            
 | 
			
		||||
            eval_cache                        m_cache;
 | 
			
		||||
            expr_ref_vector                   m_lhs, m_rhs;
 | 
			
		||||
            ptr_vector<enode_pair_dependency> m_deps;
 | 
			
		||||
            ptr_vector<dependency> m_deps;
 | 
			
		||||
            svector<map_update>               m_updates;
 | 
			
		||||
            unsigned_vector                   m_limit;
 | 
			
		||||
 | 
			
		||||
            void add_trail(map_update op, expr* l, expr* r, enode_pair_dependency* d);
 | 
			
		||||
            void add_trail(map_update op, expr* l, expr* r, dependency* d);
 | 
			
		||||
        public:
 | 
			
		||||
            solution_map(ast_manager& m, enode_pair_dependency_manager& dm): 
 | 
			
		||||
            solution_map(ast_manager& m, dependency_manager& dm): 
 | 
			
		||||
                m(m),  m_dm(dm), m_cache(m), m_lhs(m), m_rhs(m) {}
 | 
			
		||||
            bool empty() const { return m_map.empty(); }
 | 
			
		||||
            void  update(expr* e, expr* r, enode_pair_dependency* d);
 | 
			
		||||
            bool  empty() const { return m_map.empty(); }
 | 
			
		||||
            void  update(expr* e, expr* r, dependency* d);
 | 
			
		||||
            void  add_cache(expr* v, expr_dep& r) { m_cache.insert(v, r); }
 | 
			
		||||
            bool  find_cache(expr* v, expr_dep& r) { return m_cache.find(v, r); }
 | 
			
		||||
            expr* find(expr* e, enode_pair_dependency*& d);
 | 
			
		||||
            void  cache(expr* e, expr* r, enode_pair_dependency* d);
 | 
			
		||||
            void push_scope() { m_limit.push_back(m_updates.size()); }
 | 
			
		||||
            void pop_scope(unsigned num_scopes);
 | 
			
		||||
            void display(std::ostream& out) const;
 | 
			
		||||
            expr* find(expr* e, dependency*& d);
 | 
			
		||||
            expr* find(expr* e);
 | 
			
		||||
            bool  is_root(expr* e) const;
 | 
			
		||||
            void  cache(expr* e, expr* r, dependency* d);
 | 
			
		||||
            void  reset_cache() { m_cache.reset(); }
 | 
			
		||||
            void  push_scope() { m_limit.push_back(m_updates.size()); }
 | 
			
		||||
            void  pop_scope(unsigned num_scopes);
 | 
			
		||||
            void  display(std::ostream& out) const;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // Table of current disequalities
 | 
			
		||||
| 
						 | 
				
			
			@ -94,55 +106,308 @@ namespace smt {
 | 
			
		|||
        };
 | 
			
		||||
 | 
			
		||||
        // Asserted or derived equality with dependencies
 | 
			
		||||
        struct eq {
 | 
			
		||||
            expr_ref               m_lhs;
 | 
			
		||||
            expr_ref               m_rhs;
 | 
			
		||||
            enode_pair_dependency* m_dep;
 | 
			
		||||
            eq(expr_ref& l, expr_ref& r, enode_pair_dependency* d):
 | 
			
		||||
                m_lhs(l), m_rhs(r), m_dep(d) {}
 | 
			
		||||
            eq(eq const& other): m_lhs(other.m_lhs), m_rhs(other.m_rhs), m_dep(other.m_dep) {}
 | 
			
		||||
            eq& operator=(eq const& other) { m_lhs = other.m_lhs; m_rhs = other.m_rhs; m_dep = other.m_dep; return *this; }
 | 
			
		||||
        class eq {
 | 
			
		||||
            unsigned         m_id;
 | 
			
		||||
            expr_ref_vector  m_lhs;
 | 
			
		||||
            expr_ref_vector  m_rhs;
 | 
			
		||||
            dependency*      m_dep;
 | 
			
		||||
        public:
 | 
			
		||||
            
 | 
			
		||||
            eq(unsigned id, expr_ref_vector& l, expr_ref_vector& r, dependency* d):
 | 
			
		||||
                m_id(id), m_lhs(l), m_rhs(r), m_dep(d) {}
 | 
			
		||||
            eq(eq const& other): m_id(other.m_id), m_lhs(other.m_lhs), m_rhs(other.m_rhs), m_dep(other.m_dep) {}
 | 
			
		||||
            eq& operator=(eq const& other) {
 | 
			
		||||
                if (this != &other) {
 | 
			
		||||
                    m_lhs.reset(); 
 | 
			
		||||
                    m_rhs.reset();
 | 
			
		||||
                    m_lhs.append(other.m_lhs); 
 | 
			
		||||
                    m_rhs.append(other.m_rhs); 
 | 
			
		||||
                    m_dep = other.m_dep;
 | 
			
		||||
                    m_id = other.m_id;
 | 
			
		||||
                } 
 | 
			
		||||
                return *this; 
 | 
			
		||||
            }
 | 
			
		||||
            expr_ref_vector const& ls() const { return m_lhs; }
 | 
			
		||||
            expr_ref_vector const& rs() const { return m_rhs; }
 | 
			
		||||
            dependency* dep() const { return m_dep; }
 | 
			
		||||
            unsigned id() const { return m_id; }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        eq mk_eqdep(expr* l, expr* r, dependency* dep) {
 | 
			
		||||
            expr_ref_vector ls(m), rs(m);
 | 
			
		||||
            m_util.str.get_concat(l, ls);
 | 
			
		||||
            m_util.str.get_concat(r, rs);
 | 
			
		||||
            return eq(m_eq_id++, ls, rs, dep);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        class ne2 {            
 | 
			
		||||
            vector<expr_ref_vector>  m_lhs;
 | 
			
		||||
            vector<expr_ref_vector>  m_rhs;
 | 
			
		||||
            literal_vector           m_lits;
 | 
			
		||||
            dependency*              m_dep;
 | 
			
		||||
        public:
 | 
			
		||||
            ne2(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep):
 | 
			
		||||
                m_dep(dep) {
 | 
			
		||||
                    m_lhs.push_back(l);
 | 
			
		||||
                    m_rhs.push_back(r);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            ne2(ne2 const& other): 
 | 
			
		||||
                m_lhs(other.m_lhs), m_rhs(other.m_rhs), m_lits(other.m_lits), m_dep(other.m_dep) {}
 | 
			
		||||
 | 
			
		||||
            ne2& operator=(ne2 const& other) { 
 | 
			
		||||
                if (this != &other) {
 | 
			
		||||
                    m_lhs.reset();  m_lhs.append(other.m_lhs);
 | 
			
		||||
                    m_rhs.reset();  m_rhs.append(other.m_rhs); 
 | 
			
		||||
                    m_lits.reset(); m_lits.append(other.m_lits); 
 | 
			
		||||
                    m_dep = other.m_dep; 
 | 
			
		||||
                }
 | 
			
		||||
                return *this; 
 | 
			
		||||
            }            
 | 
			
		||||
            vector<expr_ref_vector> const& ls() const { return m_lhs; }
 | 
			
		||||
            vector<expr_ref_vector> const& rs() const { return m_rhs; }
 | 
			
		||||
            expr_ref_vector const& ls(unsigned i) const { return m_lhs[i]; }
 | 
			
		||||
            expr_ref_vector const& rs(unsigned i) const { return m_rhs[i]; }
 | 
			
		||||
            literal_vector const& lits() const { return m_lits; }
 | 
			
		||||
            literal lits(unsigned i) const { return m_lits[i]; }
 | 
			
		||||
            dependency* dep() const { return m_dep; }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
        // asserted or derived disqequality with dependencies
 | 
			
		||||
        struct ne {
 | 
			
		||||
            bool                   m_solved;
 | 
			
		||||
            expr_ref               m_l, m_r;
 | 
			
		||||
            expr_ref_vector        m_lhs;
 | 
			
		||||
            expr_ref_vector        m_rhs;
 | 
			
		||||
            literal_vector         m_lits;
 | 
			
		||||
            dependency* m_dep;
 | 
			
		||||
            ne(expr_ref& l, expr_ref& r):
 | 
			
		||||
                m_solved(false), m_l(l), m_r(r), m_lhs(l.get_manager()), m_rhs(r.get_manager()), m_dep(0) {
 | 
			
		||||
                m_lhs.push_back(l);
 | 
			
		||||
                m_rhs.push_back(r);
 | 
			
		||||
            }
 | 
			
		||||
            ne(ne const& other): 
 | 
			
		||||
                m_solved(other.m_solved), m_l(other.m_l), m_r(other.m_r), m_lhs(other.m_lhs), m_rhs(other.m_rhs), m_lits(other.m_lits), m_dep(other.m_dep) {}
 | 
			
		||||
            ne& operator=(ne const& other) { 
 | 
			
		||||
                m_solved = other.m_solved;
 | 
			
		||||
                m_l = other.m_l;
 | 
			
		||||
                m_r = other.m_r;
 | 
			
		||||
                m_lhs.reset();  m_lhs.append(other.m_lhs);
 | 
			
		||||
                m_rhs.reset();  m_rhs.append(other.m_rhs); 
 | 
			
		||||
                m_lits.reset(); m_lits.append(other.m_lits); 
 | 
			
		||||
                m_dep = other.m_dep; 
 | 
			
		||||
                return *this; 
 | 
			
		||||
            }            
 | 
			
		||||
            bool is_solved() const { return m_solved; }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class pop_lit : public trail<theory_seq> { 
 | 
			
		||||
            unsigned m_idx;
 | 
			
		||||
            literal  m_lit;
 | 
			
		||||
        public:
 | 
			
		||||
            pop_lit(theory_seq& th, unsigned idx): m_idx(idx), m_lit(th.m_nqs[idx].m_lits.back()) {
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_lits.pop_back();
 | 
			
		||||
            }
 | 
			
		||||
            virtual void undo(theory_seq & th) { th.m_nqs.ref(m_idx).m_lits.push_back(m_lit); }
 | 
			
		||||
        };
 | 
			
		||||
        class push_lit : public trail<theory_seq> {
 | 
			
		||||
            unsigned m_idx;
 | 
			
		||||
        public:
 | 
			
		||||
            push_lit(theory_seq& th, unsigned idx, literal lit): m_idx(idx) {
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_lits.push_back(lit);
 | 
			
		||||
            }
 | 
			
		||||
            virtual void undo(theory_seq & th) { th.m_nqs.ref(m_idx).m_lits.pop_back(); }
 | 
			
		||||
        };  
 | 
			
		||||
        class set_lit : public trail<theory_seq> {
 | 
			
		||||
            unsigned m_idx;
 | 
			
		||||
            unsigned m_i;
 | 
			
		||||
            literal  m_lit;
 | 
			
		||||
        public:
 | 
			
		||||
            set_lit(theory_seq& th, unsigned idx, unsigned i, literal lit): 
 | 
			
		||||
                m_idx(idx), m_i(i), m_lit(th.m_nqs[idx].m_lits[i]) {
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_lits[i] = lit;
 | 
			
		||||
            }
 | 
			
		||||
            virtual void undo(theory_seq & th) { th.m_nqs.ref(m_idx).m_lits[m_i] = m_lit; }            
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class solved_ne : public trail<theory_seq> {
 | 
			
		||||
            unsigned m_idx;
 | 
			
		||||
        public:
 | 
			
		||||
            solved_ne(theory_seq& th, unsigned idx) : m_idx(idx) { th.m_nqs.ref(idx).m_solved = true; }
 | 
			
		||||
            virtual void undo(theory_seq& th) { th.m_nqs.ref(m_idx).m_solved = false;  }
 | 
			
		||||
        };
 | 
			
		||||
        void mark_solved(unsigned idx);
 | 
			
		||||
 | 
			
		||||
        class push_ne : public trail<theory_seq> {
 | 
			
		||||
            unsigned m_idx;
 | 
			
		||||
        public:
 | 
			
		||||
            push_ne(theory_seq& th, unsigned idx, expr* l, expr* r) : m_idx(idx) {
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_lhs.push_back(l);
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_rhs.push_back(r);
 | 
			
		||||
            }
 | 
			
		||||
            virtual void undo(theory_seq& th) { th.m_nqs.ref(m_idx).m_lhs.pop_back(); th.m_nqs.ref(m_idx).m_rhs.pop_back(); }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class pop_ne : public trail<theory_seq> {
 | 
			
		||||
            expr_ref m_lhs;
 | 
			
		||||
            expr_ref m_rhs;
 | 
			
		||||
            unsigned m_idx;
 | 
			
		||||
        public:
 | 
			
		||||
            pop_ne(theory_seq& th, unsigned idx): 
 | 
			
		||||
                m_lhs(th.m_nqs[idx].m_lhs.back(), th.m),
 | 
			
		||||
                m_rhs(th.m_nqs[idx].m_rhs.back(), th.m),
 | 
			
		||||
                m_idx(idx) {
 | 
			
		||||
                th.m_nqs.ref(idx).m_lhs.pop_back();
 | 
			
		||||
                th.m_nqs.ref(idx).m_rhs.pop_back();
 | 
			
		||||
            }
 | 
			
		||||
            virtual void undo(theory_seq& th) { 
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_lhs.push_back(m_lhs);
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_rhs.push_back(m_rhs); 
 | 
			
		||||
                m_lhs.reset();
 | 
			
		||||
                m_rhs.reset();
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class set_ne : public trail<theory_seq> {
 | 
			
		||||
            expr_ref m_lhs;
 | 
			
		||||
            expr_ref m_rhs;
 | 
			
		||||
            unsigned m_idx;
 | 
			
		||||
            unsigned m_i;
 | 
			
		||||
        public:
 | 
			
		||||
            set_ne(theory_seq& th, unsigned idx, unsigned i, expr* l, expr* r): 
 | 
			
		||||
                m_lhs(th.m_nqs[idx].m_lhs[i], th.m),
 | 
			
		||||
                m_rhs(th.m_nqs[idx].m_rhs[i], th.m),
 | 
			
		||||
                m_idx(idx),
 | 
			
		||||
                m_i(i) {
 | 
			
		||||
                th.m_nqs.ref(idx).m_lhs[i] = l;
 | 
			
		||||
                th.m_nqs.ref(idx).m_rhs[i] = r;
 | 
			
		||||
            }
 | 
			
		||||
            virtual void undo(theory_seq& th) { 
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_lhs[m_i] = m_lhs;
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_rhs[m_i] = m_rhs;
 | 
			
		||||
                m_lhs.reset();
 | 
			
		||||
                m_rhs.reset();
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class push_dep : public trail<theory_seq> {
 | 
			
		||||
            dependency* m_dep;
 | 
			
		||||
            unsigned m_idx;
 | 
			
		||||
        public:
 | 
			
		||||
            push_dep(theory_seq& th, unsigned idx, dependency* d): m_dep(th.m_nqs[idx].m_dep), m_idx(idx) {
 | 
			
		||||
                th.m_nqs.ref(idx).m_dep = d;
 | 
			
		||||
            }
 | 
			
		||||
            virtual void undo(theory_seq& th) {
 | 
			
		||||
                th.m_nqs.ref(m_idx).m_dep = m_dep;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class apply {
 | 
			
		||||
        public:
 | 
			
		||||
            virtual ~apply() {}
 | 
			
		||||
            virtual void operator()(theory_seq& th) = 0;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class replay_length_coherence : public apply {
 | 
			
		||||
            expr_ref m_e;
 | 
			
		||||
        public:
 | 
			
		||||
            replay_length_coherence(ast_manager& m, expr* e) : m_e(e, m) {}
 | 
			
		||||
            virtual void operator()(theory_seq& th) {
 | 
			
		||||
                th.check_length_coherence(m_e);
 | 
			
		||||
                m_e.reset();
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class replay_axiom : public apply {
 | 
			
		||||
            expr_ref m_e;
 | 
			
		||||
        public:
 | 
			
		||||
            replay_axiom(ast_manager& m, expr* e) : m_e(e, m) {}
 | 
			
		||||
            virtual void operator()(theory_seq& th) {
 | 
			
		||||
                th.enque_axiom(m_e);
 | 
			
		||||
                m_e.reset();
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class push_replay : public trail<theory_seq> {
 | 
			
		||||
            apply* m_apply;
 | 
			
		||||
        public:
 | 
			
		||||
            push_replay(apply* app): m_apply(app) {}
 | 
			
		||||
            virtual void undo(theory_seq& th) {
 | 
			
		||||
                th.m_replay.push_back(m_apply);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class pop_branch : public trail<theory_seq> {
 | 
			
		||||
            unsigned k;
 | 
			
		||||
        public:
 | 
			
		||||
            pop_branch(unsigned k): k(k) {}
 | 
			
		||||
            virtual void undo(theory_seq& th) {
 | 
			
		||||
                th.m_branch_start.erase(k);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        void erase_index(unsigned idx, unsigned i);
 | 
			
		||||
 | 
			
		||||
        struct stats {
 | 
			
		||||
            stats() { reset(); }
 | 
			
		||||
            void reset() { memset(this, 0, sizeof(stats)); }
 | 
			
		||||
            unsigned m_num_splits;
 | 
			
		||||
            unsigned m_num_reductions;
 | 
			
		||||
            unsigned m_propagate_automata;
 | 
			
		||||
            unsigned m_check_length_coherence;
 | 
			
		||||
            unsigned m_branch_variable;
 | 
			
		||||
            unsigned m_solve_nqs;
 | 
			
		||||
            unsigned m_solve_eqs;
 | 
			
		||||
            unsigned m_add_axiom;
 | 
			
		||||
        };
 | 
			
		||||
        ast_manager&                        m;
 | 
			
		||||
        enode_pair_dependency_manager       m_dm;
 | 
			
		||||
        solution_map                        m_rep;        // unification representative.
 | 
			
		||||
        scoped_vector<eq>                   m_eqs;        // set of current equations.
 | 
			
		||||
        ast_manager&               m;
 | 
			
		||||
        dependency_manager         m_dm;
 | 
			
		||||
        solution_map               m_rep;        // unification representative.
 | 
			
		||||
        scoped_vector<eq>          m_eqs;        // set of current equations.
 | 
			
		||||
        scoped_vector<ne>          m_nqs;        // set of current disequalities.
 | 
			
		||||
        unsigned                   m_eq_id;
 | 
			
		||||
 | 
			
		||||
        seq_factory*    m_factory;               // value factory
 | 
			
		||||
        expr_ref_vector m_ineqs;                 // inequalities to check solution against
 | 
			
		||||
        exclusion_table m_exclude;               // set of asserted disequalities.
 | 
			
		||||
        expr_ref_vector m_axioms;                // list of axioms to add.
 | 
			
		||||
        unsigned        m_axioms_head;           // index of first axiom to add.
 | 
			
		||||
        unsigned        m_branch_variable_head;  // index of first equation to examine.
 | 
			
		||||
        bool            m_incomplete;            // is the solver (clearly) incomplete for the fragment.
 | 
			
		||||
        bool            m_has_length;            // is length applied
 | 
			
		||||
        bool            m_model_completion;      // during model construction, invent values in canonizer
 | 
			
		||||
        th_rewriter     m_rewrite;
 | 
			
		||||
        seq_util        m_util;
 | 
			
		||||
        arith_util      m_autil;
 | 
			
		||||
        th_trail_stack  m_trail_stack;
 | 
			
		||||
        stats           m_stats;
 | 
			
		||||
        symbol          m_prefix_sym;
 | 
			
		||||
        symbol          m_suffix_sym;
 | 
			
		||||
        symbol          m_contains_left_sym;
 | 
			
		||||
        symbol          m_contains_right_sym;
 | 
			
		||||
        symbol          m_left_sym;               // split variable left part
 | 
			
		||||
        symbol          m_right_sym;              // split variable right part
 | 
			
		||||
        seq_factory*               m_factory;    // value factory
 | 
			
		||||
        exclusion_table            m_exclude;    // set of asserted disequalities.
 | 
			
		||||
        expr_ref_vector            m_axioms;     // list of axioms to add.
 | 
			
		||||
        obj_hashtable<expr>        m_axiom_set;
 | 
			
		||||
        unsigned                   m_axioms_head; // index of first axiom to add.
 | 
			
		||||
        bool            m_incomplete;             // is the solver (clearly) incomplete for the fragment.
 | 
			
		||||
        obj_hashtable<expr> m_length;             // is length applied
 | 
			
		||||
        scoped_ptr_vector<apply> m_replay;        // set of actions to replay
 | 
			
		||||
        model_generator* m_mg;
 | 
			
		||||
        th_rewriter      m_rewrite;
 | 
			
		||||
        seq_rewriter     m_seq_rewrite;
 | 
			
		||||
        seq_util         m_util;
 | 
			
		||||
        arith_util       m_autil;
 | 
			
		||||
        th_trail_stack   m_trail_stack;
 | 
			
		||||
        stats            m_stats;
 | 
			
		||||
        symbol           m_prefix, m_suffix, m_contains_left, m_contains_right, m_accept, m_reject;
 | 
			
		||||
        symbol           m_tail, m_nth, m_seq_first, m_seq_last, m_indexof_left, m_indexof_right, m_aut_step;
 | 
			
		||||
        symbol           m_extract_prefix, m_at_left, m_at_right;
 | 
			
		||||
        ptr_vector<expr> m_todo;
 | 
			
		||||
        expr_ref_vector  m_ls, m_rs, m_lhs, m_rhs;
 | 
			
		||||
 | 
			
		||||
        // maintain automata with regular expressions.
 | 
			
		||||
        scoped_ptr_vector<eautomaton>  m_automata;
 | 
			
		||||
        obj_map<expr, eautomaton*>     m_re2aut;
 | 
			
		||||
 | 
			
		||||
        // queue of asserted atoms
 | 
			
		||||
        ptr_vector<expr>               m_atoms;
 | 
			
		||||
        unsigned_vector                m_atoms_lim;
 | 
			
		||||
        unsigned                       m_atoms_qhead;
 | 
			
		||||
        bool                           m_new_solution;     // new solution added
 | 
			
		||||
        bool                           m_new_propagation;  // new propagation to core
 | 
			
		||||
 | 
			
		||||
        virtual final_check_status final_check_eh();
 | 
			
		||||
        virtual bool internalize_atom(app*, bool);
 | 
			
		||||
        virtual bool internalize_atom(app* atom, bool) { return internalize_term(atom); }
 | 
			
		||||
        virtual bool internalize_term(app*);
 | 
			
		||||
        virtual void internalize_eq_eh(app * atom, bool_var v);
 | 
			
		||||
        virtual void internalize_eq_eh(app * atom, bool_var v) {}
 | 
			
		||||
        virtual void new_eq_eh(theory_var, theory_var);
 | 
			
		||||
        virtual void new_diseq_eh(theory_var, theory_var);
 | 
			
		||||
        virtual void assign_eq(bool_var v, bool is_true);        
 | 
			
		||||
        virtual void assign_eh(bool_var v, bool is_true);        
 | 
			
		||||
        virtual bool can_propagate();
 | 
			
		||||
        virtual void propagate();
 | 
			
		||||
        virtual void push_scope_eh();
 | 
			
		||||
| 
						 | 
				
			
			@ -159,40 +424,61 @@ namespace smt {
 | 
			
		|||
        virtual void init_model(model_generator & mg);
 | 
			
		||||
 | 
			
		||||
        // final check 
 | 
			
		||||
        bool check_ineqs();              // check if inequalities are violated.
 | 
			
		||||
        bool simplify_and_solve_eqs();   // solve unitary equalities
 | 
			
		||||
        bool branch_variable();          // branch on a variable
 | 
			
		||||
        bool split_variable();           // split a variable
 | 
			
		||||
        bool is_solved(); 
 | 
			
		||||
        bool check_length_coherence();
 | 
			
		||||
        bool check_length_coherence_tbd();  
 | 
			
		||||
        bool check_ineq_coherence(); 
 | 
			
		||||
        bool check_length_coherence(expr* e);
 | 
			
		||||
        bool propagate_length_coherence(expr* e);  
 | 
			
		||||
 | 
			
		||||
        bool pre_process_eqs(bool simplify_or_solve);
 | 
			
		||||
        bool simplify_eqs();
 | 
			
		||||
        bool simplify_eq(expr* l, expr* r, enode_pair_dependency* dep);
 | 
			
		||||
        bool solve_unit_eq(expr* l, expr* r, enode_pair_dependency* dep);
 | 
			
		||||
        bool solve_basic_eqs();
 | 
			
		||||
        bool solve_eqs(unsigned start);
 | 
			
		||||
        bool solve_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep);
 | 
			
		||||
        bool simplify_eq(expr_ref_vector& l, expr_ref_vector& r, dependency* dep);
 | 
			
		||||
        bool solve_unit_eq(expr* l, expr* r, dependency* dep);
 | 
			
		||||
        bool solve_unit_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep);
 | 
			
		||||
        bool is_binary_eq(expr_ref_vector const& l, expr_ref_vector const& r, expr*& x, ptr_vector<expr>& xunits, ptr_vector<expr>& yunits, expr*& y);
 | 
			
		||||
        bool solve_binary_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep);
 | 
			
		||||
        bool propagate_max_length(expr* l, expr* r, dependency* dep);
 | 
			
		||||
 | 
			
		||||
        expr_ref mk_concat(unsigned n, expr*const* es) { return expr_ref(m_util.str.mk_concat(n, es), m); }
 | 
			
		||||
        expr_ref mk_concat(expr_ref_vector const& es) { return mk_concat(es.size(), es.c_ptr()); }
 | 
			
		||||
        expr_ref mk_concat(expr* e1, expr* e2) { return expr_ref(m_util.str.mk_concat(e1, e2), m); }
 | 
			
		||||
        expr_ref mk_concat(expr* e1, expr* e2, expr* e3) { return expr_ref(m_util.str.mk_concat(e1, e2, e3), m); }
 | 
			
		||||
        bool solve_nqs(unsigned i);
 | 
			
		||||
        void solve_ne(unsigned i);
 | 
			
		||||
 | 
			
		||||
        // asserting consequences
 | 
			
		||||
        void propagate_lit(enode_pair_dependency* dep, literal lit);
 | 
			
		||||
        void propagate_eq(enode_pair_dependency* dep, enode* n1, enode* n2);
 | 
			
		||||
        void propagate_eq(bool_var v, expr* e1, expr* e2);
 | 
			
		||||
        void set_conflict(enode_pair_dependency* dep);
 | 
			
		||||
        void linearize(dependency* dep, enode_pair_vector& eqs, literal_vector& lits) const;
 | 
			
		||||
        void propagate_lit(dependency* dep, literal lit) { propagate_lit(dep, 0, 0, lit); }
 | 
			
		||||
        void propagate_lit(dependency* dep, unsigned n, literal const* lits, literal lit);
 | 
			
		||||
        void propagate_eq(dependency* dep, enode* n1, enode* n2);
 | 
			
		||||
        void propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs = false);
 | 
			
		||||
        void set_conflict(dependency* dep, literal_vector const& lits = literal_vector());
 | 
			
		||||
 | 
			
		||||
        bool find_branch_candidate(expr* l, ptr_vector<expr> const& rs);
 | 
			
		||||
        bool assume_equality(expr* l, expr* r);
 | 
			
		||||
        u_map<unsigned> m_branch_start;
 | 
			
		||||
        void insert_branch_start(unsigned k, unsigned s);
 | 
			
		||||
        unsigned find_branch_start(unsigned k);
 | 
			
		||||
        bool find_branch_candidate(unsigned& start, dependency* dep, expr_ref_vector const& ls, expr_ref_vector const& rs);
 | 
			
		||||
        bool can_be_equal(unsigned szl, expr* const* ls, unsigned szr, expr* const* rs) const;
 | 
			
		||||
        lbool assume_equality(expr* l, expr* r);
 | 
			
		||||
 | 
			
		||||
        // variable solving utilities
 | 
			
		||||
        bool occurs(expr* a, expr* b);
 | 
			
		||||
        bool occurs(expr* a, expr_ref_vector const& b);
 | 
			
		||||
        bool is_var(expr* b);
 | 
			
		||||
        void add_solution(expr* l, expr* r, enode_pair_dependency* dep);
 | 
			
		||||
        bool is_left_select(expr* a, expr*& b);
 | 
			
		||||
        bool is_right_select(expr* a, expr*& b);
 | 
			
		||||
        expr_ref canonize(expr* e, enode_pair_dependency*& eqs);
 | 
			
		||||
        expr_ref expand(expr* e, enode_pair_dependency*& eqs);
 | 
			
		||||
        void add_dependency(enode_pair_dependency*& dep, enode* a, enode* b);
 | 
			
		||||
        bool add_solution(expr* l, expr* r, dependency* dep);
 | 
			
		||||
        bool is_nth(expr* a) const;
 | 
			
		||||
        bool is_tail(expr* a, expr*& s, unsigned& idx) const;
 | 
			
		||||
        expr_ref mk_nth(expr* s, expr* idx);
 | 
			
		||||
        expr_ref mk_last(expr* e);
 | 
			
		||||
        expr_ref canonize(expr* e, dependency*& eqs);
 | 
			
		||||
        bool canonize(expr* e, expr_ref_vector& es, dependency*& eqs);
 | 
			
		||||
        bool canonize(expr_ref_vector const& es, expr_ref_vector& result, dependency*& eqs);
 | 
			
		||||
        expr_ref expand(expr* e, dependency*& eqs);
 | 
			
		||||
        void add_dependency(dependency*& dep, enode* a, enode* b);
 | 
			
		||||
 | 
			
		||||
        void get_concat(expr* e, ptr_vector<expr>& concats);
 | 
			
		||||
    
 | 
			
		||||
        // terms whose meaning are encoded using axioms.
 | 
			
		||||
        void enque_axiom(expr* e);
 | 
			
		||||
| 
						 | 
				
			
			@ -202,28 +488,80 @@ namespace smt {
 | 
			
		|||
        void add_replace_axiom(expr* e);
 | 
			
		||||
        void add_extract_axiom(expr* e);
 | 
			
		||||
        void add_length_axiom(expr* n);
 | 
			
		||||
        void add_length_unit_axiom(expr* n);
 | 
			
		||||
        void add_length_empty_axiom(expr* n);
 | 
			
		||||
        void add_length_concat_axiom(expr* n);
 | 
			
		||||
        void add_length_string_axiom(expr* n);
 | 
			
		||||
 | 
			
		||||
        bool has_length(expr *e) const { return m_length.contains(e); }
 | 
			
		||||
        void add_length(expr* e);
 | 
			
		||||
        void enforce_length(enode* n);
 | 
			
		||||
        void enforce_length_coherence(enode* n1, enode* n2);
 | 
			
		||||
 | 
			
		||||
        void add_elim_string_axiom(expr* n);
 | 
			
		||||
        void add_at_axiom(expr* n);
 | 
			
		||||
        void add_in_re_axiom(expr* n);
 | 
			
		||||
        literal mk_literal(expr* n);
 | 
			
		||||
        literal mk_eq_empty(expr* n);
 | 
			
		||||
        literal mk_equals(expr* a, expr* b);
 | 
			
		||||
        void tightest_prefix(expr* s, expr* x, literal lit, literal lit2 = null_literal);
 | 
			
		||||
        expr* mk_sub(expr* a, expr* b);
 | 
			
		||||
        expr_ref mk_sub(expr* a, expr* b);
 | 
			
		||||
        enode* ensure_enode(expr* a);
 | 
			
		||||
 | 
			
		||||
        // arithmetic integration
 | 
			
		||||
        bool lower_bound(expr* s, rational& lo);
 | 
			
		||||
        bool upper_bound(expr* s, rational& hi);
 | 
			
		||||
        bool get_length(expr* s, rational& val);
 | 
			
		||||
 | 
			
		||||
        void mk_decompose(expr* e, expr_ref& head, expr_ref& tail);
 | 
			
		||||
        expr_ref mk_skolem(symbol const& s, expr* e1, expr* e2 = 0, expr* e3 = 0, sort* range = 0);
 | 
			
		||||
        bool is_skolem(symbol const& s, expr* e) const;
 | 
			
		||||
 | 
			
		||||
        void set_incomplete(app* term);
 | 
			
		||||
 | 
			
		||||
        // automata utilities
 | 
			
		||||
        void propagate_in_re(expr* n, bool is_true);
 | 
			
		||||
        eautomaton* get_automaton(expr* e);
 | 
			
		||||
        literal mk_accept(expr* s, expr* idx, expr* re, expr* state);
 | 
			
		||||
        literal mk_accept(expr* s, expr* idx, expr* re, unsigned i) { return mk_accept(s, idx, re, m_autil.mk_int(i)); }
 | 
			
		||||
        bool is_accept(expr* acc) const {  return is_skolem(m_accept, acc); }
 | 
			
		||||
        bool is_accept(expr* acc, expr*& s, expr*& idx, expr*& re, unsigned& i, eautomaton*& aut) {
 | 
			
		||||
            return is_acc_rej(m_accept, acc, s, idx, re, i, aut);
 | 
			
		||||
        }
 | 
			
		||||
        literal mk_reject(expr* s, expr* idx, expr* re, expr* state);
 | 
			
		||||
        literal mk_reject(expr* s, expr* idx, expr* re, unsigned i) { return mk_reject(s, idx, re, m_autil.mk_int(i)); }
 | 
			
		||||
        bool is_reject(expr* rej) const {  return is_skolem(m_reject, rej); }
 | 
			
		||||
        bool is_reject(expr* rej, expr*& s, expr*& idx, expr*& re, unsigned& i, eautomaton*& aut) {
 | 
			
		||||
            return is_acc_rej(m_reject, rej, s, idx, re, i, aut);
 | 
			
		||||
        }
 | 
			
		||||
        bool is_acc_rej(symbol const& ar, expr* e, expr*& s, expr*& idx, expr*& re, unsigned& i, eautomaton*& aut);
 | 
			
		||||
        expr_ref mk_step(expr* s, expr* tail, expr* re, unsigned i, unsigned j, expr* t);
 | 
			
		||||
        bool is_step(expr* e, expr*& s, expr*& tail, expr*& re, expr*& i, expr*& j, expr*& t) const;
 | 
			
		||||
        bool is_step(expr* e) const;
 | 
			
		||||
        void propagate_step(literal lit, expr* n);
 | 
			
		||||
        bool add_reject2reject(expr* rej);
 | 
			
		||||
        bool add_accept2step(expr* acc);       
 | 
			
		||||
        bool add_step2accept(expr* step);
 | 
			
		||||
        bool add_prefix2prefix(expr* e);
 | 
			
		||||
        bool add_suffix2suffix(expr* e);
 | 
			
		||||
        bool add_contains2contains(expr* e);
 | 
			
		||||
        void ensure_nth(literal lit, expr* s, expr* idx);
 | 
			
		||||
        bool canonizes(bool sign, expr* e);
 | 
			
		||||
        void propagate_non_empty(literal lit, expr* s);
 | 
			
		||||
        void propagate_is_conc(expr* e, expr* conc);
 | 
			
		||||
        void propagate_acc_rej_length(literal lit, expr* acc_rej);
 | 
			
		||||
        bool propagate_automata();
 | 
			
		||||
        void add_atom(expr* e);
 | 
			
		||||
        void new_eq_eh(dependency* dep, enode* n1, enode* n2);
 | 
			
		||||
 | 
			
		||||
        // diagnostics
 | 
			
		||||
        void display_equations(std::ostream& out) const;
 | 
			
		||||
        void display_deps(std::ostream& out, enode_pair_dependency* deps) const;
 | 
			
		||||
        void display_disequations(std::ostream& out) const;
 | 
			
		||||
        void display_disequation(std::ostream& out, ne const& e) const;
 | 
			
		||||
        void display_deps(std::ostream& out, dependency* deps) const;
 | 
			
		||||
    public:
 | 
			
		||||
        theory_seq(ast_manager& m);
 | 
			
		||||
        virtual ~theory_seq();
 | 
			
		||||
 | 
			
		||||
        // model building
 | 
			
		||||
        app* mk_value(app* a);
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ namespace smt {
 | 
			
		|||
        seq_util     u;
 | 
			
		||||
        symbol_set   m_strings;
 | 
			
		||||
        unsigned     m_next;
 | 
			
		||||
        char         m_char;
 | 
			
		||||
        std::string  m_unique_prefix;
 | 
			
		||||
        obj_map<sort, expr*> m_unique_sequences;
 | 
			
		||||
        expr_ref_vector m_trail;
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +42,7 @@ namespace smt {
 | 
			
		|||
            m_model(md),
 | 
			
		||||
            u(m),
 | 
			
		||||
            m_next(0),
 | 
			
		||||
            m_char(0),
 | 
			
		||||
            m_unique_prefix("#B"),
 | 
			
		||||
            m_trail(m)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +101,11 @@ namespace smt {
 | 
			
		|||
                expr* v0 = get_fresh_value(seq);
 | 
			
		||||
                return u.re.mk_to_re(v0);
 | 
			
		||||
            }
 | 
			
		||||
            if (u.is_char(s)) {
 | 
			
		||||
                //char s[2] = { ++m_char, 0 };
 | 
			
		||||
                //return u.str.mk_char(zstring(s), 0);
 | 
			
		||||
                return u.str.mk_char(zstring("a"), 0);
 | 
			
		||||
            }
 | 
			
		||||
            NOT_IMPLEMENTED_YET();
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -366,7 +366,7 @@ struct purify_arith_proc {
 | 
			
		|||
                    push_cnstr(EQ(x, u().mk_power(k, u().mk_numeral(n, false))));
 | 
			
		||||
                    push_cnstr_pr(result_pr);
 | 
			
		||||
                }
 | 
			
		||||
                else if (complete()) {
 | 
			
		||||
                else {
 | 
			
		||||
                    SASSERT(n.is_even());
 | 
			
		||||
                    // (^ x (/ 1 n)) --> k  |  x >= 0 implies (x = k^n and k >= 0), x < 0 implies k = neg-root(x, n)   
 | 
			
		||||
                    // when n is even
 | 
			
		||||
| 
						 | 
				
			
			@ -379,9 +379,9 @@ struct purify_arith_proc {
 | 
			
		|||
                                  EQ(k, u().mk_neg_root(x, u().mk_numeral(n, false)))));
 | 
			
		||||
                    push_cnstr_pr(result_pr);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    return BR_FAILED;
 | 
			
		||||
                }
 | 
			
		||||
//                else {
 | 
			
		||||
//                    return BR_FAILED;
 | 
			
		||||
//                }
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                // root not supported for integers.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,32 +1,33 @@
 | 
			
		|||
/*++
 | 
			
		||||
 /*++
 | 
			
		||||
Copyright (c) 2011 Microsoft Corporation
 | 
			
		||||
 
 | 
			
		||||
Module Name:
 | 
			
		||||
 Module Name:
 | 
			
		||||
 
 | 
			
		||||
    bit_blaster_tactic.h
 | 
			
		||||
 
 | 
			
		||||
Abstract:
 | 
			
		||||
 Abstract:
 | 
			
		||||
 
 | 
			
		||||
    Apply bit-blasting to a given goal.
 | 
			
		||||
 
 | 
			
		||||
Author:
 | 
			
		||||
 Author:
 | 
			
		||||
 
 | 
			
		||||
    Leonardo (leonardo) 2011-10-25
 | 
			
		||||
 
 | 
			
		||||
Notes:
 | 
			
		||||
 Notes:
 | 
			
		||||
 
 | 
			
		||||
--*/
 | 
			
		||||
 --*/
 | 
			
		||||
#ifndef BIT_BLASTER_TACTIC_H_
 | 
			
		||||
#define BIT_BLASTER_TACTIC_H_
 | 
			
		||||
 
 | 
			
		||||
#include"params.h"
 | 
			
		||||
#include"bit_blaster_rewriter.h"
 | 
			
		||||
class ast_manager;
 | 
			
		||||
class tactic;
 | 
			
		||||
 #include"params.h"
 | 
			
		||||
 #include"bit_blaster_rewriter.h"
 | 
			
		||||
 class ast_manager;
 | 
			
		||||
 class tactic;
 | 
			
		||||
 
 | 
			
		||||
tactic * mk_bit_blaster_tactic(ast_manager & m, params_ref const & p = params_ref());
 | 
			
		||||
tactic * mk_bit_blaster_tactic(ast_manager & m, bit_blaster_rewriter* rw, params_ref const & p = params_ref());
 | 
			
		||||
/*
 | 
			
		||||
 /*
 | 
			
		||||
  ADD_TACTIC("bit-blast", "reduce bit-vector expressions into SAT.", "mk_bit_blaster_tactic(m, p)")
 | 
			
		||||
*/
 | 
			
		||||
#endif
 | 
			
		||||
 */
 | 
			
		||||
 #endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ Revision History:
 | 
			
		|||
#include"occurs.h"
 | 
			
		||||
#include"cooperate.h"
 | 
			
		||||
#include"goal_shared_occs.h"
 | 
			
		||||
#include"ast_smt2_pp.h"
 | 
			
		||||
#include"ast_pp.h"
 | 
			
		||||
 | 
			
		||||
class solve_eqs_tactic : public tactic {
 | 
			
		||||
    struct imp {
 | 
			
		||||
| 
						 | 
				
			
			@ -92,21 +92,23 @@ class solve_eqs_tactic : public tactic {
 | 
			
		|||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Use: (= x def) and (= def x)
 | 
			
		||||
        bool trivial_solve(expr * lhs, expr * rhs, app_ref & var, expr_ref & def, proof_ref & pr) {
 | 
			
		||||
 | 
			
		||||
        bool trivial_solve1(expr * lhs, expr * rhs, app_ref & var, expr_ref & def, proof_ref & pr) { 
 | 
			
		||||
 | 
			
		||||
            if (is_uninterp_const(lhs) && !m_candidate_vars.is_marked(lhs) && !occurs(lhs, rhs) && check_occs(lhs)) {
 | 
			
		||||
                var = to_app(lhs); 
 | 
			
		||||
                def = rhs;
 | 
			
		||||
                pr  = 0;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            else if (is_uninterp_const(rhs) && !m_candidate_vars.is_marked(rhs) && !occurs(rhs, lhs) && check_occs(rhs)) {
 | 
			
		||||
                var = to_app(rhs);
 | 
			
		||||
                def = lhs;
 | 
			
		||||
                if (m_produce_proofs)
 | 
			
		||||
                    pr = m().mk_commutativity(m().mk_eq(lhs, rhs));
 | 
			
		||||
                return true;
 | 
			
		||||
            else {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        bool trivial_solve(expr * lhs, expr * rhs, app_ref & var, expr_ref & def, proof_ref & pr) {
 | 
			
		||||
            return 
 | 
			
		||||
                trivial_solve1(lhs, rhs, var, def, pr) ||
 | 
			
		||||
                trivial_solve1(rhs, lhs, var, def, pr);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // (ite c (= x t1) (= x t2)) --> (= x (ite c t1 t2))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,7 +132,7 @@ expr_ref fpa2bv_model_converter::convert_bv2fp(sort * s, expr * sgn, expr * exp,
 | 
			
		|||
    mpzm.set(sig_z, sig_q.to_mpq().numerator());
 | 
			
		||||
    exp_z = mpzm.get_int64(exp_unbiased_q.to_mpq().numerator());
 | 
			
		||||
 | 
			
		||||
    fu.fm().set(fp_val, ebits, sbits, !mpqm.is_zero(sgn_q.to_mpq()), sig_z, exp_z);
 | 
			
		||||
    fu.fm().set(fp_val, ebits, sbits, !mpqm.is_zero(sgn_q.to_mpq()), exp_z, sig_z);
 | 
			
		||||
 | 
			
		||||
    mpzm.del(sig_z);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -102,7 +102,8 @@ tactic * mk_lra_tactic(ast_manager & m, params_ref const & p) {
 | 
			
		|||
                           or_else(try_for(mk_smt_tactic(), 100), 
 | 
			
		||||
                                   try_for(qe::mk_sat_tactic(m), 1000), 
 | 
			
		||||
                                   try_for(mk_smt_tactic(), 1000),
 | 
			
		||||
                                   and_then(mk_qe_tactic(m), mk_smt_tactic())));
 | 
			
		||||
                                   and_then(mk_qe_tactic(m), mk_smt_tactic())
 | 
			
		||||
                                   ));
 | 
			
		||||
 | 
			
		||||
    st->updt_params(p);
 | 
			
		||||
    return st;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ Notes:
 | 
			
		|||
#include"algebraic_numbers.h"
 | 
			
		||||
#include"polynomial_var2value.h"
 | 
			
		||||
#include"mpbq.h"
 | 
			
		||||
#include"rlimit.h"
 | 
			
		||||
 | 
			
		||||
static void display_anums(std::ostream & out, scoped_anum_vector const & rs) {
 | 
			
		||||
    out << "numbers in decimal:\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -40,14 +41,15 @@ static void display_anums(std::ostream & out, scoped_anum_vector const & rs) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst1() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    polynomial_ref p(m);
 | 
			
		||||
    p = 3*x - 2;
 | 
			
		||||
 | 
			
		||||
    algebraic_numbers::manager am(nm);
 | 
			
		||||
    algebraic_numbers::manager am(rl, nm);
 | 
			
		||||
    scoped_anum_vector rs1(am);
 | 
			
		||||
    std::cout << "p: " << p << "\n";
 | 
			
		||||
    am.isolate_roots(p, rs1);
 | 
			
		||||
| 
						 | 
				
			
			@ -221,8 +223,9 @@ void tst_mpbq_root() {
 | 
			
		|||
 | 
			
		||||
static void tst_wilkinson() {
 | 
			
		||||
    // Test Wilkinson Polynomial
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    polynomial_ref p(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +237,7 @@ static void tst_wilkinson() {
 | 
			
		|||
    }
 | 
			
		||||
    std::cout << "Wilkinson's polynomial: " << p << "\n";
 | 
			
		||||
 | 
			
		||||
    algebraic_numbers::manager am(nm);
 | 
			
		||||
    algebraic_numbers::manager am(rl, nm);
 | 
			
		||||
    scoped_anum_vector rs1(am);
 | 
			
		||||
    std::cout << "p: " << p << "\n";
 | 
			
		||||
    am.isolate_roots(p, rs1);
 | 
			
		||||
| 
						 | 
				
			
			@ -246,8 +249,9 @@ static void tst_wilkinson() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_dejan() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager qm;
 | 
			
		||||
    algebraic_numbers::manager am(qm);
 | 
			
		||||
    algebraic_numbers::manager am(rl, qm);
 | 
			
		||||
 | 
			
		||||
    scoped_anum two101(am);
 | 
			
		||||
    am.set(two101, 2);
 | 
			
		||||
| 
						 | 
				
			
			@ -332,9 +336,10 @@ static void tst_eval_sign(polynomial_ref const & p, anum_manager & am,
 | 
			
		|||
 | 
			
		||||
static void tst_eval_sign() {
 | 
			
		||||
    enable_trace("anum_eval_sign");
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager        qm;
 | 
			
		||||
    polynomial::manager        pm(qm);
 | 
			
		||||
    algebraic_numbers::manager am(qm);
 | 
			
		||||
    polynomial::manager        pm(rl, qm);
 | 
			
		||||
    algebraic_numbers::manager am(rl, qm);
 | 
			
		||||
    polynomial_ref x0(pm);
 | 
			
		||||
    polynomial_ref x1(pm);
 | 
			
		||||
    polynomial_ref x2(pm);
 | 
			
		||||
| 
						 | 
				
			
			@ -412,9 +417,10 @@ static void tst_isolate_roots(polynomial_ref const & p, anum_manager & am,
 | 
			
		|||
 | 
			
		||||
static void tst_isolate_roots() {
 | 
			
		||||
    enable_trace("isolate_roots");
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager        qm;
 | 
			
		||||
    polynomial::manager        pm(qm);
 | 
			
		||||
    algebraic_numbers::manager am(qm);
 | 
			
		||||
    polynomial::manager        pm(rl, qm);
 | 
			
		||||
    algebraic_numbers::manager am(rl, qm);
 | 
			
		||||
    polynomial_ref x0(pm);
 | 
			
		||||
    polynomial_ref x1(pm);
 | 
			
		||||
    polynomial_ref x2(pm);
 | 
			
		||||
| 
						 | 
				
			
			@ -485,7 +491,8 @@ static void pp(polynomial_ref const & p, polynomial::var x) {
 | 
			
		|||
 | 
			
		||||
static void ex1() {
 | 
			
		||||
    unsynch_mpq_manager        qm;
 | 
			
		||||
    polynomial::manager        pm(qm);
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::manager        pm(rl, qm);
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    polynomial_ref a(pm);
 | 
			
		||||
    polynomial_ref b(pm);
 | 
			
		||||
| 
						 | 
				
			
			@ -508,7 +515,7 @@ static void ex1() {
 | 
			
		|||
    std::cout << "d: " << d << "\n";
 | 
			
		||||
    std::cout << "h3: "; pp(h3, 0); std::cout << "\n";
 | 
			
		||||
 | 
			
		||||
    algebraic_numbers::manager am(qm);
 | 
			
		||||
    algebraic_numbers::manager am(rl, qm);
 | 
			
		||||
    scoped_anum v1(am), v2(am);
 | 
			
		||||
    am.set(v1, 2);
 | 
			
		||||
    am.root(v1, 3, v1);
 | 
			
		||||
| 
						 | 
				
			
			@ -542,8 +549,9 @@ static void ex1() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_root() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager        qm;
 | 
			
		||||
    algebraic_numbers::manager am(qm);
 | 
			
		||||
    algebraic_numbers::manager am(rl, qm);
 | 
			
		||||
    scoped_anum v1(am), v2(am);
 | 
			
		||||
    am.set(v1, 4);
 | 
			
		||||
    am.root(v1, 2, v2);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ Copyright (c) 2015 Microsoft Corporation
 | 
			
		|||
#include "tactic.h"
 | 
			
		||||
#include "tactic2solver.h"
 | 
			
		||||
#include "solver.h"
 | 
			
		||||
#include "rlimit.h"
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +284,8 @@ static void saturate_basis(hilbert_basis& hb) {
 | 
			
		|||
static void gorrila_test(unsigned seed, unsigned n, unsigned k, unsigned bound, unsigned num_ineqs) {
 | 
			
		||||
    std::cout << "Gorrila test\n";
 | 
			
		||||
    random_gen rand(seed);
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    SASSERT(0 < bound);
 | 
			
		||||
    SASSERT(k <= n);
 | 
			
		||||
    int ibound = static_cast<int>(bound);
 | 
			
		||||
| 
						 | 
				
			
			@ -368,7 +370,8 @@ static vector<rational> vec(int i, int j, int k, int l, int x, int y, int z) {
 | 
			
		|||
// -y + z <= 0
 | 
			
		||||
 | 
			
		||||
static void tst1() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_eq(vec(1,1,-2));
 | 
			
		||||
    hb.add_eq(vec(1,0,-1));
 | 
			
		||||
    hb.add_le(vec(0,1,-1));
 | 
			
		||||
| 
						 | 
				
			
			@ -380,7 +383,8 @@ static void tst1() {
 | 
			
		|||
// 23x - 12y - 9z <= 0
 | 
			
		||||
// x   - 8y  - 8z <= 0
 | 
			
		||||
void tst2() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
 | 
			
		||||
    hb.add_eq(vec(-23,12,9));
 | 
			
		||||
    hb.add_eq(vec(-1,8,8));
 | 
			
		||||
| 
						 | 
				
			
			@ -391,7 +395,8 @@ void tst2() {
 | 
			
		|||
// example 6, Ajili, Contenjean
 | 
			
		||||
// 3x + 2y - z - 2u <= 0
 | 
			
		||||
static void tst3() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec(3,2,-1,-2));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -400,7 +405,8 @@ static void tst3() {
 | 
			
		|||
 | 
			
		||||
// Sigma_1, table 1, Ajili, Contejean
 | 
			
		||||
static void tst4() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec( 0,-2, 1, 3, 2,-2, 3), R(3));
 | 
			
		||||
    hb.add_le(vec(-1, 7, 0, 1, 3, 5,-4), R(2));
 | 
			
		||||
    hb.add_le(vec( 0,-1, 1,-1,-1, 0, 0), R(2));
 | 
			
		||||
| 
						 | 
				
			
			@ -416,7 +422,8 @@ static void tst4() {
 | 
			
		|||
 | 
			
		||||
// Sigma_2 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst5() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec( 1, 2,-1, 1), R(3));
 | 
			
		||||
    hb.add_le(vec( 2, 4, 1, 2), R(12));
 | 
			
		||||
    hb.add_le(vec( 1, 4, 2, 1), R(9));
 | 
			
		||||
| 
						 | 
				
			
			@ -429,7 +436,8 @@ static void tst5() {
 | 
			
		|||
 | 
			
		||||
// Sigma_3 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst6() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec( 4, 3, 0), R(6));
 | 
			
		||||
    hb.add_le(vec(-3,-4, 0), R(-1));
 | 
			
		||||
    hb.add_le(vec( 4, 0,-3), R(3));
 | 
			
		||||
| 
						 | 
				
			
			@ -441,7 +449,8 @@ static void tst6() {
 | 
			
		|||
 | 
			
		||||
// Sigma_4 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst7() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_eq(vec( 1, 1, 1, 0),  R(5));
 | 
			
		||||
    hb.add_le(vec( 2, 1, 0, 1),  R(6));
 | 
			
		||||
    hb.add_le(vec( 1, 2, 1, 1),  R(7));
 | 
			
		||||
| 
						 | 
				
			
			@ -454,7 +463,8 @@ static void tst7() {
 | 
			
		|||
 | 
			
		||||
// Sigma_5 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst8() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec( 2, 1, 1), R(2));
 | 
			
		||||
    hb.add_le(vec( 1, 2, 3), R(5));
 | 
			
		||||
    hb.add_le(vec( 2, 2, 3), R(6));
 | 
			
		||||
| 
						 | 
				
			
			@ -464,7 +474,8 @@ static void tst8() {
 | 
			
		|||
 | 
			
		||||
// Sigma_6 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst9() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec( 1, 2, 3), R(11));
 | 
			
		||||
    hb.add_le(vec( 2, 2, 5), R(13));
 | 
			
		||||
    hb.add_le(vec( 1,-1,-11), R(3));
 | 
			
		||||
| 
						 | 
				
			
			@ -473,7 +484,8 @@ static void tst9() {
 | 
			
		|||
 | 
			
		||||
// Sigma_7 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst10() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec( 1,-1,-1,-3), R(2));
 | 
			
		||||
    hb.add_le(vec(-2, 3, 3,-5), R(3));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
| 
						 | 
				
			
			@ -481,14 +493,16 @@ static void tst10() {
 | 
			
		|||
 | 
			
		||||
// Sigma_8 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst11() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec( 7,-2,11, 3, -5), R(5));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sigma_9 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst12() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_eq(vec( 1,-2,-3,4), R(0));
 | 
			
		||||
    hb.add_le(vec(100,45,-78,-67), R(0));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
| 
						 | 
				
			
			@ -496,34 +510,39 @@ static void tst12() {
 | 
			
		|||
 | 
			
		||||
// Sigma_10 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst13() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec( 23, -56, -34, 12, 11), R(0));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sigma_11 table 1,  Ajili, Contejean
 | 
			
		||||
static void tst14() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_eq(vec(1, 0, -4, 8), R(2));
 | 
			
		||||
    hb.add_le(vec(12,19,-11,-7), R(-7));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tst15() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec(1, 0), R(1));
 | 
			
		||||
    hb.add_le(vec(0, 1), R(1));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tst16() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_le(vec(1, 0), R(100));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tst17() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_eq(vec(1,  0), R(0));
 | 
			
		||||
    hb.add_eq(vec(-1, 0), R(0));
 | 
			
		||||
    hb.add_eq(vec(0,  2), R(0));
 | 
			
		||||
| 
						 | 
				
			
			@ -533,21 +552,24 @@ static void tst17() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst18() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_eq(vec(0, 1), R(0));
 | 
			
		||||
    hb.add_eq(vec(1, -1), R(2));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tst19() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    hb.add_eq(vec(0,  1, 0), R(0));
 | 
			
		||||
    hb.add_eq(vec(1, -1, 0), R(2));
 | 
			
		||||
    saturate_basis(hb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_A_5_5_3() {
 | 
			
		||||
    hilbert_basis hb;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    hilbert_basis hb(rl);
 | 
			
		||||
    for (unsigned i = 0; i < 15; ++i) {
 | 
			
		||||
        vector<rational> v;
 | 
			
		||||
        for (unsigned j = 0; j < 5; ++j) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ Revision History:
 | 
			
		|||
#include"mpq.h"
 | 
			
		||||
#include"ast.h"
 | 
			
		||||
#include"debug.h"
 | 
			
		||||
#include"rlimit.h"
 | 
			
		||||
 | 
			
		||||
template class interval_manager<im_default_config>;
 | 
			
		||||
typedef im_default_config::interval interval;
 | 
			
		||||
| 
						 | 
				
			
			@ -235,9 +236,10 @@ static void display_lemmas(unsynch_mpq_manager & nm, char const * result_term,
 | 
			
		|||
 | 
			
		||||
#define MK_BINARY(NAME, RES_TERM)                                       \
 | 
			
		||||
static void tst_ ## NAME(unsigned N, unsigned magnitude) {              \
 | 
			
		||||
    reslimit                            rl;                             \
 | 
			
		||||
    unsynch_mpq_manager                 nm;                             \
 | 
			
		||||
    im_default_config                   imc(nm);                        \
 | 
			
		||||
    interval_manager<im_default_config> im(imc);                        \
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);                    \
 | 
			
		||||
    interval a, b, r;                                                   \
 | 
			
		||||
                                                                        \
 | 
			
		||||
    for (unsigned i = 0; i < N; i++) {                                  \
 | 
			
		||||
| 
						 | 
				
			
			@ -256,9 +258,10 @@ MK_BINARY(add, "(+ a b)");
 | 
			
		|||
MK_BINARY(sub, "(- a b)");
 | 
			
		||||
 | 
			
		||||
static void tst_neg(unsigned N, unsigned magnitude) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    interval a, b, r;
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < N; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -271,9 +274,10 @@ static void tst_neg(unsigned N, unsigned magnitude) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_pw_2(unsigned N, unsigned magnitude) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    interval a, b, r;
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < N; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -286,9 +290,10 @@ static void tst_pw_2(unsigned N, unsigned magnitude) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_pw_3(unsigned N, unsigned magnitude) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    interval a, b, r;
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < N; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -301,9 +306,10 @@ static void tst_pw_3(unsigned N, unsigned magnitude) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_root_2(unsigned N, unsigned magnitude, unsigned precision) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    interval a, b, r;
 | 
			
		||||
    scoped_mpq                          p(nm);
 | 
			
		||||
    p = precision;
 | 
			
		||||
| 
						 | 
				
			
			@ -323,9 +329,10 @@ static void tst_root_2(unsigned N, unsigned magnitude, unsigned precision) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_root_3(unsigned N, unsigned magnitude, unsigned precision) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    interval a, b, r;
 | 
			
		||||
    scoped_mpq                          p(nm);
 | 
			
		||||
    p = precision;
 | 
			
		||||
| 
						 | 
				
			
			@ -343,9 +350,10 @@ static void tst_root_3(unsigned N, unsigned magnitude, unsigned precision) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_inv(unsigned N, unsigned magnitude) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    interval a, b, r;
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < N; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -362,9 +370,10 @@ static void tst_inv(unsigned N, unsigned magnitude) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_div(unsigned N, unsigned magnitude) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);                  
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    interval a, b, r;
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < N; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -420,9 +429,10 @@ static void tst_float() {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
void tst_pi() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    interval r;
 | 
			
		||||
    for (unsigned i = 0; i < 8; i++) {
 | 
			
		||||
        im.pi(i, r);
 | 
			
		||||
| 
						 | 
				
			
			@ -436,10 +446,11 @@ void tst_pi() {
 | 
			
		|||
#if 0
 | 
			
		||||
static void tst_pi_float() {
 | 
			
		||||
    std::cout << "pi float...\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager   qm;
 | 
			
		||||
    mpf_manager           fm;
 | 
			
		||||
    im_float_config<mpf_manager>                    ifc(fm, 22, 106);
 | 
			
		||||
    interval_manager<im_float_config<mpf_manager> > im(ifc);
 | 
			
		||||
    interval_manager<im_float_config<mpf_manager> > im(rl, ifc);
 | 
			
		||||
    scoped_mpq q(qm);
 | 
			
		||||
    im_float_config<mpf_manager>::interval r;
 | 
			
		||||
    for (unsigned i = 0; i < 8; i++) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
Copyright (c) 2015 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
#include"rlimit.h"
 | 
			
		||||
#include "hilbert_basis.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +46,8 @@ namespace karr {
 | 
			
		|||
 | 
			
		||||
    // treat src as a homogeneous matrix.
 | 
			
		||||
    void dualizeH(matrix& dst, matrix const& src) {
 | 
			
		||||
        hilbert_basis hb;
 | 
			
		||||
        reslimit rl;
 | 
			
		||||
        hilbert_basis hb(rl);
 | 
			
		||||
        for (unsigned i = 0; i < src.size(); ++i) {
 | 
			
		||||
            vector<rational> v(src.A[i]);
 | 
			
		||||
            v.push_back(src.b[i]);
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +75,8 @@ namespace karr {
 | 
			
		|||
 | 
			
		||||
    // treat src as an inhomegeneous matrix.
 | 
			
		||||
    void dualizeI(matrix& dst, matrix const& src) {
 | 
			
		||||
        hilbert_basis hb;
 | 
			
		||||
        reslimit rl;
 | 
			
		||||
        hilbert_basis hb(rl);
 | 
			
		||||
        for (unsigned i = 0; i < src.size(); ++i) {
 | 
			
		||||
            hb.add_eq(src.A[i], -src.b[i]);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ Notes:
 | 
			
		|||
#include"nlsat_evaluator.h"
 | 
			
		||||
#include"nlsat_solver.h"
 | 
			
		||||
#include"util.h"
 | 
			
		||||
#include"rlimit.h"
 | 
			
		||||
 | 
			
		||||
nlsat::interval_set_ref tst_interval(nlsat::interval_set_ref const & s1,
 | 
			
		||||
                                     nlsat::interval_set_ref const & s2,
 | 
			
		||||
| 
						 | 
				
			
			@ -57,8 +58,9 @@ nlsat::interval_set_ref tst_interval(nlsat::interval_set_ref const & s1,
 | 
			
		|||
 | 
			
		||||
static void tst3() {
 | 
			
		||||
    enable_trace("nlsat_interval");
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager         qm;
 | 
			
		||||
    anum_manager                am(qm);
 | 
			
		||||
    anum_manager                am(rl, qm);
 | 
			
		||||
    small_object_allocator      allocator;
 | 
			
		||||
    nlsat::interval_set_manager ism(am, allocator);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -241,8 +243,9 @@ static void check_subset_result(nlsat::interval_set_ref const & s1,
 | 
			
		|||
 | 
			
		||||
static void tst4() {
 | 
			
		||||
    enable_trace("nlsat_interval");
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager         qm;
 | 
			
		||||
    anum_manager                am(qm);
 | 
			
		||||
    anum_manager                am(rl, qm);
 | 
			
		||||
    small_object_allocator      allocator;
 | 
			
		||||
    nlsat::interval_set_manager ism(am, allocator);
 | 
			
		||||
    nlsat::interval_set_ref     s1(ism), s2(ism), r(ism);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,11 +22,13 @@ Notes:
 | 
			
		|||
#include"polynomial_var2value.h"
 | 
			
		||||
#include"polynomial_cache.h"
 | 
			
		||||
#include"linear_eq_solver.h"
 | 
			
		||||
#include"rlimit.h"
 | 
			
		||||
 | 
			
		||||
static void tst1() {
 | 
			
		||||
    std::cout << "\n----- Basic testing -------\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -56,6 +58,7 @@ static void tst1() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_pseudo_div(polynomial_ref const & A, polynomial_ref const & B, polynomial::var x) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::manager & m = A.m();
 | 
			
		||||
    std::cout << "---- Pseudo-division test ----\n";
 | 
			
		||||
    std::cout << "A: " << A << "\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -81,8 +84,9 @@ static void tst_pseudo_div(polynomial_ref const & A, polynomial_ref const & B, p
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst2() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -98,8 +102,9 @@ static void tst2() {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
static void tst3() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    x0 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -113,8 +118,9 @@ static void tst3() {
 | 
			
		|||
 | 
			
		||||
static void tst4() {
 | 
			
		||||
    std::cout << "---- Testing renaming/reordering ----\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -141,8 +147,9 @@ static void tst_quasi_resultant(polynomial_ref const & p, polynomial_ref const &
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst5() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -158,8 +165,9 @@ static void tst5() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst6() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -176,8 +184,9 @@ static void tst6() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst7() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -198,8 +207,9 @@ static void tst7() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst8() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -220,8 +230,9 @@ static void tst8() {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
static void tst9() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -261,8 +272,9 @@ static void tst9() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst10() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -300,8 +312,9 @@ static void tst10() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst11() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -342,8 +355,9 @@ static void tst_discriminant(polynomial_ref const & p, polynomial_ref const & ex
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_discriminant() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref a(m);
 | 
			
		||||
    polynomial_ref b(m);
 | 
			
		||||
    polynomial_ref c(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -460,8 +474,9 @@ static void tst_resultant(polynomial_ref const & p, polynomial_ref const & q, po
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_resultant() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref a(m);
 | 
			
		||||
    polynomial_ref b(m);
 | 
			
		||||
    polynomial_ref c(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -545,8 +560,9 @@ static void tst_resultant() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_compose() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    x0 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -560,8 +576,9 @@ static void tst_compose() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void tst_prem() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    polynomial_ref y(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -577,8 +594,9 @@ void tst_prem() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void tst_sqrt() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    polynomial_ref y(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -622,8 +640,9 @@ static void tst_gcd(polynomial_ref const & p, polynomial_ref const & q, polynomi
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_gcd() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -721,8 +740,9 @@ static void tst_psc_perf(polynomial_ref const & p, polynomial_ref const & q, pol
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
static void tst_psc() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -834,7 +854,7 @@ static void tst_vars(polynomial_ref const & p, unsigned sz, polynomial::var * xs
 | 
			
		|||
 | 
			
		||||
static void tst_vars() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -874,7 +894,7 @@ static void tst_sqf(polynomial_ref const & p, polynomial_ref const & expected) {
 | 
			
		|||
 | 
			
		||||
static void tst_sqf() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -919,7 +939,7 @@ static void tst_substitute(polynomial_ref const & p,
 | 
			
		|||
 | 
			
		||||
static void tst_substitute() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -960,7 +980,7 @@ static void tst_qsubstitute(polynomial_ref const & p,
 | 
			
		|||
 | 
			
		||||
static void tst_qsubstitute() {
 | 
			
		||||
    unsynch_mpq_manager qm;
 | 
			
		||||
    polynomial::manager m(qm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, qm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1013,7 +1033,7 @@ void tst_mfact(polynomial_ref const & p, unsigned num_distinct_factors) {
 | 
			
		|||
 | 
			
		||||
static void tst_mfact() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1175,7 +1195,7 @@ static void tst_mfact() {
 | 
			
		|||
 | 
			
		||||
static void tst_zp() {
 | 
			
		||||
    unsynch_mpz_manager    z;
 | 
			
		||||
    polynomial::manager    pm(z);
 | 
			
		||||
    reslimit rl; polynomial::manager    pm(rl, z);
 | 
			
		||||
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    polynomial_ref y(pm);
 | 
			
		||||
| 
						 | 
				
			
			@ -1233,7 +1253,7 @@ static void tst_translate(polynomial_ref const & p, polynomial::var x0, int v0,
 | 
			
		|||
 | 
			
		||||
static void tst_translate() {
 | 
			
		||||
    unsynch_mpq_manager qm;
 | 
			
		||||
    polynomial::manager m(qm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, qm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1264,7 +1284,7 @@ static void tst_translate() {
 | 
			
		|||
#if 0
 | 
			
		||||
static void tst_p25() {
 | 
			
		||||
    unsynch_mpq_manager qm;
 | 
			
		||||
    polynomial::manager m(qm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, qm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1288,10 +1308,11 @@ static void tst_p25() {
 | 
			
		|||
static void tst_mm() {
 | 
			
		||||
    unsynch_mpq_manager qm;
 | 
			
		||||
    // pm1 and pm2 share the same monomial manager
 | 
			
		||||
    polynomial::manager * pm1_ptr = alloc(polynomial::manager, qm);
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::manager * pm1_ptr = alloc(polynomial::manager, rl, qm);
 | 
			
		||||
    polynomial::manager & pm1 = *pm1_ptr;
 | 
			
		||||
    polynomial::manager pm2(qm, &pm1.mm());
 | 
			
		||||
    polynomial::manager pm3(qm); // pm3 has its own manager
 | 
			
		||||
    polynomial::manager pm2(rl, qm, &pm1.mm());
 | 
			
		||||
    polynomial::manager pm3(rl, qm); // pm3 has its own manager
 | 
			
		||||
    polynomial_ref p2(pm2);
 | 
			
		||||
    {
 | 
			
		||||
        polynomial_ref x0(pm1);
 | 
			
		||||
| 
						 | 
				
			
			@ -1336,7 +1357,7 @@ static void tst_eval(polynomial_ref const & p, polynomial::var x0, rational v0,
 | 
			
		|||
 | 
			
		||||
static void tst_eval() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1369,7 +1390,7 @@ static void tst_eval() {
 | 
			
		|||
 | 
			
		||||
static void tst_mk_unique() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1414,7 +1435,7 @@ static void tst_del_eh() {
 | 
			
		|||
    dummy_del_eh eh2;
 | 
			
		||||
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    x0 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -1444,7 +1465,7 @@ static void tst_del_eh() {
 | 
			
		|||
 | 
			
		||||
static void tst_const_coeff() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    x0 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -1490,7 +1511,7 @@ static void tst_const_coeff() {
 | 
			
		|||
static void tst_gcd2() {
 | 
			
		||||
    // enable_trace("mgcd");
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    polynomial_ref x1(m);
 | 
			
		||||
    polynomial_ref x2(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1582,7 +1603,7 @@ static void tst_gcd3() {
 | 
			
		|||
    enable_trace("polynomial_gcd_detail");
 | 
			
		||||
    enable_trace("mpzzp");
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    polynomial_ref p(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1607,7 +1628,7 @@ static void tst_gcd4() {
 | 
			
		|||
    enable_trace("mgcd");
 | 
			
		||||
    // enable_trace("CRA");
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    polynomial_ref p(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1631,7 +1652,7 @@ static void tst_gcd4() {
 | 
			
		|||
static void tst_newton_interpolation() {
 | 
			
		||||
    // enable_trace("newton");
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    polynomial_ref y(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -1654,7 +1675,7 @@ static void tst_newton_interpolation() {
 | 
			
		|||
 | 
			
		||||
static void tst_slow_mod_gcd() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m), x1(m), x2(m), x3(m), x4(m), x5(m);
 | 
			
		||||
    x0 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    x1 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -1735,7 +1756,7 @@ static void tst_lex(polynomial_ref const & p1, polynomial_ref const & p2, int le
 | 
			
		|||
 | 
			
		||||
static void tst_lex() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m), x1(m), x2(m), x3(m), x4(m), x5(m);
 | 
			
		||||
    x0 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    x1 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -1772,7 +1793,7 @@ static void tst_lex() {
 | 
			
		|||
 | 
			
		||||
static void tst_divides() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    x0 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    polynomial_ref q(m);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ Notes:
 | 
			
		|||
#include"upolynomial_factorization_int.h"
 | 
			
		||||
#include"timeit.h"
 | 
			
		||||
#include"polynomial.h"
 | 
			
		||||
 | 
			
		||||
#include"rlimit.h"
 | 
			
		||||
#if 0
 | 
			
		||||
#include"polynomial_factorization.h"
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +176,7 @@ int random_polynomial[20][2][11] = {
 | 
			
		|||
#if 0
 | 
			
		||||
static void tst_square_free_finite_1() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    // example from Knuth, p. 442
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
| 
						 | 
				
			
			@ -224,7 +224,7 @@ static void tst_square_free_finite_1() {
 | 
			
		|||
static void tst_factor_finite_1() {
 | 
			
		||||
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    // example from Knuth, p. 442
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
| 
						 | 
				
			
			@ -274,7 +274,7 @@ static void tst_factor_finite_1() {
 | 
			
		|||
static void tst_factor_finite_2() {
 | 
			
		||||
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    x = pm.mk_polynomial(pm.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -333,7 +333,7 @@ static void tst_factor_finite_2() {
 | 
			
		|||
static void tst_factor_finite_3() {
 | 
			
		||||
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    x = pm.mk_polynomial(pm.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -403,7 +403,7 @@ static void tst_factor_finite_3() {
 | 
			
		|||
 | 
			
		||||
static void tst_factor_enumeration() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    x = pm.mk_polynomial(pm.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -514,7 +514,7 @@ static void tst_factor_square_free_univariate_1(unsigned max_length) {
 | 
			
		|||
    nm.set(p, 5);
 | 
			
		||||
    nm.mod(test, p, test);
 | 
			
		||||
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    x = pm.mk_polynomial(pm.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -560,7 +560,7 @@ static void tst_factor_square_free_univariate_1(unsigned max_length) {
 | 
			
		|||
 | 
			
		||||
static void tst_factor_square_free_univariate_2() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    x = pm.mk_polynomial(pm.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -598,7 +598,7 @@ static void tst_factor_square_free_univariate_2() {
 | 
			
		|||
 | 
			
		||||
static void tst_factor_square_free_univariate_3() {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    x = pm.mk_polynomial(pm.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -622,7 +622,7 @@ static void tst_factor_square_free_univariate_3() {
 | 
			
		|||
 | 
			
		||||
void tst_factor_swinnerton_dyer_big(unsigned max) {
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    x = pm.mk_polynomial(pm.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			@ -669,7 +669,8 @@ void tst_factor_swinnerton_dyer_big(unsigned max) {
 | 
			
		|||
        {
 | 
			
		||||
            timeit timer(true, "factoring swinnerton-dyer");
 | 
			
		||||
 | 
			
		||||
            upolynomial::manager upm(nm);
 | 
			
		||||
            reslimit rl;
 | 
			
		||||
            upolynomial::manager upm(rl, nm);
 | 
			
		||||
            scoped_mpz_vector sd_u(nm);
 | 
			
		||||
            upm.to_numeral_vector(computation, sd_u);
 | 
			
		||||
            upolynomial::factors factors(upm);
 | 
			
		||||
| 
						 | 
				
			
			@ -689,7 +690,7 @@ static void tst_factor_square_free_multivariate_1(unsigned max_n) {
 | 
			
		|||
    nm.set(p, 5);
 | 
			
		||||
    nm.mod(test, p, test);
 | 
			
		||||
 | 
			
		||||
    polynomial::manager pm(nm);
 | 
			
		||||
    reslimit rl; polynomial::manager pm(rl, nm);
 | 
			
		||||
 | 
			
		||||
    polynomial_ref x(pm);
 | 
			
		||||
    x = pm.mk_polynomial(pm.mk_var());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,10 +18,12 @@ Notes:
 | 
			
		|||
--*/
 | 
			
		||||
#include"realclosure.h"
 | 
			
		||||
#include"mpz_matrix.h"
 | 
			
		||||
#include"rlimit.h"
 | 
			
		||||
 | 
			
		||||
static void tst1() {
 | 
			
		||||
    unsynch_mpq_manager qm;
 | 
			
		||||
    rcmanager m(qm);
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    rcmanager m(rl, qm);
 | 
			
		||||
    scoped_rcnumeral a(m);
 | 
			
		||||
#if 0
 | 
			
		||||
    a = 10;
 | 
			
		||||
| 
						 | 
				
			
			@ -143,8 +145,9 @@ static void tst_lin_indep(unsigned m, unsigned n, int _A[], unsigned ex_sz, unsi
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_denominators() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager qm;
 | 
			
		||||
    rcmanager m(qm);
 | 
			
		||||
    rcmanager m(rl, qm);
 | 
			
		||||
    scoped_rcnumeral a(m);
 | 
			
		||||
    scoped_rcnumeral t(m);
 | 
			
		||||
    scoped_rcnumeral eps(m);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ Copyright (c) 2015 Microsoft Corporation
 | 
			
		|||
#include "mpq_inf.h"
 | 
			
		||||
#include "vector.h"
 | 
			
		||||
#include "rational.h"
 | 
			
		||||
#include "rlimit.h"
 | 
			
		||||
 | 
			
		||||
#define R rational
 | 
			
		||||
typedef simplex::simplex<simplex::mpz_ext> Simplex;
 | 
			
		||||
| 
						 | 
				
			
			@ -99,7 +100,8 @@ static void feas(Simplex& S) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void test1() {
 | 
			
		||||
    Simplex S;
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    Simplex S(rl);
 | 
			
		||||
    add_row(S, vec(1,0), R(1));
 | 
			
		||||
    add_row(S, vec(0,1), R(1));
 | 
			
		||||
    add_row(S, vec(1,1), R(1));
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +109,7 @@ static void test1() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void test2() {
 | 
			
		||||
    Simplex S;
 | 
			
		||||
    reslimit rl; Simplex S(rl);
 | 
			
		||||
    add_row(S, vec(1, 0), R(1));
 | 
			
		||||
    add_row(S, vec(0, 1), R(1));
 | 
			
		||||
    add_row(S, vec(1, 1), R(1), true);
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +117,7 @@ static void test2() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void test3() {
 | 
			
		||||
    Simplex S;
 | 
			
		||||
    reslimit rl; Simplex S(rl);
 | 
			
		||||
    add_row(S, vec(-1, 0), R(-1));
 | 
			
		||||
    add_row(S, vec(0, -1), R(-1));
 | 
			
		||||
    add_row(S, vec(1, 1), R(1), true);
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +125,7 @@ static void test3() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void test4() {
 | 
			
		||||
    Simplex S;
 | 
			
		||||
    reslimit rl; Simplex S(rl);
 | 
			
		||||
    add_row(S, vec(1, 0), R(1));
 | 
			
		||||
    add_row(S, vec(0, -1), R(-1));
 | 
			
		||||
    add_row(S, vec(1, 1), R(1), true);
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +133,7 @@ static void test4() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void tst_simplex() {
 | 
			
		||||
    Simplex S;
 | 
			
		||||
    reslimit rl; Simplex S(rl);
 | 
			
		||||
 | 
			
		||||
    std::cout << "simplex\n";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ Revision History:
 | 
			
		|||
#include"ast.h"
 | 
			
		||||
#include"debug.h"
 | 
			
		||||
#include"im_float_config.h"
 | 
			
		||||
#include"rlimit.h"
 | 
			
		||||
 | 
			
		||||
#define PREC 100000
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +40,8 @@ static void tst_sine_core(std::ostream & out, unsynch_mpq_manager & nm, interval
 | 
			
		|||
static void tst_sine(std::ostream & out, unsigned N, unsigned k) {
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    scoped_mpq a(nm);
 | 
			
		||||
    nm.set(a, 0);
 | 
			
		||||
    tst_sine_core(out, nm, im, a, 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -63,9 +65,10 @@ static void tst_cosine_core(std::ostream & out, unsynch_mpq_manager & nm, interv
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_cosine(std::ostream & out, unsigned N, unsigned k) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    scoped_mpq a(nm);
 | 
			
		||||
    nm.set(a, 0);
 | 
			
		||||
    tst_cosine_core(out, nm, im, a, 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -95,9 +98,10 @@ const unsigned SBITS = 53;
 | 
			
		|||
 | 
			
		||||
template<typename fmanager>
 | 
			
		||||
static void tst_float_sine(std::ostream & out, unsigned N, unsigned k) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    fmanager                                     fm;
 | 
			
		||||
    im_float_config<fmanager>                    ifc(fm, EBITS, SBITS);
 | 
			
		||||
    interval_manager<im_float_config<fmanager> > im(ifc);
 | 
			
		||||
    interval_manager<im_float_config<fmanager> > im(rl, ifc);
 | 
			
		||||
    _scoped_numeral<fmanager> a(fm);
 | 
			
		||||
    fm.set(a, EBITS, SBITS, static_cast<int>(0));
 | 
			
		||||
    tst_float_sine_core(out, fm, im, a, 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -130,9 +134,10 @@ static void tst_mpf_bug() {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
static void tst_e(std::ostream & out) {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager                 nm;
 | 
			
		||||
    im_default_config                   imc(nm);
 | 
			
		||||
    interval_manager<im_default_config> im(imc);
 | 
			
		||||
    interval_manager<im_default_config> im(rl, imc);
 | 
			
		||||
    im_default_config::interval         r;
 | 
			
		||||
    for (unsigned i = 0; i < 64; i++) {
 | 
			
		||||
        im.e(i, r);
 | 
			
		||||
| 
						 | 
				
			
			@ -144,10 +149,11 @@ static void tst_e(std::ostream & out) {
 | 
			
		|||
 | 
			
		||||
static void tst_e_float(std::ostream & out) {
 | 
			
		||||
    std::cout << "e float...\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager   qm;
 | 
			
		||||
    mpf_manager           fm;
 | 
			
		||||
    im_float_config<mpf_manager>                    ifc(fm);
 | 
			
		||||
    interval_manager<im_float_config<mpf_manager> > im(ifc);
 | 
			
		||||
    interval_manager<im_float_config<mpf_manager> > im(rl, ifc);
 | 
			
		||||
    scoped_mpq q(qm);
 | 
			
		||||
    im_float_config<mpf_manager>::interval r;
 | 
			
		||||
    for (unsigned i = 0; i < 64; i++) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,11 +18,13 @@ Notes:
 | 
			
		|||
--*/
 | 
			
		||||
#include"upolynomial.h"
 | 
			
		||||
#include"timeit.h"
 | 
			
		||||
#include"rlimit.h"
 | 
			
		||||
 | 
			
		||||
static void tst1() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    upolynomial::manager um(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    upolynomial::manager um(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +66,8 @@ static void tst1() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_isolate_roots(polynomial_ref const & p, unsigned prec, mpbq_manager & bqm, mpbq_vector & roots, mpbq_vector & lowers, mpbq_vector & uppers) {
 | 
			
		||||
    upolynomial::manager um(p.m().m());
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    upolynomial::manager um(rl, p.m().m());
 | 
			
		||||
    upolynomial::scoped_numeral_vector q(um);
 | 
			
		||||
    um.to_numeral_vector(p, q);
 | 
			
		||||
    std::cout << "isolating roots of: "; um.display(std::cout, q); std::cout << "\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -189,8 +192,9 @@ static void tst_isolate_roots(polynomial_ref const & p, unsigned expected_sz, ra
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_isolate_roots() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -275,15 +279,16 @@ static void tst_isolate_roots() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_remove_one_half() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
    polynomial_ref p(m), r(m);
 | 
			
		||||
    p = 4*(x^3) - 12*(x^2) - x + 3;
 | 
			
		||||
    r = 16*(x^2) - 40*x - 24;
 | 
			
		||||
    upolynomial::manager um(nm);
 | 
			
		||||
    upolynomial::manager um(rl, nm);
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um), _q(um), _r(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
    um.to_numeral_vector(r, _r);
 | 
			
		||||
| 
						 | 
				
			
			@ -321,15 +326,16 @@ static void tst_gcd(polynomial_ref const & p, polynomial_ref const & q, pmanager
 | 
			
		|||
 | 
			
		||||
static void tst_gcd() {
 | 
			
		||||
    std::cout << "\n\nTesting GCD\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
    polynomial_ref p(m);
 | 
			
		||||
    polynomial_ref q(m);
 | 
			
		||||
 | 
			
		||||
    upolynomial::manager um(nm);
 | 
			
		||||
    upolynomial::manager um(rl, nm);
 | 
			
		||||
 | 
			
		||||
    p = 13*((x - 3)^6)*((x - 5)^5)*((x - 11)^7);
 | 
			
		||||
    q = derivative(p, 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -351,8 +357,9 @@ static void tst_gcd() {
 | 
			
		|||
 | 
			
		||||
static void tst_zp() {
 | 
			
		||||
    std::cout << "\n\nTesting Z_p\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -363,20 +370,21 @@ static void tst_zp() {
 | 
			
		|||
 | 
			
		||||
    // Computing GCD of p an q in Z[x]
 | 
			
		||||
    std::cout << "GCD in Z[x]\n";
 | 
			
		||||
    upolynomial::manager um(nm);
 | 
			
		||||
    upolynomial::manager um(rl, nm);
 | 
			
		||||
    tst_gcd(p, q, um);
 | 
			
		||||
 | 
			
		||||
    // Computing GCD of p an q in Z_3[x]
 | 
			
		||||
    std::cout << "GCD in Z_3[x]\n";
 | 
			
		||||
    upolynomial::zp_manager um3(nm);
 | 
			
		||||
    upolynomial::zp_manager um3(rl, nm);
 | 
			
		||||
    um3.set_zp(3);
 | 
			
		||||
    tst_gcd(p, q, um3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tst_zp2() {
 | 
			
		||||
    std::cout << "\n\nTesting Z_p\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -387,20 +395,21 @@ static void tst_zp2() {
 | 
			
		|||
 | 
			
		||||
    // Computing GCD of p an q in Z[x]
 | 
			
		||||
    std::cout << "GCD in Z[x]\n";
 | 
			
		||||
    upolynomial::manager um(nm);
 | 
			
		||||
    upolynomial::manager um(rl, nm);
 | 
			
		||||
    tst_gcd(u, v, um);
 | 
			
		||||
 | 
			
		||||
    // Computing GCD of p an q in Z_3[x]
 | 
			
		||||
    std::cout << "GCD in Z_13[x]\n";
 | 
			
		||||
    upolynomial::zp_manager um13(nm);
 | 
			
		||||
    upolynomial::zp_manager um13(rl, nm);
 | 
			
		||||
    um13.set_zp(13);
 | 
			
		||||
    tst_gcd(u, v, um13);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tst_ext_gcd() {
 | 
			
		||||
    std::cout << "\nExtended GCD\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -411,7 +420,7 @@ static void tst_ext_gcd() {
 | 
			
		|||
 | 
			
		||||
    // Computing GCD of p an q in Z_3[x]
 | 
			
		||||
    std::cout << "GCD in Z_13[x]\n";
 | 
			
		||||
    upolynomial::zp_manager um(nm);
 | 
			
		||||
    upolynomial::zp_manager um(rl, nm);
 | 
			
		||||
    um.set_zp(13);
 | 
			
		||||
    mpzzp_manager & z13 = um.m();
 | 
			
		||||
    upolynomial::zp_manager::scoped_numeral_vector A(z13), B(z13), U(z13), V(z13), D(z13);
 | 
			
		||||
| 
						 | 
				
			
			@ -427,8 +436,9 @@ static void tst_ext_gcd() {
 | 
			
		|||
 | 
			
		||||
static void tst_ext_gcd_z7() {
 | 
			
		||||
    std::cout << "\nExtended GCD in Z_7\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -441,7 +451,7 @@ static void tst_ext_gcd_z7() {
 | 
			
		|||
    // Computing GCD of a and b in Z_3[x]
 | 
			
		||||
    // expecting: D = 1, U = 3*x + 6, V = 3*x^2 + 6*x + 4
 | 
			
		||||
    std::cout << "GCD in Z_7[x]\n";
 | 
			
		||||
    upolynomial::zp_manager um(nm);
 | 
			
		||||
    upolynomial::zp_manager um(rl, nm);
 | 
			
		||||
    um.set_zp(7);
 | 
			
		||||
    mpzzp_manager & z7 = um.m();
 | 
			
		||||
    upolynomial::zp_manager::scoped_numeral_vector A(z7), B(z7), U(z7), V(z7), D(z7);
 | 
			
		||||
| 
						 | 
				
			
			@ -457,8 +467,9 @@ static void tst_ext_gcd_z7() {
 | 
			
		|||
 | 
			
		||||
static void tst_sturm() {
 | 
			
		||||
    std::cout << "\nSturm Seq\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -467,7 +478,7 @@ static void tst_sturm() {
 | 
			
		|||
    // p = ((x^17) + 5*(x^16) + 3*(x^15) + 10*(x^13) + 13*(x^10) + (x^9) + 8*(x^5) + 3*(x^2) + 7)*(((x^5) - x - 1)^2)*(((x^3) - 2)^2);
 | 
			
		||||
    // p = ((x^17) + 5*(x^16) + 3*(x^15) + 10*(x^13) + 13*(x^10) + (x^9) + 8*(x^5) + 3*(x^2) + 7)*(((x^5) - x - 1))*(((x^3) - 2));
 | 
			
		||||
 | 
			
		||||
    upolynomial::manager um(nm);
 | 
			
		||||
    upolynomial::manager um(rl, nm);
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um);
 | 
			
		||||
    upolynomial::scoped_upolynomial_sequence seq2(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
| 
						 | 
				
			
			@ -478,7 +489,8 @@ static void tst_sturm() {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
static void tst_refinable(polynomial_ref const & p, mpbq_manager & bqm, mpbq & a, mpbq & b) {
 | 
			
		||||
    upolynomial::manager um(p.m().m());
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    upolynomial::manager um(rl, p.m().m());
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
    std::cout << "before (" << bqm.to_string(a) << ", " << bqm.to_string(b) << ")\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -497,8 +509,9 @@ static void tst_refinable(polynomial_ref const & p, mpbq_manager & bqm, mpbq & a
 | 
			
		|||
 | 
			
		||||
static void tst_refinable() {
 | 
			
		||||
    std::cout << "\nRefinable intervals\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -544,7 +557,7 @@ static void tst_refinable() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_refine(polynomial_ref const & p, mpbq_manager & bqm, mpbq & a, mpbq & b, unsigned prec_k=100) {
 | 
			
		||||
    upolynomial::manager um(p.m().m());
 | 
			
		||||
    reslimit rl; upolynomial::manager um(rl, p.m().m());
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
    std::cout << "before (" << bqm.to_string(a) << ", " << bqm.to_string(b) << ")\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -561,8 +574,9 @@ static void tst_refine(polynomial_ref const & p, mpbq_manager & bqm, mpbq & a, m
 | 
			
		|||
 | 
			
		||||
static void tst_refine() {
 | 
			
		||||
    std::cout << "\nRefining intervals\n";
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -583,14 +597,15 @@ static void tst_refine() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_translate_q() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
    polynomial_ref p(m);
 | 
			
		||||
    p = (x-1)*(x-2)*(x-3)*(x-4);
 | 
			
		||||
    upolynomial::manager um(nm);
 | 
			
		||||
    upolynomial::manager um(rl, nm);
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um), _q(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
    SASSERT(um.eval_sign_at(_p.size(), _p.c_ptr(), mpq(1)) == 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -637,7 +652,8 @@ static void tst_translate_q() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_convert_q2bq(unsynch_mpq_manager & m, polynomial_ref const & p, mpq const & a, mpq const & b) {
 | 
			
		||||
    upolynomial::manager um(m);
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    upolynomial::manager um(rl, m);
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
    std::cout << "\np: ";
 | 
			
		||||
| 
						 | 
				
			
			@ -657,8 +673,9 @@ static void tst_convert_q2bq(unsynch_mpq_manager & m, polynomial_ref const & p,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_convert_q2bq() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    unsynch_mpq_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -704,8 +721,9 @@ static void tst_convert_q2bq() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_sturm2() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -715,7 +733,7 @@ static void tst_sturm2() {
 | 
			
		|||
    p = (x^16) - 136*(x^14) + 6476*(x^12) - 141912*(x^10) + 1513334*(x^8) - 7453176*(x^6) + 13950764*(x^4) - 5596840*(x^2) + 46225;
 | 
			
		||||
    q = ((x^8) - 40*(x^6) + 352*(x^4) - 960*(x^2) + 576)^2;
 | 
			
		||||
 | 
			
		||||
    upolynomial::manager um(nm);
 | 
			
		||||
    upolynomial::manager um(rl, nm);
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um), _q(um);
 | 
			
		||||
    upolynomial::scoped_upolynomial_sequence seq2(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
| 
						 | 
				
			
			@ -784,7 +802,7 @@ static void tst_gcd2() {
 | 
			
		|||
    polynomial_ref p(m);
 | 
			
		||||
    p = ((x^1000) - x + 1)^5;
 | 
			
		||||
 | 
			
		||||
    upolynomial::manager um(nm);
 | 
			
		||||
    reslimit rl; upolynomial::manager um(rl, nm);
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um);
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p_sqf(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
| 
						 | 
				
			
			@ -797,8 +815,9 @@ static void tst_gcd2() {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
static void tst_isolate_roots5() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -811,7 +830,8 @@ static void tst_isolate_roots5() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_exact_div(polynomial_ref const & p1, polynomial_ref const & p2, bool expected, polynomial_ref const & expected_q) {
 | 
			
		||||
    upolynomial::manager um(p1.m().m());
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    upolynomial::manager um(rl, p1.m().m());
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p1(um), _p2(um), _q(um), _r(um);
 | 
			
		||||
    um.to_numeral_vector(p1, _p1);
 | 
			
		||||
    um.to_numeral_vector(p2, _p2);
 | 
			
		||||
| 
						 | 
				
			
			@ -834,8 +854,9 @@ static void tst_exact_div(polynomial_ref const & p1, polynomial_ref const & p2,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_exact_div() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    // create univariate polynomial using multivariate polynomial package
 | 
			
		||||
| 
						 | 
				
			
			@ -860,7 +881,7 @@ static void tst_fact(polynomial_ref const & p, unsigned num_distinct_factors, up
 | 
			
		|||
    SASSERT(is_univariate(p));
 | 
			
		||||
    std::cout << "---------------\n";
 | 
			
		||||
    std::cout << "p: " << p << std::endl;
 | 
			
		||||
    upolynomial::manager um(p.m().m());
 | 
			
		||||
    reslimit rl; upolynomial::manager um(rl, p.m().m());
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um);
 | 
			
		||||
    upolynomial::factors fs(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
| 
						 | 
				
			
			@ -878,8 +899,9 @@ static void tst_fact(polynomial_ref const & p, unsigned num_distinct_factors, up
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_fact() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m);
 | 
			
		||||
    x0 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    tst_fact((x0^4) + (x0^2) - 20, 3);
 | 
			
		||||
| 
						 | 
				
			
			@ -975,7 +997,7 @@ static void tst_rem(polynomial_ref const & p, polynomial_ref const & q, polynomi
 | 
			
		|||
    std::cout << "---------------\n";
 | 
			
		||||
    std::cout << "p: " << p << std::endl;
 | 
			
		||||
    std::cout << "q: " << q << std::endl;
 | 
			
		||||
    upolynomial::manager um(p.m().m());
 | 
			
		||||
    reslimit rl; upolynomial::manager um(rl, p.m().m());
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um), _q(um), _r(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
    um.to_numeral_vector(q, _q);
 | 
			
		||||
| 
						 | 
				
			
			@ -987,8 +1009,9 @@ static void tst_rem(polynomial_ref const & p, polynomial_ref const & q, polynomi
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_rem() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x0(m), zero(m), one(m);
 | 
			
		||||
    x0 = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    zero = m.mk_zero();
 | 
			
		||||
| 
						 | 
				
			
			@ -1002,7 +1025,7 @@ static void tst_lower_bound(polynomial_ref const & p) {
 | 
			
		|||
    SASSERT(is_univariate(p));
 | 
			
		||||
    std::cout << "---------------\n";
 | 
			
		||||
    std::cout << "p: " << p << std::endl;
 | 
			
		||||
    upolynomial::manager um(p.m().m());
 | 
			
		||||
    reslimit rl; upolynomial::manager um(rl, p.m().m());
 | 
			
		||||
    upolynomial::scoped_numeral_vector _p(um);
 | 
			
		||||
    um.to_numeral_vector(p, _p);
 | 
			
		||||
    std::cout << "_p: "; um.display(std::cout, _p); std::cout << "\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -1012,8 +1035,9 @@ static void tst_lower_bound(polynomial_ref const & p) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void tst_lower_bound() {
 | 
			
		||||
    reslimit rl;
 | 
			
		||||
    polynomial::numeral_manager nm;
 | 
			
		||||
    polynomial::manager m(nm);
 | 
			
		||||
    polynomial::manager m(rl, nm);
 | 
			
		||||
    polynomial_ref x(m), zero(m), one(m);
 | 
			
		||||
    x = m.mk_polynomial(m.mk_var());
 | 
			
		||||
    zero = m.mk_zero();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,12 +44,16 @@ bool assertions_enabled();
 | 
			
		|||
#define DEBUG_CODE(CODE) ((void) 0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef NO_Z3_DEBUGGER
 | 
			
		||||
#define INVOKE_DEBUGGER() exit(ERR_INTERNAL_FATAL)
 | 
			
		||||
#else
 | 
			
		||||
#ifdef _WINDOWS
 | 
			
		||||
#define INVOKE_DEBUGGER() __debugbreak()
 | 
			
		||||
#else
 | 
			
		||||
void invoke_gdb();
 | 
			
		||||
#define INVOKE_DEBUGGER() invoke_gdb()
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void notify_assertion_violation(const char * file_name, int line, const char * condition);
 | 
			
		||||
void enable_debug(const char * tag);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,7 +192,7 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode
 | 
			
		|||
    TRACE("mpf_dbg", tout << "set: " << m_mpq_manager.to_string(value) << " [" << ebits << "/" << sbits << "]"<< std::endl;);
 | 
			
		||||
    scoped_mpz exp(m_mpz_manager);
 | 
			
		||||
    m_mpz_manager.set(exp, 0);
 | 
			
		||||
    set(o, ebits, sbits, rm, value, exp);
 | 
			
		||||
    set(o, ebits, sbits, rm, exp, value);
 | 
			
		||||
    TRACE("mpf_dbg", tout << "set: res = " << to_string(o) << std::endl;);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -221,12 +221,12 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode
 | 
			
		|||
    scoped_mpz ex(m_mpq_manager);
 | 
			
		||||
    m_mpz_manager.set(ex, e.c_str());
 | 
			
		||||
 | 
			
		||||
    set(o, ebits, sbits, rm, q, ex);    
 | 
			
		||||
    set(o, ebits, sbits, rm, ex, q);
 | 
			
		||||
 | 
			
		||||
    TRACE("mpf_dbg", tout << "set: res = " << to_string(o) << std::endl;);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & significand, mpz const & exponent) {
 | 
			
		||||
void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpz const & exponent, mpq const & significand) {
 | 
			
		||||
    // Assumption: this represents significand * 2^exponent.
 | 
			
		||||
    TRACE("mpf_dbg", tout << "set: sig = " << m_mpq_manager.to_string(significand) << " exp = " << m_mpz_manager.to_string(exponent) << std::endl;);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -289,7 +289,7 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode
 | 
			
		|||
    TRACE("mpf_dbg", tout << "set: res = " << to_string(o) << std::endl;);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, mpf_exp_t exponent) {
 | 
			
		||||
void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, bool sign, mpf_exp_t exponent, uint64 significand) {
 | 
			
		||||
    // Assumption: this represents (sign * -1) * (significand/2^sbits) * 2^exponent.
 | 
			
		||||
    o.ebits = ebits;
 | 
			
		||||
    o.sbits = sbits;
 | 
			
		||||
| 
						 | 
				
			
			@ -304,7 +304,7 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64
 | 
			
		|||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, bool sign, mpz const & significand, mpf_exp_t exponent) {
 | 
			
		||||
void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, bool sign, mpf_exp_t exponent, mpz const & significand) {
 | 
			
		||||
    // Assumption: this represents (sign * -1) * (significand/2^sbits) * 2^exponent.
 | 
			
		||||
    o.ebits = ebits;
 | 
			
		||||
    o.sbits = sbits;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,9 +74,9 @@ public:
 | 
			
		|||
    void set(mpf & o, unsigned ebits, unsigned sbits, double value);
 | 
			
		||||
    void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & value);
 | 
			
		||||
    void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, char const * value);
 | 
			
		||||
    void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & significand, mpz const & exponent);
 | 
			
		||||
    void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, mpf_exp_t exponent);
 | 
			
		||||
    void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, mpz const & significand, mpf_exp_t exponent);	
 | 
			
		||||
    void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpz const & exponent, mpq const & significand);
 | 
			
		||||
    void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, mpf_exp_t exponent, uint64 significand);
 | 
			
		||||
    void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, mpf_exp_t exponent, mpz const & significand);
 | 
			
		||||
    void set(mpf & o, mpf const & x);
 | 
			
		||||
    void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpf const & x);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,9 +89,10 @@ public:
 | 
			
		|||
        m_nodes.shrink(sz);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void push_back(T * n) {
 | 
			
		||||
    ref_vector_core& push_back(T * n) {
 | 
			
		||||
        inc_ref(n);
 | 
			
		||||
        m_nodes.push_back(n);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void pop_back() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ public:
 | 
			
		|||
    ~scoped_ptr_vector() { reset(); }
 | 
			
		||||
    void reset() { std::for_each(m_vector.begin(), m_vector.end(), delete_proc<T>()); m_vector.reset(); }
 | 
			
		||||
    void push_back(T * ptr) { m_vector.push_back(ptr); }
 | 
			
		||||
    void pop_back() { SASSERT(!empty()); set(size()-1, 0); m_vector.pop_back(); }
 | 
			
		||||
    T * operator[](unsigned idx) const { return m_vector[idx]; }
 | 
			
		||||
    void set(unsigned idx, T * ptr) { 
 | 
			
		||||
        if (m_vector[idx] == ptr) 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ public:
 | 
			
		|||
        m_elems_lim.push_back(m_elems_start);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void pop_scopes(unsigned num_scopes) {
 | 
			
		||||
    void pop_scope(unsigned num_scopes) {
 | 
			
		||||
        if (num_scopes == 0) return;
 | 
			
		||||
        unsigned new_size = m_sizes.size() - num_scopes;
 | 
			
		||||
        unsigned src_lim = m_src_lim[new_size];
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +72,12 @@ public:
 | 
			
		|||
        return m_elems[m_index[idx]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // breaks abstraction, caller must ensure backtracking.
 | 
			
		||||
    T& ref(unsigned idx) {
 | 
			
		||||
        SASSERT(idx < m_size);
 | 
			
		||||
        return m_elems[m_index[idx]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set(unsigned idx, T const& t) {
 | 
			
		||||
        SASSERT(idx < m_size);
 | 
			
		||||
        unsigned n = m_index[idx];
 | 
			
		||||
| 
						 | 
				
			
			@ -102,6 +108,13 @@ public:
 | 
			
		|||
        SASSERT(invariant());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void erase_and_swap(unsigned i) {
 | 
			
		||||
        if (i + 1 < size()) {
 | 
			
		||||
            set(i, m_elems[m_index[size()-1]]);
 | 
			
		||||
        }
 | 
			
		||||
        pop_back();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned size() const { return m_size; }
 | 
			
		||||
    
 | 
			
		||||
    bool empty() const { return m_size == 0; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue