├── .clang-format ├── .gitignore ├── .travis.yml ├── CHANGES.md ├── CITATION.md ├── CMakeLists.txt ├── LICENSE ├── NOTICE ├── README.md ├── appveyor.yml ├── bdist_wheel ├── setup.cfg └── setup.py ├── cmake └── appveyor.cmake ├── doc └── symdiff.pdf ├── examples ├── arrhenius.py ├── deftest.py ├── modellist1.py ├── models1.py ├── ordered.py ├── parsetest.py ├── remove1.py ├── subexpression1.py ├── table.py ├── undefined1.py └── utf8.py ├── goldenresults └── unix │ ├── arrhenius_py2.out │ ├── arrhenius_py3.out │ ├── arrhenius_tcl.out │ ├── deftest_py2.out │ ├── deftest_py3.out │ ├── maple.cc │ ├── maple.out │ ├── modellist1_py2.out │ ├── modellist1_py3.out │ ├── models1_py2.out │ ├── models1_py3.out │ ├── ns_3d.out │ ├── ordered_py2.out │ ├── ordered_py3.out │ ├── parsetest_py2.out │ ├── parsetest_py3.out │ ├── parsetest_tcl.out │ ├── remove1_py2.out │ ├── remove1_py3.out │ ├── subexpression1_py2.out │ ├── subexpression1_py3.out │ ├── symdiff1.out │ ├── symdiff2.out │ ├── symdiff3.out │ ├── symdiff4.out │ ├── table.out │ ├── table_py2.out │ ├── table_py3.out │ ├── undefined1_py2.out │ ├── undefined1_py3.out │ ├── units.out │ ├── utf8_py2.out │ └── utf8_py3.out ├── lib └── symdiff │ └── __init__.py ├── scripts ├── build_appveyor.bat ├── build_docker_manylinux2014.sh ├── build_docker_manylinux_2_28.sh ├── build_macos.sh ├── build_manylinux2014.sh ├── build_manylinux_2_28.sh ├── mkindex.tcl ├── setup_appveyor.sh ├── setup_osx_anaconda.sh ├── setup_ubuntu_18.sh ├── symdiff_centos.sh └── symdiff_macos.sh ├── sphinx ├── Makefile ├── NOTICE ├── make.bat └── source │ ├── additional.rst │ ├── advanced.rst │ ├── conf.py │ ├── devsim.bib │ ├── frontmatter.rst │ ├── index.rst │ ├── installation.rst │ ├── introduction.rst │ ├── macros.txt │ ├── references.rst │ ├── releasenotes.rst │ └── syntax.rst ├── src ├── CMakeLists.txt ├── engine │ ├── Add.cc │ ├── Add.hh │ ├── CMakeLists.txt │ ├── Constant.cc │ ├── Constant.hh │ ├── Context.cc │ ├── Context.hh │ ├── EngineAPI.cc │ ├── EngineAPI.hh │ ├── EquationFunc.cc │ ├── EquationFunc.hh │ ├── EquationObject.cc │ ├── EquationObject.hh │ ├── Exponent.cc │ ├── Exponent.hh │ ├── Functions.cc │ ├── Functions.hh │ ├── IfElse.cc │ ├── IfElse.hh │ ├── Log.cc │ ├── Log.hh │ ├── LogicalFunc.cc │ ├── LogicalFunc.hh │ ├── Pow.cc │ ├── Pow.hh │ ├── ProcessModelOrder.cc │ ├── ProcessModelOrder.hh │ ├── ProcessOrderedTable.cc │ ├── ProcessOrderedTable.hh │ ├── Product.cc │ ├── Product.hh │ ├── SubExpr.cc │ ├── SubExpr.hh │ ├── SymdiffImport.hh │ ├── UserFunc.cc │ ├── UserFunc.hh │ ├── Utility.cc │ ├── Utility.hh │ ├── Variable.cc │ ├── Variable.hh │ ├── gcd.cc │ ├── mcModel.cc │ ├── mcModel.hh │ ├── mcModelCompiler.cc │ ├── mcModelCompiler.hh │ ├── mcParser.y │ ├── mcScanner.l │ ├── mcTest.cc │ ├── mcTest.hh │ ├── parseexpr.cc │ └── parseexpr.hh ├── pycomp │ ├── CMakeLists.txt │ └── PythonSymdiffCommands.cc └── tclcomp │ ├── CMakeLists.txt │ ├── TclCommands.cc │ ├── TclCommands.hh │ ├── TclSymdiffCommands.cc │ ├── TclSymdiffCommands.hh │ └── tclcomp.cc └── testing ├── CMakeLists.txt ├── arrhenius_tcl.tcl ├── parsetest_tcl.tcl ├── rundifftest.py ├── symdiff1.tcl ├── symdiff2.tcl ├── symdiff3.tcl ├── symdiff4.tcl ├── table.tcl └── units.tcl /.gitignore: -------------------------------------------------------------------------------- 1 | manual/*.aux 2 | manual/*.dvi 3 | manual/*.log 4 | manual/*.out 5 | manual/*.ps 6 | manual/*.lot 7 | manual/*.toc 8 | osx_debug 9 | osx_release 10 | include 11 | bin 12 | lib 13 | 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: cpp 3 | 4 | matrix: 5 | include: 6 | - os: osx 7 | osx_image: xcode14.2 8 | - os: linux 9 | dist: focal 10 | services: docker 11 | arch: amd64 12 | - os: linux 13 | dist: focal 14 | services: docker 15 | arch: arm64 16 | 17 | addons: 18 | homebrew: 19 | update: false 20 | 21 | #https://github.com/travis-ci/travis-ci/issues/6893 22 | if: tag IS present 23 | 24 | # prevent duplicate builds on tagged versions on master 25 | # development to be done on other branches 26 | branches: 27 | except: 28 | - main 29 | 30 | # please see this if you have issues in docker with utf8_py3.out 31 | #https://stackoverflow.com/questions/29740662/python3-utf8-codecs-not-decoding-as-expected-in-docker-ubuntutrusty 32 | 33 | #before_install: 34 | # - if [ "$TRAVIS_OS_NAME" == "linux" ]; then 35 | # sudo apt-get install tcl8.5 tcl8.5-dev tcl-dev python3 python3-dev cmake flex bison; 36 | # fi 37 | # - if [ "$TRAVIS_OS_NAME" == "osx" ]; then 38 | # (curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh && 39 | # bash Miniconda3-latest-MacOSX-x86_64.sh -b -p $HOME/anaconda && 40 | # ${HOME}/anaconda/bin/conda create -y --name python37 python=3.7 41 | # ); 42 | # fi 43 | 44 | #script: 45 | # - if [ "$TRAVIS_OS_NAME" == "linux" ]; then 46 | # (bash scripts/setup_ubuntu_18.sh && cd linux_x86_64_release && make -j2 && ctest --verbose); 47 | # fi 48 | # - if [ "$TRAVIS_OS_NAME" == "osx" ]; then 49 | # (bash scripts/setup_osx_anaconda.sh && cd osx_release && make -j2 && ctest --verbose); 50 | # fi 51 | 52 | before_script: 53 | - export HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 54 | - if [ "$TRAVIS_OS_NAME" == "osx" ]; then 55 | brew install cmake; 56 | /usr/local/bin/pip3 install --upgrade pip; 57 | fi 58 | # specifically for pypi deployment 59 | - export README_BASE_URL="https://github.com/devsim/symdiff/blob/${TRAVIS_TAG}" 60 | 61 | script: 62 | - if [ "$TRAVIS_OS_NAME" == "linux" ]; then 63 | ./scripts/build_docker_manylinux_2_28.sh ${TRAVIS_TAG}; 64 | fi 65 | - if [ "$TRAVIS_OS_NAME" == "osx" ]; then 66 | ./scripts/build_macos.sh "${TRAVIS_TAG}"; 67 | fi 68 | 69 | deploy: 70 | provider: releases 71 | api_key: 72 | secure: "UrKCvZVvVCY51kbF31AKQiS2LSPNCkTeFGUTuP5XIvwWuupJockT/FVJXxdlBPjc1ALQr1or2ObPvOdp3XBbcoEWRCG9pFhQOuAh3HKntC1sxitudY3Djvn9g4iwlzBVzyzJoRo9Tra2zybjcwN8Q3HdXFeHzP3A1L3uatViTiE=" 73 | 74 | file_glob: true 75 | file: 76 | - "symdiff*.whl" 77 | skip_cleanup: true 78 | prerelease: false 79 | draft: true 80 | # fix issue with multiple deployments https://github.com/travis-ci/travis-ci/issues/6132 81 | tag_name: $TRAVIS_TAG 82 | on: 83 | repo: devsim/symdiff 84 | tags: true 85 | 86 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | # 1.2.11 2 | 3 | Drop support for `x86_64` on `macOS`. 4 | 5 | # 1.2.10 6 | 7 | Use the clang compiler on the windows platform. 8 | 9 | # 1.2.9 10 | 11 | Move to RHEL 8 compatible `manylinux_2_28`. 12 | 13 | Add `.clang-format` file to provide assist automatic formatting for new source code. 14 | 15 | # 1.2.8 16 | 17 | macOS is now a `universal` build for both `arm64` and `x86_64`. Minimum deployment version is now 12.0. 18 | 19 | # 1.2.7 20 | 21 | Update copyright. Build for aarch64 linux. 22 | -------------------------------------------------------------------------------- /CITATION.md: -------------------------------------------------------------------------------- 1 | 2 | # CITATION 3 | 4 | The package has been issued a DOI which is citable in publications. Please see the instructions at [Zenodo](https://doi.org/10.5281/zenodo.7237275) for citing this version, or all versions. 5 | 6 | 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT (SYMDIFF CXX) 2 | cmake_minimum_required(VERSION 3.9) 3 | 4 | OPTION(TCLMAIN "Build with TCL Interpreter" ON) 5 | OPTION(PYTHON3 "Build Python 3 Interpreter" ON) 6 | OPTION(STATICONLY "Build static only" OFF) 7 | 8 | IF (STATICONLY AND (TCLMAIN OR PYTHON3)) 9 | MESSAGE(FATAL_ERROR "STATICONLY not implemented for TCLMAIN and PYTHON3") 10 | ENDIF() 11 | 12 | set (CMAKE_CXX_STANDARD 17) 13 | 14 | SET (SUBDIRS 15 | src 16 | testing 17 | ) 18 | 19 | # superlu stuff 20 | SITE_NAME(HOSTNAME) 21 | MESSAGE("Hostname: ${HOSTNAME}") 22 | ADD_DEFINITIONS(-DSYMDIFF_VERSION_STRING=\"1.2.10\") 23 | ADD_DEFINITIONS(-DSYMDIFF_COPYRIGHT_YEAR=\"2010-2024\") 24 | 25 | IF (COPY_PROJECT_DIR) 26 | set(PROJECT_BIN_DIR ${COPY_PROJECT_DIR}/bin) 27 | set(PROJECT_SCRIPTS_DIR ${COPY_PROJECT_DIR}/scripts) 28 | set(PROJECT_LIBRARY_DIR ${COPY_PROJECT_DIR}/lib) 29 | set(PROJECT_INCLUDE_DIR ${COPY_PROJECT_DIR}/include) 30 | ELSE () 31 | set(PROJECT_BIN_DIR ${PROJECT_SOURCE_DIR}/bin) 32 | set(PROJECT_SCRIPTS_DIR ${PROJECT_SOURCE_DIR}/scripts) 33 | set(PROJECT_LIBRARY_DIR ${PROJECT_SOURCE_DIR}/lib) 34 | set(PROJECT_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) 35 | ENDIF () 36 | 37 | #TODO: put these in the individual setup scripts 38 | IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") 39 | ADD_DEFINITIONS(-Wall -DTCL_THREADS -DUSE_TCL_STUBS -fvisibility=hidden) 40 | #SET(CMAKE_SKIP_BUILD_RPATH TRUE) 41 | SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) 42 | ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") 43 | IF (APPLE) 44 | ADD_DEFINITIONS(-Wall -DTCL_THREADS -DUSE_TCL_STUBS -fvisibility=hidden) 45 | #SET (CMAKE_INSTALL_NAME_DIR "@rpath") 46 | SET(CMAKE_SKIP_BUILD_RPATH TRUE) 47 | ENDIF(APPLE) 48 | 49 | SET (FLEX flex) 50 | SET (DIFF diff) 51 | SET (BISON bison) 52 | 53 | INCLUDE(${PROJECT_SOURCE_DIR}/cmake/${SYMDIFF_CONFIG}.cmake OPTIONAL) 54 | 55 | ENABLE_TESTING() 56 | FOREACH (SUB ${SUBDIRS}) 57 | ADD_SUBDIRECTORY(${SUB}) 58 | ENDFOREACH (SUB ${SUBDIRS}) 59 | 60 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | SYMDIFF 2 | 3 | Copyright 2012--2024 DEVSIM LLC 4 | 5 | DEVSIM is a registered trademark of DEVSIM LLC. 6 | 7 | This product includes software developed at DEVSIM LLC (https://devsim.com). 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Build Status](https://app.travis-ci.com/devsim/symdiff.svg?branch=main)](https://app.travis-ci.com/devsim/symdiff) 3 | [![Build status](https://ci.appveyor.com/api/projects/status/github/devsim/symdiff?branch=main&svg=true)](https://ci.appveyor.com/project/devsim/symdiff) 4 | 5 | # SYMDIFF 6 | 7 | **SYMDIFF** is a tool for symbolic differentiation. The source code is provided by Devsim LLC ([http://www.devsim.com](http://www.devsim.com)). 8 | It is licensed under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html), meaning it is available for use in your own software. 9 | 10 | ## Software Features: 11 | * [Documentation](https://github.com/devsim/symdiff/blob/main/doc/symdiff.pdf?raw=true) 12 | * Expression parser 13 | * Symbolic differentiation of expressions with respect to arbitrary number of variables. 14 | * User defined differentiation rules for arbitrary functions 15 | * Common subexpression elimination for group of expressions 16 | * Expression ordering to facilitate source code generation. 17 | * **C++** library 18 | * **Python** scripting interface 19 | * **Tcl** scripting interface 20 | 21 | Recent changes are available in [CHANGES.md](CHANGES.md). 22 | 23 | Please see NOTICE and LICENSE files for copyright and license information. 24 | 25 | Documentation available in doc/symdiff.pdf. 26 | 27 | ## Install 28 | 29 | This software is available via ``pip`` from [https://pypi.org/project/symdiff/](https://pypi.org/project/symdiff/). 30 | 31 | ``` 32 | pip install symdiff 33 | ``` 34 | 35 | ## Citing This Work: 36 | 37 | Please see [CITATION.md](CITATION.md). *Please do not cite this Github Repository as it will be moving in the future.* 38 | 39 | -------------------------------------------------------------------------------- /bdist_wheel/setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | py-limited-api = cp37 3 | #plat-name= 4 | [metadata] 5 | version = 1.2.10 6 | classifiers = 7 | Development Status :: 5 - Production/Stable 8 | Intended Audience :: Science/Research 9 | License :: OSI Approved :: Apache Software License 10 | Programming Language :: Python :: 3 11 | Topic :: Scientific/Engineering :: Electronic Design Automation (EDA) 12 | name = symdiff 13 | url = https://symdiff.org 14 | author = Juan Sanchez 15 | author_email = info@devsim.com 16 | description = SYMDIFF: Symbolic differentation of algebraic expressions 17 | license = Apache License, Version 2.0 18 | project_urls = 19 | Bug Tracker = https://github.com/devsim/symdiff/issues 20 | Source Code = https://github.com/devsim/symdiff 21 | Online Forum = https://forum.devsim.org 22 | -------------------------------------------------------------------------------- /bdist_wheel/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, Distribution 2 | from glob import glob 3 | import os 4 | import re 5 | 6 | #https://stackoverflow.com/questions/35112511/pip-setup-py-bdist-wheel-no-longer-builds-forced-non-pure-wheels/36886459#36886459 7 | #https://stackoverflow.com/questions/24071491/how-can-i-make-a-python-wheel-from-an-existing-native-library/24793171#24793171 8 | class BinaryDistribution(Distribution): 9 | """Distribution which always forces a binary package with platform name""" 10 | def has_ext_modules(foo): 11 | return True 12 | 13 | def fix_readme(text): 14 | regex = re.compile('\[([^]]+)\]+\((?!http[s]:\/\/)([^)]+)\)') 15 | base_url = os.environ.get('README_BASE_URL') 16 | if base_url: 17 | if base_url[-1] != '/': 18 | base_url += '/' 19 | print("Fixing up base url for long description {0}".format(base_url)) 20 | text = regex.sub(lambda m, urlbase=base_url : r'[{0}]({1})'.format(m.group(1), urlbase + m.group(2)), text) 21 | return text 22 | 23 | with open('README.md', 'r') as ifile: 24 | text = ifile.read() 25 | text = fix_readme(text) 26 | 27 | setup( 28 | packages=['symdiff',], 29 | package_data={ 30 | 'symdiff' : ['./*.so', './*.dll', './*.dylib', './*.pyd',], 31 | }, 32 | distclass=BinaryDistribution, 33 | data_files = [ 34 | ('symdiff_data', ['LICENSE', 'NOTICE', 'README.md',]), 35 | ('symdiff_data/doc', glob('doc/*.pdf')), 36 | ('symdiff_data/examples', glob('examples/*.*')), 37 | ], 38 | long_description = text, 39 | long_description_content_type="text/markdown", 40 | ) 41 | -------------------------------------------------------------------------------- /cmake/appveyor.cmake: -------------------------------------------------------------------------------- 1 | # Any copyright is dedicated to the Public Domain. 2 | # http://creativecommons.org/publicdomain/zero/1.0/ 3 | #SET(PYTHON_BIN="/usr/bin/python") 4 | 5 | ADD_DEFINITIONS(-DTCL_THREADS -DUSE_TCL_STUBS) 6 | ADD_DEFINITIONS(-DSTATIC_BUILD -D_USE_MATH_DEFINES) 7 | SET (CMAKE_CXX_WARNING_LEVEL 4) 8 | 9 | 10 | # warning C4251 for dll exports 11 | # warning C4005 concerning macro redefines in stdint.h 12 | # warning C4996: 'isatty': The POSIX name for this item is deprecated 13 | SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:strict /wd4251 /wd4005 /wd4996") 14 | SET (CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} /fp:strict /wd4251 /wd4005 /wd4996") 15 | #64 bit build 16 | #SET(TCL_INCLUDE "c:/Tcl/include") 17 | #SET(TCL_ARCHIVE "c:/Tcl/lib/tclstub85.lib") 18 | 19 | SET(TCL_INCLUDE "${ANACONDA_PATH}/Library/include") 20 | SET(TCL_ARCHIVE "${ANACONDA_PATH}/Library/lib/tclstub86.lib") 21 | SET(TCL_BIN "${ANACONDA_PATH}/Library/bin/tclsh.exe") 22 | SET (PYTHON3_ARCHIVE ${ANACONDA_PATH}/libs/python3.lib) 23 | SET (PYTHON3_INCLUDE ${ANACONDA_PATH}/include) 24 | 25 | SET (FLEX "C:/msys64/usr/bin/flex.exe") 26 | SET (BISON "C:/msys64/usr/bin/bison.exe") 27 | 28 | SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:strict /EHsc") 29 | SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") 30 | SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB:python3") 31 | SET (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") 32 | 33 | -------------------------------------------------------------------------------- /doc/symdiff.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsim/symdiff/cf3472702f84d20d7d5e12f35ea50bd2e6a90a32/doc/symdiff.pdf -------------------------------------------------------------------------------- /examples/arrhenius.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff('define_model(arrhenius, simplify(Cf * pow(T, Etar) * exp(-Ea/T)))') 6 | symdiff('define_model(KC1 , simplify(A3 * R * T * exp((A1 * (-pow(T,(-1)) + pow(A2,(-1))) * pow(R,(-1))))))') 7 | symdiff('define_model(kb_model , simplify(arrhenius / KC1))') 8 | symdiff('declare_model(fprod)') 9 | 10 | symdiff('define_model(rprod , simplify(H * CN * AR))') 11 | symdiff('define_model(omega_dot_H , simplify((vr_H - vf_H) * (arrhenius * fprod - kb_model * rprod)))') 12 | symdiff('diff(omega_dot_H, T)') 13 | symdiff('diff(omega_dot_H, H)') 14 | symdiff('diff(omega_dot_H, HCN)') 15 | symdiff('diff(omega_dot_H, AR)') 16 | symdiff('diff(omega_dot_H, CN)') 17 | 18 | subexpression() 19 | remove_zeros() 20 | mylist = ordered_list('omega_dot_H', 'omega_dot_H__T', 'omega_dot_H__H', 'omega_dot_H__HCN', 'omega_dot_H__AR', 'omega_dot_H__CN') 21 | for i in mylist: 22 | mv = symdiff("model_value(%s);" % i) 23 | print("%s, %s" % (i, mv)) 24 | 25 | -------------------------------------------------------------------------------- /examples/deftest.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | commands = [ 6 | "define(f(x,y),y^2, 2*y*x+3*y^2)", 7 | "simplify(diff(f(x,y),x))", 8 | "simplify(diff(f(x,y),y))", 9 | "simplify(diff(f(y,x),y))", 10 | "simplify(diff(f(y,x),x))", 11 | 12 | "declare(cos(x))", 13 | "define(sin(x),cos(x))", 14 | "define(cos(x),-sin(x))", 15 | "simplify(diff(sin(x),x))", 16 | "simplify(diff(sin(y),x))", 17 | "simplify(diff(sin(x^2),x))", 18 | "simplify(diff(sin(y^2),y))", 19 | 20 | "clear", 21 | "define(f(x,y),diff(x*y^2+y^3,x),diff(x*y^2+y^3,y))", 22 | "simplify(diff(f(x,y),x))", 23 | "simplify(diff(f(x,y),y))", 24 | "simplify(diff(f(y,x),y))", 25 | "simplify(diff(f(y,x),x))", 26 | 27 | "clear", 28 | "declare(g(x,y,z))", 29 | "define(f(x,y,z),g(y,z,x),1,0)", 30 | "diff(f(x,y,z),x)", 31 | "diff(f(a,b,c),x)", 32 | "diff(f(a,b,c),a)", 33 | "diff(f(a,b,c),b)", 34 | "diff(f(a,b,c),c)", 35 | 36 | "clear", 37 | "a+b", 38 | "$_*$_", 39 | "expand($_)", 40 | "simplify($_)", 41 | "$a = $_ +1", 42 | "$b = $_ - $a", 43 | "$c = simplify($_)", 44 | "$c = simplify(expand($_))", 45 | ] 46 | 47 | for i in commands: 48 | print(symdiff(i)) 49 | -------------------------------------------------------------------------------- /examples/modellist1.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff('declare_model(x)') 6 | symdiff('declare_model(y)') 7 | l = model_list(); 8 | for i in l: 9 | print(('%s' % i)) 10 | -------------------------------------------------------------------------------- /examples/models1.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | print(symdiff('declare_model(x)')) 6 | print(symdiff('define_model(y, a*x)')) 7 | print(symdiff('diff(y, x)')) 8 | print(symdiff('clear_model(x)')) 9 | print(ordered_list('y')) 10 | print(symdiff('declare_model(x)')) 11 | print(ordered_list('y')) 12 | print(symdiff('define_model(x,y)')) 13 | # catch cycles 14 | try: 15 | print(ordered_list('y')) 16 | except SymdiffError as x: 17 | print(x) 18 | 19 | for i in model_list(): 20 | print(i + ' ' + symdiff('model_value(%s)' % i)) 21 | symdiff('clear_model(%s)' % i) 22 | 23 | print("") 24 | print(symdiff('declare_model(x)')) 25 | print(symdiff('define_model(y,x^2)')) 26 | print(symdiff('diff(y,x)')) 27 | print(symdiff('clear_model(y)')) 28 | print(symdiff('model_value(y__x)')) 29 | print(symdiff('diff(model_value(y__x),z)')) 30 | 31 | for i in model_list(): 32 | print(i + ' ' + symdiff('model_value(%s)' % i)) 33 | 34 | print("") 35 | symdiff('clear_model(x)') 36 | symdiff('clear_model(x__z)') 37 | 38 | for i in model_list(): 39 | print(i + ' ' + symdiff('model_value(%s)' % i)) 40 | symdiff('clear_model(%s)' % i) 41 | 42 | -------------------------------------------------------------------------------- /examples/ordered.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff('define_model(b, a)') 6 | symdiff('define_model(d, b * c)') 7 | mylist = ordered_list('d'); 8 | for i in mylist: 9 | print(('%s' % i)) 10 | -------------------------------------------------------------------------------- /examples/parsetest.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | def maptest(arg): 6 | print("") 7 | print(arg); 8 | try: 9 | out = symdiff(arg) 10 | except SymdiffError as x: 11 | out = x 12 | print(out) 13 | 14 | maptest("a*x") 15 | maptest("simplify(a*a)") 16 | maptest("simplify(pow(x, 0.0))") 17 | maptest("simplify(pow(x, 1.0))") 18 | maptest("simplify(pow(1.0, x))") 19 | maptest("simplify(exp(1.0))") 20 | maptest("simplify(exp(0.0))") 21 | maptest("simplify(exp(log(x)))") 22 | maptest("simplify(log(exp(x)))") 23 | maptest("simplify(log(1.0))") 24 | 25 | maptest("(exp(pow(c,pow(x,pow(c,x)))))") 26 | maptest("diff((exp(pow(c,pow(x,pow(c,x))))),x)") 27 | maptest("simplify(diff((exp(pow(c,pow(x,pow(c,x))))),x))") 28 | maptest("simplify((((((((1 * pow(x,(-1))) * pow(c,x)) + ((log(c) * pow(c,x)) * log(x))) * pow(x,pow(c,x))) * log(c)) * pow(c,pow(x,pow(c,x)))) * exp(pow(c,pow(x,pow(c,x))))))") 29 | 30 | maptest("simplify(a*5*pow(a,-1))") 31 | 32 | maptest("c*c*c*c") 33 | maptest("simplify(c*c*c*c)") 34 | maptest("diff(c*c*x*x,x)") 35 | 36 | maptest("simplify(log(pow(x,y)))") 37 | 38 | maptest("simplify(a*a+a*a*a)") 39 | maptest("simplify(a*a+a*a)") 40 | maptest("simplify(a+a+a*a)") 41 | maptest("simplify(a+a+a+a*a)") 42 | 43 | maptest("simplify(y*pow(x,(-1)) * pow(x,y))"); 44 | maptest("simplify(pow(x,(-1)) * pow(x,y)*y)"); 45 | maptest("simplify(pow(x,(-1)) * pow(x,y)*x)"); 46 | 47 | maptest("unscaledval(2*x)") 48 | maptest("scale(2*x)") 49 | 50 | maptest("a - a") 51 | maptest("a + -a") 52 | maptest("a - b") 53 | 54 | maptest("simplify(a - a)") 55 | maptest("simplify(a + -a)") 56 | maptest("simplify(a - b)") 57 | 58 | maptest("-simplify(a - b)") 59 | maptest("simplify(-simplify(a - b))") 60 | 61 | maptest("(-1*3*4*-3*x)"); 62 | maptest("simplify(-1*3*4*-3*x)"); 63 | 64 | maptest("-a"); 65 | maptest("a++-+a") 66 | maptest("a+*+a"); 67 | maptest("diff(-1*3*4*(-3)*x,x)"); 68 | maptest("diff(simplify(-1*3*4*(-3)*x),x)"); 69 | maptest("diff((-1*3*4*(-3)*x),x)"); 70 | 71 | maptest("(a *(-a))"); 72 | maptest("(a * -a)"); 73 | maptest("(a * (+a))"); 74 | maptest("(a * +a)"); 75 | 76 | maptest("expand((a)*(c+d))") 77 | maptest("expand((a + b)*(c+d))") 78 | maptest("expand((a+b)*(c+d)*(e+f+g))") 79 | maptest("expand((a-1)*(b+1))") 80 | maptest("expand((a-1)*(a+1))") 81 | 82 | maptest("simplify((a-1)*(a+1)/(a+1))") 83 | maptest("simplify((a-1)*(a+1)^2/(a+1))") 84 | maptest("simplify((a-1)*(a+1)^2/(a+1)^3)") 85 | 86 | maptest("expand((a-b)^-2)") 87 | maptest("expand((a-b)^+2)") 88 | maptest("expand(((a-b)^2)/((a-b)^2))") 89 | maptest("expand((a-b)^2/(a-b)^2)") 90 | maptest("simplify(expand((a-b)^2/(a-b)^2))") 91 | maptest("simplify((a-b)^2/expand((a-b)^2))") 92 | 93 | maptest("unscaledval(-1*10)") 94 | maptest("scale(-1*10)") 95 | maptest("unsignedval(-1*10)") 96 | maptest("sign(-1*10)") 97 | maptest("(a-3)") 98 | maptest("simplify(a-3)") 99 | maptest("2-10") 100 | maptest("unscaledval(-10)") 101 | maptest("scale(-10)") 102 | maptest("sign(-10)") 103 | maptest("unsignedval(-10)") 104 | maptest("simplify(-8*a*x^2 -3*b*c^2)") 105 | 106 | maptest("simplify(x,y)") 107 | maptest("subst(y)") 108 | -------------------------------------------------------------------------------- /examples/remove1.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff('define_model(x, 0)') 6 | symdiff('define_model(y, x + z)') 7 | remove_zeros() 8 | print(('%s' % symdiff('model_value(y)'))) 9 | -------------------------------------------------------------------------------- /examples/subexpression1.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff('define_model(x, y * z)') 6 | symdiff('define_model(z, y * z)') 7 | subexpression() 8 | l = model_list() 9 | for i in l: 10 | print(("%s, %s" % (i, symdiff('model_value(%s)' % i)))) 11 | -------------------------------------------------------------------------------- /examples/table.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff('declare_model(x)') 6 | for i, v in enumerate(symdiff_table('a*x + b*c')): 7 | print('%s %s' % (i, v)) 8 | -------------------------------------------------------------------------------- /examples/undefined1.py: -------------------------------------------------------------------------------- 1 | from symdiff import * 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff('declare_model(y)') 6 | symdiff('define_model(x, 3 * y + z)') 7 | symdiff('diff(x, z)') 8 | print(('%s' % symdiff('model_value(x)'))) 9 | print(('%s' % symdiff('model_value(x__z)'))) 10 | print(('%s' % symdiff('model_value(y__z)'))) 11 | -------------------------------------------------------------------------------- /examples/utf8.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from symdiff import * 3 | # Any copyright is dedicated to the Public Domain. 4 | # http://creativecommons.org/publicdomain/zero/1.0/ 5 | 6 | alpha = 'α' 7 | print(alpha) 8 | x = symdiff('%s' % alpha); 9 | x = symdiff('diff(%s^2, %s)' % (alpha, alpha)); 10 | print(x) 11 | -------------------------------------------------------------------------------- /goldenresults/unix/arrhenius_py2.out: -------------------------------------------------------------------------------- 1 | unique3, pow(T,(-1)) 2 | unique12, (Ea * unique3) 3 | unique11, exp((-unique12)) 4 | arrhenius, (Cf * pow(T,Etar) * unique11) 5 | fprod, UNDEFINED 6 | unique4, pow(A2,(-1)) 7 | unique2, (-unique3 + unique4) 8 | unique5, pow(R,(-1)) 9 | unique1, (A1 * unique2 * unique5) 10 | unique0, exp(unique1) 11 | KC1, (A3 * R * T * unique0) 12 | unique8, pow(KC1,(-1)) 13 | kb_model, (arrhenius * unique8) 14 | rprod, (AR * CN * H) 15 | unique10, (vr_H - vf_H) 16 | omega_dot_H, ((-(kb_model * rprod) + (arrhenius * fprod)) * unique10) 17 | arrhenius__T, ((Cf * Ea * pow(T,(-2 + Etar)) * unique11) + (Cf * Etar * pow(T,(-1 + Etar)) * unique11)) 18 | fprod__T, UNDEFINED 19 | KC1__T, ((A1 * A3 * unique0 * unique3) + (A3 * R * unique0)) 20 | unique9, pow(KC1,(-2)) 21 | kb_model__T, (-(KC1__T * arrhenius * unique9) + (arrhenius__T * unique8)) 22 | omega_dot_H__T, ((-(kb_model__T * rprod) + (arrhenius * fprod__T) + (arrhenius__T * fprod)) * unique10) 23 | fprod__H, UNDEFINED 24 | rprod__H, (AR * CN) 25 | omega_dot_H__H, ((-(kb_model * rprod__H) + (arrhenius * fprod__H)) * unique10) 26 | fprod__HCN, UNDEFINED 27 | omega_dot_H__HCN, (arrhenius * fprod__HCN * unique10) 28 | fprod__AR, UNDEFINED 29 | rprod__AR, (CN * H) 30 | omega_dot_H__AR, ((-(kb_model * rprod__AR) + (arrhenius * fprod__AR)) * unique10) 31 | fprod__CN, UNDEFINED 32 | rprod__CN, (AR * H) 33 | omega_dot_H__CN, ((-(kb_model * rprod__CN) + (arrhenius * fprod__CN)) * unique10) 34 | -------------------------------------------------------------------------------- /goldenresults/unix/arrhenius_py3.out: -------------------------------------------------------------------------------- 1 | unique3, pow(T,(-1)) 2 | unique12, (Ea * unique3) 3 | unique11, exp((-unique12)) 4 | arrhenius, (Cf * pow(T,Etar) * unique11) 5 | fprod, UNDEFINED 6 | unique4, pow(A2,(-1)) 7 | unique2, (-unique3 + unique4) 8 | unique5, pow(R,(-1)) 9 | unique1, (A1 * unique2 * unique5) 10 | unique0, exp(unique1) 11 | KC1, (A3 * R * T * unique0) 12 | unique8, pow(KC1,(-1)) 13 | kb_model, (arrhenius * unique8) 14 | rprod, (AR * CN * H) 15 | unique10, (vr_H - vf_H) 16 | omega_dot_H, ((-(kb_model * rprod) + (arrhenius * fprod)) * unique10) 17 | arrhenius__T, ((Cf * Ea * pow(T,(-2 + Etar)) * unique11) + (Cf * Etar * pow(T,(-1 + Etar)) * unique11)) 18 | fprod__T, UNDEFINED 19 | KC1__T, ((A1 * A3 * unique0 * unique3) + (A3 * R * unique0)) 20 | unique9, pow(KC1,(-2)) 21 | kb_model__T, (-(KC1__T * arrhenius * unique9) + (arrhenius__T * unique8)) 22 | omega_dot_H__T, ((-(kb_model__T * rprod) + (arrhenius * fprod__T) + (arrhenius__T * fprod)) * unique10) 23 | fprod__H, UNDEFINED 24 | rprod__H, (AR * CN) 25 | omega_dot_H__H, ((-(kb_model * rprod__H) + (arrhenius * fprod__H)) * unique10) 26 | fprod__HCN, UNDEFINED 27 | omega_dot_H__HCN, (arrhenius * fprod__HCN * unique10) 28 | fprod__AR, UNDEFINED 29 | rprod__AR, (CN * H) 30 | omega_dot_H__AR, ((-(kb_model * rprod__AR) + (arrhenius * fprod__AR)) * unique10) 31 | fprod__CN, UNDEFINED 32 | rprod__CN, (AR * H) 33 | omega_dot_H__CN, ((-(kb_model * rprod__CN) + (arrhenius * fprod__CN)) * unique10) 34 | -------------------------------------------------------------------------------- /goldenresults/unix/arrhenius_tcl.out: -------------------------------------------------------------------------------- 1 | unique3, pow(T,(-1)) 2 | unique12, (Ea * unique3) 3 | unique11, exp((-unique12)) 4 | arrhenius, (Cf * pow(T,Etar) * unique11) 5 | fprod, UNDEFINED 6 | unique4, pow(A2,(-1)) 7 | unique2, (-unique3 + unique4) 8 | unique5, pow(R,(-1)) 9 | unique1, (A1 * unique2 * unique5) 10 | unique0, exp(unique1) 11 | KC1, (A3 * R * T * unique0) 12 | unique8, pow(KC1,(-1)) 13 | kb_model, (arrhenius * unique8) 14 | rprod, (AR * CN * H) 15 | unique10, (vr_H - vf_H) 16 | omega_dot_H, ((-(kb_model * rprod) + (arrhenius * fprod)) * unique10) 17 | arrhenius__T, ((Cf * Ea * pow(T,(-2 + Etar)) * unique11) + (Cf * Etar * pow(T,(-1 + Etar)) * unique11)) 18 | fprod__T, UNDEFINED 19 | KC1__T, ((A1 * A3 * unique0 * unique3) + (A3 * R * unique0)) 20 | unique9, pow(KC1,(-2)) 21 | kb_model__T, (-(KC1__T * arrhenius * unique9) + (arrhenius__T * unique8)) 22 | omega_dot_H__T, ((-(kb_model__T * rprod) + (arrhenius * fprod__T) + (arrhenius__T * fprod)) * unique10) 23 | fprod__H, UNDEFINED 24 | rprod__H, (AR * CN) 25 | omega_dot_H__H, ((-(kb_model * rprod__H) + (arrhenius * fprod__H)) * unique10) 26 | fprod__HCN, UNDEFINED 27 | omega_dot_H__HCN, (arrhenius * fprod__HCN * unique10) 28 | fprod__AR, UNDEFINED 29 | rprod__AR, (CN * H) 30 | omega_dot_H__AR, ((-(kb_model * rprod__AR) + (arrhenius * fprod__AR)) * unique10) 31 | fprod__CN, UNDEFINED 32 | rprod__CN, (AR * H) 33 | omega_dot_H__CN, ((-(kb_model * rprod__CN) + (arrhenius * fprod__CN)) * unique10) 34 | -------------------------------------------------------------------------------- /goldenresults/unix/deftest_py2.out: -------------------------------------------------------------------------------- 1 | f(x, y) 2 | pow(y,2) 3 | ((2 * x * y) + (3 * pow(y,2))) 4 | pow(x,2) 5 | ((2 * x * y) + (3 * pow(x,2))) 6 | cos(x) 7 | sin(x) 8 | cos(x) 9 | cos(x) 10 | 0 11 | (2 * x * cos(pow(x,2))) 12 | (2 * y * cos(pow(y,2))) 13 | 0 14 | f(x, y) 15 | pow(y,2) 16 | ((2 * x * y) + (3 * pow(y,2))) 17 | pow(x,2) 18 | ((2 * x * y) + (3 * pow(x,2))) 19 | 0 20 | g(x, y, z) 21 | f(x, y, z) 22 | (0 + 0 + g(y, z, x)) 23 | (0 + 0 + 0) 24 | (0 + 0 + g(b, c, a)) 25 | (0 + 0 + 1) 26 | (0 + 0 + 0) 27 | 0 28 | (a + b) 29 | ((a + b) * (a + b)) 30 | ((2 * a * b) + pow(a,2) + pow(b,2)) 31 | ((2 * a * b) + pow(a,2) + pow(b,2)) 32 | (1 + (2 * a * b) + pow(a,2) + pow(b,2)) 33 | (1 - (1 + (2 * a * b) + pow(a,2) + pow(b,2)) + (2 * a * b) + pow(a,2) + pow(b,2)) 34 | (1 - (1 + (2 * a * b) + pow(a,2) + pow(b,2)) + (2 * a * b) + pow(a,2) + pow(b,2)) 35 | 0 36 | -------------------------------------------------------------------------------- /goldenresults/unix/deftest_py3.out: -------------------------------------------------------------------------------- 1 | f(x, y) 2 | pow(y,2) 3 | ((2 * x * y) + (3 * pow(y,2))) 4 | pow(x,2) 5 | ((2 * x * y) + (3 * pow(x,2))) 6 | cos(x) 7 | sin(x) 8 | cos(x) 9 | cos(x) 10 | 0 11 | (2 * x * cos(pow(x,2))) 12 | (2 * y * cos(pow(y,2))) 13 | 0 14 | f(x, y) 15 | pow(y,2) 16 | ((2 * x * y) + (3 * pow(y,2))) 17 | pow(x,2) 18 | ((2 * x * y) + (3 * pow(x,2))) 19 | 0 20 | g(x, y, z) 21 | f(x, y, z) 22 | (0 + 0 + g(y, z, x)) 23 | (0 + 0 + 0) 24 | (0 + 0 + g(b, c, a)) 25 | (0 + 0 + 1) 26 | (0 + 0 + 0) 27 | 0 28 | (a + b) 29 | ((a + b) * (a + b)) 30 | ((2 * a * b) + pow(a,2) + pow(b,2)) 31 | ((2 * a * b) + pow(a,2) + pow(b,2)) 32 | (1 + (2 * a * b) + pow(a,2) + pow(b,2)) 33 | (1 - (1 + (2 * a * b) + pow(a,2) + pow(b,2)) + (2 * a * b) + pow(a,2) + pow(b,2)) 34 | (1 - (1 + (2 * a * b) + pow(a,2) + pow(b,2)) + (2 * a * b) + pow(a,2) + pow(b,2)) 35 | 0 36 | -------------------------------------------------------------------------------- /goldenresults/unix/maple.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | void fs(const double a, const double b, double &f1, double &f2, double &f3) 4 | { 5 | const double unique0 = sin(a); 6 | const double unique2 = cos(a); 7 | const double unique9 = (unique0 * unique2); 8 | f1 = ((b * unique0) + unique9); 9 | const double unique12 = (b * unique0 * unique2); 10 | const double unique6 = cos(b); 11 | f2 = ((unique0 * unique2 * unique6) + unique12 + unique9); 12 | f3 = (-unique12 + (a * unique2)); 13 | } 14 | -------------------------------------------------------------------------------- /goldenresults/unix/maple.out: -------------------------------------------------------------------------------- 1 | 2 | 3 | BEFORE 4 | 5 | 6 | f1, ((b * sin(a)) + (cos(a) * sin(a))) 7 | f2, ((b * cos(a) * sin(a)) + (cos(a) * cos(b) * sin(a)) + (cos(a) * sin(a))) 8 | f3, (-(b * cos(a) * sin(a)) + (a * cos(a))) 9 | 10 | 11 | ORDERED for f1, f2, f3 12 | 13 | 14 | unique0, sin(a) 15 | unique2, cos(a) 16 | unique9, (unique0 * unique2) 17 | f1, ((b * unique0) + unique9) 18 | unique12, (b * unique0 * unique2) 19 | unique6, cos(b) 20 | f2, ((unique0 * unique2 * unique6) + unique12 + unique9) 21 | f3, (-unique12 + (a * unique2)) 22 | unique10, pow(unique0,2) 23 | unique11, pow(unique2,2) 24 | f1__a, (-unique10 + (b * unique2) + unique11) 25 | f1__b, unique0 26 | unique15, (b * unique10) 27 | unique16, (b * unique11) 28 | f2__a, (-(unique10 * unique6) - unique10 - unique15 + (unique11 * unique6) + unique11 + unique16) 29 | f2__b, (-(unique0 * unique2 * sin(b)) + unique9) 30 | f3__a, (-(a * unique0) - unique16 + unique15 + unique2) 31 | f3__b, (-unique9) 32 | -------------------------------------------------------------------------------- /goldenresults/unix/modellist1_py2.out: -------------------------------------------------------------------------------- 1 | x 2 | y 3 | -------------------------------------------------------------------------------- /goldenresults/unix/modellist1_py3.out: -------------------------------------------------------------------------------- 1 | x 2 | y 3 | -------------------------------------------------------------------------------- /goldenresults/unix/models1_py2.out: -------------------------------------------------------------------------------- 1 | x 2 | y 3 | y__x 4 | 0 5 | ('y',) 6 | x 7 | ('x', 'y') 8 | x 9 | While calling symdiff interpreter 10 | y is being processed in terms of itself 11 | 12 | x y 13 | y (a * x) 14 | y__x a 15 | 16 | x 17 | y 18 | y__x 19 | 0 20 | (2 * x) 21 | (2 * x__z) 22 | x UNDEFINED 23 | x__z UNDEFINED 24 | y__x (2 * x) 25 | 26 | y__x (2 * x) 27 | -------------------------------------------------------------------------------- /goldenresults/unix/models1_py3.out: -------------------------------------------------------------------------------- 1 | x 2 | y 3 | y__x 4 | 0 5 | ('y',) 6 | x 7 | ('x', 'y') 8 | x 9 | While calling symdiff interpreter 10 | y is being processed in terms of itself 11 | 12 | x y 13 | y (a * x) 14 | y__x a 15 | 16 | x 17 | y 18 | y__x 19 | 0 20 | (2 * x) 21 | (2 * x__z) 22 | x UNDEFINED 23 | x__z UNDEFINED 24 | y__x (2 * x) 25 | 26 | y__x (2 * x) 27 | -------------------------------------------------------------------------------- /goldenresults/unix/ordered_py2.out: -------------------------------------------------------------------------------- 1 | b 2 | d 3 | -------------------------------------------------------------------------------- /goldenresults/unix/ordered_py3.out: -------------------------------------------------------------------------------- 1 | b 2 | d 3 | -------------------------------------------------------------------------------- /goldenresults/unix/parsetest_py2.out: -------------------------------------------------------------------------------- 1 | 2 | a*x 3 | (a * x) 4 | 5 | simplify(a*a) 6 | pow(a,2) 7 | 8 | simplify(pow(x, 0.0)) 9 | 1 10 | 11 | simplify(pow(x, 1.0)) 12 | x 13 | 14 | simplify(pow(1.0, x)) 15 | 1 16 | 17 | simplify(exp(1.0)) 18 | exp(1) 19 | 20 | simplify(exp(0.0)) 21 | 1 22 | 23 | simplify(exp(log(x))) 24 | x 25 | 26 | simplify(log(exp(x))) 27 | x 28 | 29 | simplify(log(1.0)) 30 | 0 31 | 32 | (exp(pow(c,pow(x,pow(c,x))))) 33 | exp(pow(c,pow(x,pow(c,x)))) 34 | 35 | diff((exp(pow(c,pow(x,pow(c,x))))),x) 36 | (((pow(c,x) * pow(x,(pow(c,x) - 1))) + (pow(c,x) * pow(x,pow(c,x)) * log(c) * log(x))) * exp(pow(c,pow(x,pow(c,x)))) * pow(c,pow(x,pow(c,x))) * log(c)) 37 | 38 | simplify(diff((exp(pow(c,pow(x,pow(c,x))))),x)) 39 | (((pow(c,x) * pow(x,(-1 + pow(c,x)))) + (pow(c,x) * pow(x,pow(c,x)) * log(c) * log(x))) * exp(pow(c,pow(x,pow(c,x)))) * pow(c,pow(x,pow(c,x))) * log(c)) 40 | 41 | simplify((((((((1 * pow(x,(-1))) * pow(c,x)) + ((log(c) * pow(c,x)) * log(x))) * pow(x,pow(c,x))) * log(c)) * pow(c,pow(x,pow(c,x)))) * exp(pow(c,pow(x,pow(c,x)))))) 42 | (((pow(c,x) * log(c) * log(x)) + (pow(c,x) * pow(x,(-1)))) * exp(pow(c,pow(x,pow(c,x)))) * pow(c,pow(x,pow(c,x))) * pow(x,pow(c,x)) * log(c)) 43 | 44 | simplify(a*5*pow(a,-1)) 45 | 5 46 | 47 | c*c*c*c 48 | (c * c * c * c) 49 | 50 | simplify(c*c*c*c) 51 | pow(c,4) 52 | 53 | diff(c*c*x*x,x) 54 | ((c * c * x) + (c * c * x)) 55 | 56 | simplify(log(pow(x,y))) 57 | (y * log(x)) 58 | 59 | simplify(a*a+a*a*a) 60 | (pow(a,2) + pow(a,3)) 61 | 62 | simplify(a*a+a*a) 63 | (2 * pow(a,2)) 64 | 65 | simplify(a+a+a*a) 66 | ((2 * a) + pow(a,2)) 67 | 68 | simplify(a+a+a+a*a) 69 | ((3 * a) + pow(a,2)) 70 | 71 | simplify(y*pow(x,(-1)) * pow(x,y)) 72 | (y * pow(x,(-1 + y))) 73 | 74 | simplify(pow(x,(-1)) * pow(x,y)*y) 75 | (y * pow(x,(-1 + y))) 76 | 77 | simplify(pow(x,(-1)) * pow(x,y)*x) 78 | pow(x,y) 79 | 80 | unscaledval(2*x) 81 | x 82 | 83 | scale(2*x) 84 | 2 85 | 86 | a - a 87 | (a - a) 88 | 89 | a + -a 90 | (a - a) 91 | 92 | a - b 93 | (a - b) 94 | 95 | simplify(a - a) 96 | 0 97 | 98 | simplify(a + -a) 99 | 0 100 | 101 | simplify(a - b) 102 | (a - b) 103 | 104 | -simplify(a - b) 105 | (-(a - b)) 106 | 107 | simplify(-simplify(a - b)) 108 | (-(a - b)) 109 | 110 | (-1*3*4*-3*x) 111 | (-(-3) * 3 * 4 * x) 112 | 113 | simplify(-1*3*4*-3*x) 114 | (36 * x) 115 | 116 | -a 117 | (-a) 118 | 119 | a++-+a 120 | (a - a) 121 | 122 | a+*+a 123 | While calling symdiff interpreter 124 | While evaluating expression "a+*+a" 125 | syntax error 126 | 127 | 128 | diff(-1*3*4*(-3)*x,x) 129 | (-(-3) * 3 * 4) 130 | 131 | diff(simplify(-1*3*4*(-3)*x),x) 132 | 36 133 | 134 | diff((-1*3*4*(-3)*x),x) 135 | (-(-3) * 3 * 4) 136 | 137 | (a *(-a)) 138 | (-a * a) 139 | 140 | (a * -a) 141 | (-a * a) 142 | 143 | (a * (+a)) 144 | (a * a) 145 | 146 | (a * +a) 147 | (a * a) 148 | 149 | expand((a)*(c+d)) 150 | ((a * c) + (a * d)) 151 | 152 | expand((a + b)*(c+d)) 153 | ((a * c) + (a * d) + (b * c) + (b * d)) 154 | 155 | expand((a+b)*(c+d)*(e+f+g)) 156 | ((a * c * e) + (a * c * f) + (a * c * g) + (a * d * e) + (a * d * f) + (a * d * g) + (b * c * e) + (b * c * f) + (b * c * g) + (b * d * e) + (b * d * f) + (b * d * g)) 157 | 158 | expand((a-1)*(b+1)) 159 | (-1 + a - b + (a * b)) 160 | 161 | expand((a-1)*(a+1)) 162 | (-1 + pow(a,2)) 163 | 164 | simplify((a-1)*(a+1)/(a+1)) 165 | (-1 + a) 166 | 167 | simplify((a-1)*(a+1)^2/(a+1)) 168 | ((-1 + a) * (1 + a)) 169 | 170 | simplify((a-1)*(a+1)^2/(a+1)^3) 171 | ((-1 + a) * pow((1 + a),(-1))) 172 | 173 | expand((a-b)^-2) 174 | pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) 175 | 176 | expand((a-b)^+2) 177 | (-(2 * a * b) + pow(a,2) + pow(b,2)) 178 | 179 | expand(((a-b)^2)/((a-b)^2)) 180 | (-(2 * a * b * pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1))) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(a,2)) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(b,2))) 181 | 182 | expand((a-b)^2/(a-b)^2) 183 | (-(2 * a * b * pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1))) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(a,2)) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(b,2))) 184 | 185 | simplify(expand((a-b)^2/(a-b)^2)) 186 | (-(2 * a * b * pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1))) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(a,2)) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(b,2))) 187 | 188 | simplify((a-b)^2/expand((a-b)^2)) 189 | (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow((a - b),2)) 190 | 191 | unscaledval(-1*10) 192 | 1 193 | 194 | scale(-1*10) 195 | (-10) 196 | 197 | unsignedval(-1*10) 198 | (-10) 199 | 200 | sign(-1*10) 201 | 1 202 | 203 | (a-3) 204 | (a + (-3)) 205 | 206 | simplify(a-3) 207 | (-3 + a) 208 | 209 | 2-10 210 | (2 + (-10)) 211 | 212 | unscaledval(-10) 213 | 1 214 | 215 | scale(-10) 216 | (-10) 217 | 218 | sign(-10) 219 | (-1) 220 | 221 | unsignedval(-10) 222 | 10 223 | 224 | simplify(-8*a*x^2 -3*b*c^2) 225 | (-(3 * b * pow(c,2)) - (8 * a * pow(x,2))) 226 | 227 | simplify(x,y) 228 | While calling symdiff interpreter 229 | While evaluating expression "simplify(x,y)" 230 | Function "simplify" expects 1 argument and you provided 2: "x", "y" 231 | 232 | 233 | subst(y) 234 | While calling symdiff interpreter 235 | While evaluating expression "subst(y)" 236 | Function "subst" expects 3 arguments and you provided 1: "y" 237 | 238 | -------------------------------------------------------------------------------- /goldenresults/unix/parsetest_py3.out: -------------------------------------------------------------------------------- 1 | 2 | a*x 3 | (a * x) 4 | 5 | simplify(a*a) 6 | pow(a,2) 7 | 8 | simplify(pow(x, 0.0)) 9 | 1 10 | 11 | simplify(pow(x, 1.0)) 12 | x 13 | 14 | simplify(pow(1.0, x)) 15 | 1 16 | 17 | simplify(exp(1.0)) 18 | exp(1) 19 | 20 | simplify(exp(0.0)) 21 | 1 22 | 23 | simplify(exp(log(x))) 24 | x 25 | 26 | simplify(log(exp(x))) 27 | x 28 | 29 | simplify(log(1.0)) 30 | 0 31 | 32 | (exp(pow(c,pow(x,pow(c,x))))) 33 | exp(pow(c,pow(x,pow(c,x)))) 34 | 35 | diff((exp(pow(c,pow(x,pow(c,x))))),x) 36 | (((pow(c,x) * pow(x,(pow(c,x) - 1))) + (pow(c,x) * pow(x,pow(c,x)) * log(c) * log(x))) * exp(pow(c,pow(x,pow(c,x)))) * pow(c,pow(x,pow(c,x))) * log(c)) 37 | 38 | simplify(diff((exp(pow(c,pow(x,pow(c,x))))),x)) 39 | (((pow(c,x) * pow(x,(-1 + pow(c,x)))) + (pow(c,x) * pow(x,pow(c,x)) * log(c) * log(x))) * exp(pow(c,pow(x,pow(c,x)))) * pow(c,pow(x,pow(c,x))) * log(c)) 40 | 41 | simplify((((((((1 * pow(x,(-1))) * pow(c,x)) + ((log(c) * pow(c,x)) * log(x))) * pow(x,pow(c,x))) * log(c)) * pow(c,pow(x,pow(c,x)))) * exp(pow(c,pow(x,pow(c,x)))))) 42 | (((pow(c,x) * log(c) * log(x)) + (pow(c,x) * pow(x,(-1)))) * exp(pow(c,pow(x,pow(c,x)))) * pow(c,pow(x,pow(c,x))) * pow(x,pow(c,x)) * log(c)) 43 | 44 | simplify(a*5*pow(a,-1)) 45 | 5 46 | 47 | c*c*c*c 48 | (c * c * c * c) 49 | 50 | simplify(c*c*c*c) 51 | pow(c,4) 52 | 53 | diff(c*c*x*x,x) 54 | ((c * c * x) + (c * c * x)) 55 | 56 | simplify(log(pow(x,y))) 57 | (y * log(x)) 58 | 59 | simplify(a*a+a*a*a) 60 | (pow(a,2) + pow(a,3)) 61 | 62 | simplify(a*a+a*a) 63 | (2 * pow(a,2)) 64 | 65 | simplify(a+a+a*a) 66 | ((2 * a) + pow(a,2)) 67 | 68 | simplify(a+a+a+a*a) 69 | ((3 * a) + pow(a,2)) 70 | 71 | simplify(y*pow(x,(-1)) * pow(x,y)) 72 | (y * pow(x,(-1 + y))) 73 | 74 | simplify(pow(x,(-1)) * pow(x,y)*y) 75 | (y * pow(x,(-1 + y))) 76 | 77 | simplify(pow(x,(-1)) * pow(x,y)*x) 78 | pow(x,y) 79 | 80 | unscaledval(2*x) 81 | x 82 | 83 | scale(2*x) 84 | 2 85 | 86 | a - a 87 | (a - a) 88 | 89 | a + -a 90 | (a - a) 91 | 92 | a - b 93 | (a - b) 94 | 95 | simplify(a - a) 96 | 0 97 | 98 | simplify(a + -a) 99 | 0 100 | 101 | simplify(a - b) 102 | (a - b) 103 | 104 | -simplify(a - b) 105 | (-(a - b)) 106 | 107 | simplify(-simplify(a - b)) 108 | (-(a - b)) 109 | 110 | (-1*3*4*-3*x) 111 | (-(-3) * 3 * 4 * x) 112 | 113 | simplify(-1*3*4*-3*x) 114 | (36 * x) 115 | 116 | -a 117 | (-a) 118 | 119 | a++-+a 120 | (a - a) 121 | 122 | a+*+a 123 | While calling symdiff interpreter 124 | While evaluating expression "a+*+a" 125 | syntax error 126 | 127 | 128 | diff(-1*3*4*(-3)*x,x) 129 | (-(-3) * 3 * 4) 130 | 131 | diff(simplify(-1*3*4*(-3)*x),x) 132 | 36 133 | 134 | diff((-1*3*4*(-3)*x),x) 135 | (-(-3) * 3 * 4) 136 | 137 | (a *(-a)) 138 | (-a * a) 139 | 140 | (a * -a) 141 | (-a * a) 142 | 143 | (a * (+a)) 144 | (a * a) 145 | 146 | (a * +a) 147 | (a * a) 148 | 149 | expand((a)*(c+d)) 150 | ((a * c) + (a * d)) 151 | 152 | expand((a + b)*(c+d)) 153 | ((a * c) + (a * d) + (b * c) + (b * d)) 154 | 155 | expand((a+b)*(c+d)*(e+f+g)) 156 | ((a * c * e) + (a * c * f) + (a * c * g) + (a * d * e) + (a * d * f) + (a * d * g) + (b * c * e) + (b * c * f) + (b * c * g) + (b * d * e) + (b * d * f) + (b * d * g)) 157 | 158 | expand((a-1)*(b+1)) 159 | (-1 + a - b + (a * b)) 160 | 161 | expand((a-1)*(a+1)) 162 | (-1 + pow(a,2)) 163 | 164 | simplify((a-1)*(a+1)/(a+1)) 165 | (-1 + a) 166 | 167 | simplify((a-1)*(a+1)^2/(a+1)) 168 | ((-1 + a) * (1 + a)) 169 | 170 | simplify((a-1)*(a+1)^2/(a+1)^3) 171 | ((-1 + a) * pow((1 + a),(-1))) 172 | 173 | expand((a-b)^-2) 174 | pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) 175 | 176 | expand((a-b)^+2) 177 | (-(2 * a * b) + pow(a,2) + pow(b,2)) 178 | 179 | expand(((a-b)^2)/((a-b)^2)) 180 | (-(2 * a * b * pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1))) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(a,2)) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(b,2))) 181 | 182 | expand((a-b)^2/(a-b)^2) 183 | (-(2 * a * b * pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1))) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(a,2)) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(b,2))) 184 | 185 | simplify(expand((a-b)^2/(a-b)^2)) 186 | (-(2 * a * b * pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1))) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(a,2)) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(b,2))) 187 | 188 | simplify((a-b)^2/expand((a-b)^2)) 189 | (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow((a - b),2)) 190 | 191 | unscaledval(-1*10) 192 | 1 193 | 194 | scale(-1*10) 195 | (-10) 196 | 197 | unsignedval(-1*10) 198 | (-10) 199 | 200 | sign(-1*10) 201 | 1 202 | 203 | (a-3) 204 | (a + (-3)) 205 | 206 | simplify(a-3) 207 | (-3 + a) 208 | 209 | 2-10 210 | (2 + (-10)) 211 | 212 | unscaledval(-10) 213 | 1 214 | 215 | scale(-10) 216 | (-10) 217 | 218 | sign(-10) 219 | (-1) 220 | 221 | unsignedval(-10) 222 | 10 223 | 224 | simplify(-8*a*x^2 -3*b*c^2) 225 | (-(3 * b * pow(c,2)) - (8 * a * pow(x,2))) 226 | 227 | simplify(x,y) 228 | While calling symdiff interpreter 229 | While evaluating expression "simplify(x,y)" 230 | Function "simplify" expects 1 argument and you provided 2: "x", "y" 231 | 232 | 233 | subst(y) 234 | While calling symdiff interpreter 235 | While evaluating expression "subst(y)" 236 | Function "subst" expects 3 arguments and you provided 1: "y" 237 | 238 | -------------------------------------------------------------------------------- /goldenresults/unix/parsetest_tcl.out: -------------------------------------------------------------------------------- 1 | 2 | a*x 3 | (a * x) 4 | 5 | simplify(a*a) 6 | pow(a,2) 7 | 8 | simplify(pow(x, 0.0)) 9 | 1 10 | 11 | simplify(pow(x, 1.0)) 12 | x 13 | 14 | simplify(pow(1.0, x)) 15 | 1 16 | 17 | simplify(exp(1.0)) 18 | exp(1) 19 | 20 | simplify(exp(0.0)) 21 | 1 22 | 23 | simplify(exp(log(x))) 24 | x 25 | 26 | simplify(log(exp(x))) 27 | x 28 | 29 | simplify(log(1.0)) 30 | 0 31 | 32 | (exp(pow(c,pow(x,pow(c,x))))) 33 | exp(pow(c,pow(x,pow(c,x)))) 34 | 35 | diff((exp(pow(c,pow(x,pow(c,x))))),x) 36 | (((pow(c,x) * pow(x,(pow(c,x) - 1))) + (pow(c,x) * pow(x,pow(c,x)) * log(c) * log(x))) * exp(pow(c,pow(x,pow(c,x)))) * pow(c,pow(x,pow(c,x))) * log(c)) 37 | 38 | simplify(diff((exp(pow(c,pow(x,pow(c,x))))),x)) 39 | (((pow(c,x) * pow(x,(-1 + pow(c,x)))) + (pow(c,x) * pow(x,pow(c,x)) * log(c) * log(x))) * exp(pow(c,pow(x,pow(c,x)))) * pow(c,pow(x,pow(c,x))) * log(c)) 40 | 41 | simplify((((((((1 * pow(x,(-1))) * pow(c,x)) + ((log(c) * pow(c,x)) * log(x))) * pow(x,pow(c,x))) * log(c)) * pow(c,pow(x,pow(c,x)))) * exp(pow(c,pow(x,pow(c,x)))))) 42 | (((pow(c,x) * log(c) * log(x)) + (pow(c,x) * pow(x,(-1)))) * exp(pow(c,pow(x,pow(c,x)))) * pow(c,pow(x,pow(c,x))) * pow(x,pow(c,x)) * log(c)) 43 | 44 | simplify(a*5*pow(a,-1)) 45 | 5 46 | 47 | c*c*c*c 48 | (c * c * c * c) 49 | 50 | simplify(c*c*c*c) 51 | pow(c,4) 52 | 53 | diff(c*c*x*x,x) 54 | ((c * c * x) + (c * c * x)) 55 | 56 | simplify(log(pow(x,y))) 57 | (y * log(x)) 58 | 59 | simplify(a*a+a*a*a) 60 | (pow(a,2) + pow(a,3)) 61 | 62 | simplify(a*a+a*a) 63 | (2 * pow(a,2)) 64 | 65 | simplify(a+a+a*a) 66 | ((2 * a) + pow(a,2)) 67 | 68 | simplify(a+a+a+a*a) 69 | ((3 * a) + pow(a,2)) 70 | 71 | simplify(y*pow(x,(-1)) * pow(x,y)) 72 | (y * pow(x,(-1 + y))) 73 | 74 | simplify(pow(x,(-1)) * pow(x,y)*y) 75 | (y * pow(x,(-1 + y))) 76 | 77 | simplify(pow(x,(-1)) * pow(x,y)*x) 78 | pow(x,y) 79 | 80 | unscaledval(2*x) 81 | x 82 | 83 | scale(2*x) 84 | 2 85 | 86 | a - a 87 | (a - a) 88 | 89 | a + -a 90 | (a - a) 91 | 92 | a - b 93 | (a - b) 94 | 95 | simplify(a - a) 96 | 0 97 | 98 | simplify(a + -a) 99 | 0 100 | 101 | simplify(a - b) 102 | (a - b) 103 | 104 | -simplify(a - b) 105 | (-(a - b)) 106 | 107 | simplify(-simplify(a - b)) 108 | (-(a - b)) 109 | 110 | (-1*3*4*-3*x) 111 | (-(-3) * 3 * 4 * x) 112 | 113 | simplify(-1*3*4*-3*x) 114 | (36 * x) 115 | 116 | -a 117 | (-a) 118 | 119 | a++-+a 120 | (a - a) 121 | 122 | a+*+a 123 | While calling symdiff interpreter 124 | While evaluating expression "a+*+a" 125 | syntax error 126 | 127 | 128 | diff(-1*3*4*(-3)*x,x) 129 | (-(-3) * 3 * 4) 130 | 131 | diff(simplify(-1*3*4*(-3)*x),x) 132 | 36 133 | 134 | diff((-1*3*4*(-3)*x),x) 135 | (-(-3) * 3 * 4) 136 | 137 | (a *(-a)) 138 | (-a * a) 139 | 140 | (a * -a) 141 | (-a * a) 142 | 143 | (a * (+a)) 144 | (a * a) 145 | 146 | (a * +a) 147 | (a * a) 148 | 149 | expand((a)*(c+d)) 150 | ((a * c) + (a * d)) 151 | 152 | expand((a + b)*(c+d)) 153 | ((a * c) + (a * d) + (b * c) + (b * d)) 154 | 155 | expand((a+b)*(c+d)*(e+f+g)) 156 | ((a * c * e) + (a * c * f) + (a * c * g) + (a * d * e) + (a * d * f) + (a * d * g) + (b * c * e) + (b * c * f) + (b * c * g) + (b * d * e) + (b * d * f) + (b * d * g)) 157 | 158 | expand((a-1)*(b+1)) 159 | (-1 + a - b + (a * b)) 160 | 161 | expand((a-1)*(a+1)) 162 | (-1 + pow(a,2)) 163 | 164 | simplify((a-1)*(a+1)/(a+1)) 165 | (-1 + a) 166 | 167 | simplify((a-1)*(a+1)^2/(a+1)) 168 | ((-1 + a) * (1 + a)) 169 | 170 | simplify((a-1)*(a+1)^2/(a+1)^3) 171 | ((-1 + a) * pow((1 + a),(-1))) 172 | 173 | expand((a-b)^-2) 174 | pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) 175 | 176 | expand((a-b)^+2) 177 | (-(2 * a * b) + pow(a,2) + pow(b,2)) 178 | 179 | expand(((a-b)^2)/((a-b)^2)) 180 | (-(2 * a * b * pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1))) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(a,2)) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(b,2))) 181 | 182 | expand((a-b)^2/(a-b)^2) 183 | (-(2 * a * b * pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1))) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(a,2)) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(b,2))) 184 | 185 | simplify(expand((a-b)^2/(a-b)^2)) 186 | (-(2 * a * b * pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1))) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(a,2)) + (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow(b,2))) 187 | 188 | simplify((a-b)^2/expand((a-b)^2)) 189 | (pow((-(2 * a * b) + pow(a,2) + pow(b,2)),(-1)) * pow((a - b),2)) 190 | 191 | unscaledval(-1*10) 192 | 1 193 | 194 | scale(-1*10) 195 | (-10) 196 | 197 | unsignedval(-1*10) 198 | (-10) 199 | 200 | sign(-1*10) 201 | 1 202 | 203 | (a-3) 204 | (a + (-3)) 205 | 206 | simplify(a-3) 207 | (-3 + a) 208 | 209 | 2-10 210 | (2 + (-10)) 211 | 212 | unscaledval(-10) 213 | 1 214 | 215 | scale(-10) 216 | (-10) 217 | 218 | sign(-10) 219 | (-1) 220 | 221 | unsignedval(-10) 222 | 10 223 | 224 | simplify(-8*a*x^2 -3*b*c^2) 225 | (-(3 * b * pow(c,2)) - (8 * a * pow(x,2))) 226 | 227 | simplify(x,y) 228 | While calling symdiff interpreter 229 | While evaluating expression "simplify(x,y)" 230 | Function "simplify" expects 1 argument and you provided 2: "x", "y" 231 | 232 | 233 | subst(y) 234 | While calling symdiff interpreter 235 | While evaluating expression "subst(y)" 236 | Function "subst" expects 3 arguments and you provided 1: "y" 237 | 238 | -------------------------------------------------------------------------------- /goldenresults/unix/remove1_py2.out: -------------------------------------------------------------------------------- 1 | z 2 | -------------------------------------------------------------------------------- /goldenresults/unix/remove1_py3.out: -------------------------------------------------------------------------------- 1 | z 2 | -------------------------------------------------------------------------------- /goldenresults/unix/subexpression1_py2.out: -------------------------------------------------------------------------------- 1 | unique0, (y * z) 2 | x, unique0 3 | z, unique0 4 | -------------------------------------------------------------------------------- /goldenresults/unix/subexpression1_py3.out: -------------------------------------------------------------------------------- 1 | unique0, (y * z) 2 | x, unique0 3 | z, unique0 4 | -------------------------------------------------------------------------------- /goldenresults/unix/symdiff1.out: -------------------------------------------------------------------------------- 1 | "exp(0)" 2 | "exp(0)" 3 | "0" 4 | 5 | 6 | "simplify(exp(0))" 7 | "1" 8 | "0" 9 | 10 | 11 | "exp(1)" 12 | "exp(1)" 13 | "0" 14 | 15 | 16 | "exp(2)" 17 | "exp(2)" 18 | "0" 19 | 20 | 21 | "pow(x,0)" 22 | "pow(x,0)" 23 | "0" 24 | 25 | 26 | "simplify(pow(x,0))" 27 | "1" 28 | "0" 29 | 30 | 31 | "pow(x,1)" 32 | "pow(x,1)" 33 | "1" 34 | 35 | 36 | "simplify(pow(x,1))" 37 | "x" 38 | "1" 39 | 40 | 41 | "pow(x*y,1)" 42 | "pow((x * y),1)" 43 | "y" 44 | 45 | 46 | "pow(x*y,2)" 47 | "pow((x * y),2)" 48 | "(2 * x * y * y)" 49 | 50 | 51 | "pow(x,2)" 52 | "pow(x,2)" 53 | "(2 * x)" 54 | 55 | 56 | "pow(2,x)" 57 | "pow(2,x)" 58 | "(log(2) * pow(2,x))" 59 | 60 | 61 | "pow(2,x*y)" 62 | "pow(2,(x * y))" 63 | "(y * pow(2,(x * y)) * log(2))" 64 | 65 | 66 | "pow(2,3)" 67 | "pow(2,3)" 68 | "0" 69 | 70 | 71 | "pow(0,x)" 72 | "pow(0,x)" 73 | "0" 74 | 75 | 76 | "simplify(pow(0,x))" 77 | "0" 78 | "0" 79 | 80 | 81 | "pow(1,x)" 82 | "pow(1,x)" 83 | "0" 84 | 85 | 86 | "simplify(pow(1,x))" 87 | "1" 88 | "0" 89 | 90 | 91 | "exp(x)" 92 | "exp(x)" 93 | "exp(x)" 94 | 95 | 96 | "exp(x*y)" 97 | "exp((x * y))" 98 | "(y * exp((x * y)))" 99 | 100 | 101 | "log(x)" 102 | "log(x)" 103 | "pow(x,(-1))" 104 | 105 | 106 | "log(x*y)" 107 | "log((x * y))" 108 | "(y * pow((x * y),(-1)))" 109 | 110 | 111 | "log(1)" 112 | "log(1)" 113 | "0" 114 | 115 | 116 | "x*y" 117 | "(x * y)" 118 | "y" 119 | 120 | 121 | "x" 122 | "x" 123 | "1" 124 | 125 | 126 | "0*x" 127 | "0" 128 | "0" 129 | 130 | 131 | "0*x*y" 132 | "0" 133 | "0" 134 | 135 | 136 | "x*y*z" 137 | "(x * y * z)" 138 | "(y * z)" 139 | 140 | 141 | "0+x+y" 142 | "(x + y)" 143 | "1" 144 | 145 | 146 | "pow(x*y,z)" 147 | "pow((x * y),z)" 148 | "(y * z * pow((x * y),(z - 1)))" 149 | 150 | 151 | "pow(y,x*z)" 152 | "pow(y,(x * z))" 153 | "(z * pow(y,(x * z)) * log(y))" 154 | 155 | 156 | "pow(x*y,x*z)" 157 | "pow((x * y),(x * z))" 158 | "((x * y * z * pow((x * y),((x * z) - 1))) + (z * pow((x * y),(x * z)) * log((x * y))))" 159 | 160 | 161 | -------------------------------------------------------------------------------- /goldenresults/unix/symdiff2.out: -------------------------------------------------------------------------------- 1 | x__y 2 | 1 3 | z 4 | z__x 5 | z__a 6 | ((2 * a) + (b * c)) 7 | 0 8 | 2 9 | qq 10 | (2 * a) 11 | qq 12 | ((2 * a) + b) 13 | qq 14 | (b + (2 * a) + qq) 15 | qq 16 | (b + (2 * a) + qq) 17 | -------------------------------------------------------------------------------- /goldenresults/unix/symdiff3.out: -------------------------------------------------------------------------------- 1 | 2 | 3 | BEFORE 4 | 5 | 6 | a, (b + d) 7 | c, (b + d) 8 | 9 | 10 | AFTER 11 | 12 | 13 | a, unique0 14 | c, unique0 15 | unique0, (b + d) 16 | x, (a + c) 17 | 18 | 19 | ORDERED for a c 20 | 21 | 22 | unique0, (b + d) 23 | a, unique0 24 | c, unique0 25 | 26 | 27 | ORDERED for x 28 | 29 | 30 | unique0, (b + d) 31 | a, unique0 32 | c, unique0 33 | x, (a + c) 34 | 35 | 36 | ORDERED for a 37 | 38 | 39 | unique0, (b + d) 40 | a, unique0 41 | -------------------------------------------------------------------------------- /goldenresults/unix/symdiff4.out: -------------------------------------------------------------------------------- 1 | 1 2 | 0 3 | -------------------------------------------------------------------------------- /goldenresults/unix/table.out: -------------------------------------------------------------------------------- 1 | 0 a variable {} 2 a 2 | 1 x model {} 2 x 3 | 2 * product {0 1} 6 {(a * x)} 4 | 3 b variable {} 5 b 5 | 4 c variable {} 5 c 6 | 5 * product {3 4} 6 {(b * c)} 7 | 6 + add {2 5} {} {((a * x) + (b * c))} 8 | -------------------------------------------------------------------------------- /goldenresults/unix/table_py2.out: -------------------------------------------------------------------------------- 1 | 0 ('a', 'variable', (), (2L,), 'a') 2 | 1 ('x', 'model', (), (2L,), 'x') 3 | 2 ('*', 'product', (0L, 1L), (6L,), '(a * x)') 4 | 3 ('b', 'variable', (), (5L,), 'b') 5 | 4 ('c', 'variable', (), (5L,), 'c') 6 | 5 ('*', 'product', (3L, 4L), (6L,), '(b * c)') 7 | 6 ('+', 'add', (2L, 5L), (), '((a * x) + (b * c))') 8 | -------------------------------------------------------------------------------- /goldenresults/unix/table_py3.out: -------------------------------------------------------------------------------- 1 | 0 ('a', 'variable', (), (2,), 'a') 2 | 1 ('x', 'model', (), (2,), 'x') 3 | 2 ('*', 'product', (0, 1), (6,), '(a * x)') 4 | 3 ('b', 'variable', (), (5,), 'b') 5 | 4 ('c', 'variable', (), (5,), 'c') 6 | 5 ('*', 'product', (3, 4), (6,), '(b * c)') 7 | 6 ('+', 'add', (2, 5), (), '((a * x) + (b * c))') 8 | -------------------------------------------------------------------------------- /goldenresults/unix/undefined1_py2.out: -------------------------------------------------------------------------------- 1 | ((3 * y) + z) 2 | (1 + (3 * y__z)) 3 | UNDEFINED 4 | -------------------------------------------------------------------------------- /goldenresults/unix/undefined1_py3.out: -------------------------------------------------------------------------------- 1 | ((3 * y) + z) 2 | (1 + (3 * y__z)) 3 | UNDEFINED 4 | -------------------------------------------------------------------------------- /goldenresults/unix/units.out: -------------------------------------------------------------------------------- 1 | (Kg * pow((m * pow(s,(-1))),2)) 2 | -------------------------------------------------------------------------------- /goldenresults/unix/utf8_py2.out: -------------------------------------------------------------------------------- 1 | α 2 | (2 * α) 3 | -------------------------------------------------------------------------------- /goldenresults/unix/utf8_py3.out: -------------------------------------------------------------------------------- 1 | α 2 | (2 * α) 3 | -------------------------------------------------------------------------------- /lib/symdiff/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | 4 | if sys.version_info[0] == 3: 5 | from .symdiff_py3 import * 6 | from .symdiff_py3 import __version__ 7 | else: 8 | raise ImportError('module not available for Python %d.%d please contact technical support' % sys.version_info[0:2]) 9 | 10 | 11 | -------------------------------------------------------------------------------- /scripts/build_appveyor.bat: -------------------------------------------------------------------------------- 1 | 2 | @echo off 3 | @SETLOCAL 4 | SET BASEDIR=%cd% 5 | 6 | SET CONDA_BIN=%2 7 | 8 | call %CONDA_BIN% create -y -n symdiff_build python=3.7 9 | if %errorlevel% neq 0 exit /b %errorlevel% 10 | 11 | call %CONDA_BIN% install -y -n symdiff_build cmake tk 12 | if %errorlevel% neq 0 exit /b %errorlevel% 13 | 14 | call %CONDA_BIN% activate symdiff_build 15 | if %errorlevel% neq 0 exit /b %errorlevel% 16 | 17 | SET PATH="c:\msys64\usr\bin;%PATH%" 18 | c:\msys64\usr\bin\bash %~dp0\setup_appveyor.sh %1 19 | if %errorlevel% neq 0 exit /b %errorlevel% 20 | 21 | -------------------------------------------------------------------------------- /scripts/build_docker_manylinux2014.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -u 4 | export DEVSIM_ARCH=$(uname -m) 5 | docker run -it -d --name manylinux2014 quay.io/pypa/manylinux2014_${DEVSIM_ARCH} && 6 | (cd .. && tar czf symdiff.tgz symdiff && docker cp symdiff.tgz manylinux2014:/root/) && 7 | docker exec manylinux2014 bash -c "git config --global --add safe.directory /root/symdiff" 8 | docker exec manylinux2014 bash -c "cd /root && tar xzf symdiff.tgz"; 9 | docker exec manylinux2014 bash -c "cd /root/symdiff && bash scripts/build_manylinux2014.sh"; 10 | (for i in $(docker exec manylinux2014 bash -c "ls /root/symdiff/*.whl"); do docker cp manylinux2014:${i} .; done) 11 | docker stop manylinux2014 12 | -------------------------------------------------------------------------------- /scripts/build_docker_manylinux_2_28.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -u 4 | export DEVSIM_ARCH=$(uname -m) 5 | 6 | if [ "$DEVSIM_ARCH" = "arm64" ]; then 7 | DEVSIM_ARCH=aarch64 8 | fi 9 | 10 | docker run -it -d --name manylinux_2_28 quay.io/pypa/manylinux_2_28_${DEVSIM_ARCH} && 11 | (cd .. && tar czf symdiff.tgz symdiff && docker cp symdiff.tgz manylinux_2_28:/root/) && 12 | docker exec manylinux_2_28 bash -c "git config --global --add safe.directory /root/symdiff" 13 | docker exec manylinux_2_28 bash -c "cd /root && tar xzf symdiff.tgz"; 14 | docker exec manylinux_2_28 bash -c "cd /root/symdiff && bash scripts/build_manylinux_2_28.sh"; 15 | (for i in $(docker exec manylinux_2_28 bash -c "ls /root/symdiff/*.whl"); do docker cp manylinux_2_28:${i} .; done) 16 | docker stop manylinux_2_28 17 | 18 | -------------------------------------------------------------------------------- /scripts/build_macos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -u 4 | 5 | export CMAKE="cmake" 6 | export CMAKE_CXX_FLAGS="" 7 | export CC=clang; 8 | export CXX=clang++; 9 | export F77=""; 10 | 11 | export PYTHON3_BIN=python3 12 | export PIP_BIN=pip3 13 | ${PIP_BIN} install wheel 14 | export PYTHON3_INCLUDE=$(${PYTHON3_BIN} -c "from sysconfig import get_paths as gp; print(gp()['include'])") 15 | export PYTHON3_ARCHIVE="" 16 | 17 | export MACOSX_DEPLOYMENT_TARGET=12.0 18 | 19 | # SYMDIFF build 20 | export ARCH_ARG="-DCMAKE_OSX_ARCHITECTURES=arm64" 21 | #export PLAT_NAME="arm64" 22 | #export ARCH_ARG="-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" 23 | #export PLAT_NAME="universal2" 24 | 25 | (bash scripts/symdiff_macos.sh && cd osx_release && make -j4) 26 | (cd osx_release && make test) 27 | 28 | (rsync -avP --exclude __pycache__ bdist_wheel/ dist) 29 | (rsync -avP --exclude __pycache__ lib/symdiff dist/) 30 | (rsync -avP --exclude __pycache__ LICENSE NOTICE README.md examples doc dist) 31 | 32 | FULL_PLAT_NAME=arm64 33 | echo PACKAGING $FULL_PLAT_NAME 34 | if [[ -n "$FULL_PLAT_NAME" ]]; then 35 | (cd dist && perl -p -i -e "s/^#plat-name.*/plat-name = ${FULL_PLAT_NAME}/" setup.cfg); 36 | fi 37 | (cd dist && ${PIP_BIN} wheel .) 38 | (mv dist/*.whl .) 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /scripts/build_manylinux2014.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -u 4 | export DEVSIM_ARCH=$(uname -m) 5 | 6 | yum install -y bison flex rsync 7 | 8 | export CMAKE="cmake" 9 | export CMAKE_CXX_FLAGS="" 10 | export CXX="g++" 11 | 12 | export PYTHON3_BIN=python3.7 13 | export PIP_BIN=/opt/python/cp37-cp37m/bin/pip 14 | ${PIP_BIN} install wheel auditwheel 15 | export PYTHON3_INCLUDE=$(${PYTHON3_BIN} -c "from sysconfig import get_paths as gp; print(gp()['include'])") 16 | export PYTHON3_ARCHIVE="" 17 | 18 | # SYMDIFF build 19 | (bash scripts/symdiff_centos.sh && cd linux_${DEVSIM_ARCH}_release && make -j2 && make test); 20 | (rsync -avP --exclude __pycache__ lib/symdiff bdist_wheel/) 21 | (rsync -avP --exclude __pycache__ LICENSE NOTICE README.md examples doc bdist_wheel) 22 | (cd bdist_wheel && ${PIP_BIN} wheel .) 23 | (cd bdist_wheel && auditwheel repair *.whl) 24 | (mv bdist_wheel/wheelhouse/*.whl .) 25 | 26 | -------------------------------------------------------------------------------- /scripts/build_manylinux_2_28.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -u 4 | export DEVSIM_ARCH=$(uname -m) 5 | 6 | yum install -y bison flex rsync 7 | 8 | export CMAKE="cmake" 9 | export CMAKE_CXX_FLAGS="" 10 | export CXX="g++" 11 | 12 | export PYTHON3_BIN=python3.7 13 | export PIP_BIN=/opt/python/cp37-cp37m/bin/pip 14 | ${PIP_BIN} install wheel auditwheel 15 | export PYTHON3_INCLUDE=$(${PYTHON3_BIN} -c "from sysconfig import get_paths as gp; print(gp()['include'])") 16 | export PYTHON3_ARCHIVE="" 17 | 18 | # SYMDIFF build 19 | (bash scripts/symdiff_centos.sh && cd linux_${DEVSIM_ARCH}_release && make -j2 && make test); 20 | (rsync -avP --exclude __pycache__ lib/symdiff bdist_wheel/) 21 | (rsync -avP --exclude __pycache__ LICENSE NOTICE README.md examples doc bdist_wheel) 22 | (cd bdist_wheel && ${PIP_BIN} wheel .) 23 | (cd bdist_wheel && auditwheel repair *.whl) 24 | (mv bdist_wheel/wheelhouse/*.whl .) 25 | 26 | -------------------------------------------------------------------------------- /scripts/mkindex.tcl: -------------------------------------------------------------------------------- 1 | set ext [info sharedlibextension] 2 | if {${ext} eq ".dylib"} { 3 | pkg_mkIndex . libsymdifftcl${ext} 4 | } else { 5 | pkg_mkIndex -lazy . 6 | } 7 | -------------------------------------------------------------------------------- /scripts/setup_appveyor.sh: -------------------------------------------------------------------------------- 1 | # Any copyright is dedicated to the Public Domain. 2 | # http://creativecommons.org/publicdomain/zero/1.0/ 3 | 4 | # Note: run this file using bash 5 | set -e 6 | export PATH="/usr/bin:${PATH}" 7 | CMAKE=$(cygpath -w $(which cmake) ) 8 | CTEST=$(cygpath -w $(which ctest) ) 9 | SYMDIFF_CONFIG="appveyor" 10 | 11 | if [ "$1" = x86 ]; then 12 | GENERATOR="Visual Studio 17 2022" 13 | AOPTION="Win32" 14 | BUILDDIR="win32" 15 | TOOLSET="v143" 16 | elif [ "$1" = x64 ]; then 17 | GENERATOR="Visual Studio 17 2022" 18 | AOPTION="x64" 19 | BUILDDIR="win64" 20 | TOOLSET="v143" 21 | elif [ "$1" = clangx64 ]; then 22 | GENERATOR="Visual Studio 17 2022" 23 | AOPTION="x64" 24 | BUILDDIR="clangwin64" 25 | TOOLSET="ClangCL" 26 | else 27 | echo "Must specify x86 or x64 or clangx64" 28 | exit -1 29 | fi 30 | 31 | 32 | mkdir -p ${BUILDDIR} 33 | (cd ${BUILDDIR}; "${CMAKE}" -G "${GENERATOR}" -A "${AOPTION}" -T "${TOOLSET}" -DSYMDIFF_CONFIG=${SYMDIFF_CONFIG} -DTCLMAIN=ON -DPYTHON3=ON -DANACONDA_PATH="${CONDA_PREFIX}" ..) 34 | 35 | libpath=`cygpath -w ${PWD}/lib` 36 | 37 | #echo $libpath 38 | # TODO: fix to use conda activate 39 | mkdir -p bin 40 | cat << EOF > bin/symdiff_py3.bat 41 | @setlocal 42 | @echo off 43 | SET PATH=${CONDA_PREFIX};${CONDA_PREFIX}\\Library\\bin;%PATH% 44 | SET PYTHONIOENCODING=utf-8 45 | SET PYTHONPATH=$libpath 46 | python %* 47 | EOF 48 | chmod +x bin/symdiff_py3.bat 49 | 50 | # TCLLIBPATH must always use forward slashes 51 | libpath=`/usr/bin/cygpath -m $PWD/lib` 52 | cat << EOF > bin/symdiff_tcl.bat 53 | @setlocal 54 | @echo off 55 | SET PATH=${CONDA_PREFIX};${CONDA_PREFIX}\\Library\\bin;%PATH% 56 | SET TCLLIBPATH="$libpath" %TCLLIBPATH% 57 | tclsh %* 58 | EOF 59 | chmod +x bin/symdiff_tcl.bat 60 | 61 | 62 | 63 | # The // is so that MSYS does not consider it a path 64 | (cd ${BUILDDIR} && ${CMAKE} --build . --config Release -- //m //nologo //verbosity:minimal) 65 | 66 | (cd ${BUILDDIR} && ${CTEST} --verbose) 67 | 68 | pacman -Su --noconfirm rsync 69 | (rsync -avP --exclude __pycache__ lib/symdiff bdist_wheel/) 70 | (rsync -avP --exclude __pycache__ LICENSE NOTICE README.md examples doc bdist_wheel) 71 | pip install --upgrade wheel 72 | (cd bdist_wheel && pip wheel .) 73 | (mv bdist_wheel/*.whl .) 74 | -------------------------------------------------------------------------------- /scripts/setup_osx_anaconda.sh: -------------------------------------------------------------------------------- 1 | # Any copyright is dedicated to the Public Domain. 2 | # http://creativecommons.org/publicdomain/zero/1.0/ 3 | CMAKE="cmake" 4 | CMAKE_CXX_FLAGS="" 5 | CXX="/usr/bin/g++" 6 | TCL_ARCHIVE="/usr/lib/libtclstub8.5.a" 7 | TCL_INCLUDE="/usr/include" 8 | TCL_BIN="${HOME}/anaconda/bin/tclsh8.6" 9 | PYTHON3_ARCHIVE="${HOME}/anaconda/envs/python37/lib/libpython3.7m.dylib" 10 | PYTHON3_INCLUDE="${HOME}/anaconda/envs/python37/include/python3.7m" 11 | PYTHON3_BIN="${HOME}/anaconda/envs/python37/bin/python" 12 | #-DCMAKE_OSX_ARCHITECTURES="i386;x86_64" \ 13 | for TYPE in debug release; do 14 | NAME=osx_${TYPE} 15 | mkdir ${NAME} 16 | (cd $NAME; ${CMAKE} \ 17 | -DCMAKE_CXX_FLAGS:STRING="${CMAKE_CXX_FLAGS}" \ 18 | -DCMAKE_BUILD_TYPE=${TYPE} \ 19 | -DCMAKE_CXX_COMPILER=${CXX} \ 20 | -DPYTHON3_INCLUDE=${PYTHON3_INCLUDE} \ 21 | -DTCL_INCLUDE=${TCL_INCLUDE} \ 22 | -DTCL_ARCHIVE=${TCL_ARCHIVE} \ 23 | -DTCL_BIN=${TCL_BIN} \ 24 | -DPYTHON3=ON \ 25 | ..) 26 | done 27 | mkdir -p bin 28 | 29 | cat << EOF > bin/symdiff_py3 30 | #!/bin/bash 31 | set -e 32 | progname="\$0" 33 | curdir=\`dirname "\$progname"\` 34 | export PYTHONPATH=\${curdir}/../lib 35 | ${PYTHON3_BIN} \$* 36 | EOF 37 | chmod +x bin/symdiff_py3 38 | 39 | cat << EOF > bin/symdiff_tcl 40 | #!/bin/bash 41 | set -e 42 | progname="\$0" 43 | curdir=\`dirname "\$progname"\` 44 | export TCLLIBPATH=\${curdir}/../lib 45 | ${TCL_BIN} \$* 46 | EOF 47 | chmod +x bin/symdiff_tcl 48 | 49 | -------------------------------------------------------------------------------- /scripts/setup_ubuntu_18.sh: -------------------------------------------------------------------------------- 1 | # Any copyright is dedicated to the Public Domain. 2 | # http://creativecommons.org/publicdomain/zero/1.0/ 3 | CMAKE="/usr/bin/cmake" 4 | CMAKE_CXX_FLAGS="" 5 | CXX="/usr/bin/g++" 6 | TCL_ARCHIVE="/usr/lib/x86_64-linux-gnu/libtclstub8.5.a" 7 | TCL_INCLUDE="/usr/include/tcl8.5" 8 | TCL_BIN="/usr/bin/tclsh8.5" 9 | PYTHON3_ARCHIVE="/usr/lib/x86_64-linux-gnu/libpython3.6m.so" 10 | PYTHON3_INCLUDE="/usr/include/python3.6m" 11 | PYTHON3_BIN="/usr/bin/python3.6m" 12 | for TYPE in debug release; do 13 | ARCH=`uname -m` 14 | # for ARCH in i386 x86_64; do 15 | NAME=linux_${ARCH}_${TYPE} 16 | mkdir ${NAME} 17 | (cd $NAME; ${CMAKE} \ 18 | -DCMAKE_CXX_FLAGS:STRING="${CMAKE_CXX_FLAGS}" \ 19 | -DCMAKE_BUILD_TYPE=${TYPE} \ 20 | -DCMAKE_CXX_COMPILER=${CXX} \ 21 | -DPYTHON3_INCLUDE=${PYTHON3_INCLUDE} \ 22 | -DTCL_INCLUDE=${TCL_INCLUDE} \ 23 | -DTCL_ARCHIVE=${TCL_ARCHIVE} \ 24 | -DTCL_BIN=${TCL_BIN} \ 25 | -DPYTHON3=ON \ 26 | ..) 27 | # done 28 | done 29 | mkdir -p bin 30 | 31 | cat << EOF > bin/symdiff 32 | #!/bin/bash 33 | set -e 34 | progname="\$0" 35 | curdir=\`dirname "\$progname"\` 36 | export LD_LIBRARY_PATH=\${curdir}/../lib 37 | export PYTHONPATH=\${curdir}/../lib 38 | ${PYTHON_BIN} \$* 39 | EOF 40 | chmod +x bin/symdiff 41 | 42 | cat << EOF > bin/symdiff_py3 43 | #!/bin/bash 44 | set -e 45 | progname="\$0" 46 | curdir=\`dirname "\$progname"\` 47 | export LD_LIBRARY_PATH=\${curdir}/../lib 48 | export PYTHONPATH=\${curdir}/../lib 49 | ${PYTHON3_BIN} \$* 50 | EOF 51 | chmod +x bin/symdiff_py3 52 | 53 | cat << EOF > bin/symdiff_tcl 54 | #!/bin/bash 55 | set -e 56 | progname="\$0" 57 | curdir=\`dirname "\$progname"\` 58 | export LD_LIBRARY_PATH=\${curdir}/../lib 59 | export TCLLIBPATH=\${curdir}/../lib 60 | ${TCL_BIN} \$* 61 | EOF 62 | chmod +x bin/symdiff_tcl 63 | 64 | -------------------------------------------------------------------------------- /scripts/symdiff_centos.sh: -------------------------------------------------------------------------------- 1 | # Any copyright is dedicated to the Public Domain. 2 | # http://creativecommons.org/publicdomain/zero/1.0/ 3 | for TYPE in debug release; do 4 | ARCH=`uname -m` 5 | # for ARCH in i386 x86_64; do 6 | NAME=linux_${ARCH}_${TYPE} 7 | mkdir ${NAME} 8 | (cd $NAME; ${CMAKE} \ 9 | -DCMAKE_CXX_FLAGS:STRING="${CMAKE_CXX_FLAGS}" \ 10 | -DCMAKE_BUILD_TYPE=${TYPE} \ 11 | -DCMAKE_CXX_COMPILER=${CXX} \ 12 | -DPYTHON3_INCLUDE=${PYTHON3_INCLUDE} \ 13 | -DPYTHON3=ON \ 14 | -DTCLMAIN=OFF \ 15 | ..) 16 | # done 17 | done 18 | mkdir -p bin 19 | cat << EOF > bin/symdiff 20 | #!/bin/bash 21 | set -e 22 | progname="\$0" 23 | curdir=\`dirname "\$progname"\` 24 | export PYTHONPATH=\${curdir}/../lib 25 | ${PYTHON_BIN} \$* 26 | EOF 27 | chmod +x bin/symdiff 28 | 29 | cat << EOF > bin/symdiff_py3 30 | #!/bin/bash 31 | set -e 32 | progname="\$0" 33 | curdir=\`dirname "\$progname"\` 34 | export PYTHONPATH=\${curdir}/../lib 35 | ${PYTHON3_BIN} \$* 36 | EOF 37 | chmod +x bin/symdiff_py3 38 | 39 | #cat << EOF > bin/symdiff_tcl 40 | ##!/bin/bash 41 | #set -e 42 | #progname="\$0" 43 | #curdir=\`dirname "\$progname"\` 44 | #export TCLLIBPATH=\${curdir}/../lib 45 | #${TCL_BIN} \$* 46 | #EOF 47 | #chmod +x bin/symdiff_tcl 48 | 49 | -------------------------------------------------------------------------------- /scripts/symdiff_macos.sh: -------------------------------------------------------------------------------- 1 | # Any copyright is dedicated to the Public Domain. 2 | # http://creativecommons.org/publicdomain/zero/1.0/ 3 | for TYPE in debug release; do 4 | NAME=osx_${TYPE} 5 | mkdir ${NAME} 6 | (cd $NAME; ${CMAKE} \ 7 | ${ARCH_ARG} \ 8 | -DCMAKE_CXX_FLAGS:STRING="${CMAKE_CXX_FLAGS}" \ 9 | -DCMAKE_BUILD_TYPE=${TYPE} \ 10 | -DCMAKE_CXX_COMPILER=${CXX} \ 11 | -DPYTHON3_INCLUDE=${PYTHON3_INCLUDE} \ 12 | -DPYTHON3=ON \ 13 | -DTCLMAIN=OFF \ 14 | ..) 15 | # done 16 | done 17 | mkdir -p bin 18 | cat << EOF > bin/symdiff 19 | #!/bin/bash 20 | set -e 21 | progname="\$0" 22 | curdir=\`dirname "\$progname"\` 23 | export PYTHONPATH=\${curdir}/../lib 24 | ${PYTHON_BIN} \$* 25 | EOF 26 | chmod +x bin/symdiff 27 | 28 | cat << EOF > bin/symdiff_py3 29 | #!/bin/bash 30 | set -e 31 | progname="\$0" 32 | curdir=\`dirname "\$progname"\` 33 | export PYTHONPATH=\${curdir}/../lib 34 | ${PYTHON3_BIN} \$* 35 | EOF 36 | chmod +x bin/symdiff_py3 37 | 38 | #cat << EOF > bin/symdiff_tcl 39 | ##!/bin/bash 40 | #set -e 41 | #progname="\$0" 42 | #curdir=\`dirname "\$progname"\` 43 | #export TCLLIBPATH=\${curdir}/../lib 44 | #${TCL_BIN} \$* 45 | #EOF 46 | #chmod +x bin/symdiff_tcl 47 | 48 | -------------------------------------------------------------------------------- /sphinx/NOTICE: -------------------------------------------------------------------------------- 1 | 2 | Copyright © 2009–2018 DEVSIM LLC 3 | 4 | SYMDIFF is a trademark of DEVSIM LLC. 5 | 6 | This work is licensed under the Creative Commons Attribution-NoDerivatives 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nd/4.0/. 7 | 8 | -------------------------------------------------------------------------------- /sphinx/source/additional.rst: -------------------------------------------------------------------------------- 1 | 2 | .. include:: macros.txt 3 | 4 | .. _ch__additional: 5 | 6 | Additional Information 7 | ---------------------- 8 | 9 | Other Examples 10 | ~~~~~~~~~~~~~~ 11 | 12 | The ``arrhenius.py`` example demonstrates the use of all of the model manipulation algorithms. The ``utf8.py`` is an example using |unicode| encoding. 13 | 14 | Licenses 15 | ~~~~~~~~ 16 | 17 | .. _symdiff__license: 18 | 19 | SYMDIFF 20 | ^^^^^^^ 21 | 22 | .. code:: 23 | 24 | Copyright 2012-2016 DEVSIM LLC 25 | 26 | Licensed under the Apache License, Version 2.0 (the "License"); 27 | you may not use this file except in compliance with the License. 28 | You may obtain a copy of the License at 29 | 30 | http://www.apache.org/licenses/LICENSE-2.0 31 | 32 | Unless required by applicable law or agreed to in writing, software 33 | distributed under the License is distributed on an "AS IS" BASIS, 34 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 | See the License for the specific language governing permissions and 36 | limitations under the License. 37 | 38 | Python 39 | ^^^^^^ 40 | 41 | The |python| license is available by typing ``license()`` in an interactive session. More information is available from their website at ``_. 42 | 43 | Tcl 44 | ^^^ 45 | 46 | The |tcl| license is may be viewed at ``_. 47 | 48 | -------------------------------------------------------------------------------- /sphinx/source/advanced.rst: -------------------------------------------------------------------------------- 1 | 2 | .. include:: macros.txt 3 | 4 | Generating Source Code 5 | ---------------------- 6 | 7 | model_list 8 | ~~~~~~~~~~ 9 | 10 | This command prints a list of all models which have been defined up to this point in the execution of |symdiff|. This is shown in the ``modellist1.py`` example: 11 | 12 | .. code:: 13 | 14 | symdiff('declare_model(x)') 15 | symdiff('declare_model(y)') 16 | l = model_list() 17 | for i in l: 18 | print('%s' % i) 19 | 20 | The resulting output is then: 21 | 22 | .. code:: 23 | 24 | x 25 | y 26 | 27 | ordered_list 28 | ~~~~~~~~~~~~ 29 | 30 | This command takes a list of 1 or more model names. The resulting list is in the order necessary to ensure that the models are evaluated in the correct order. In this example, ``ordered.py``, we define 2 models, and |symdiff| prints what order the models would have to be defined. 31 | 32 | .. code:: 33 | 34 | symdiff('define_model(b, a)') 35 | symdiff('define_model(d, b * c)') 36 | mylist = ordered_list('d') 37 | for i in mylist: 38 | print('%s' % i) 39 | 40 | The resulting output is then: 41 | 42 | .. code:: 43 | 44 | b 45 | d 46 | 47 | For ordering multiple model names, pass multiple names, or a list using this syntax. 48 | 49 | .. code:: 50 | 51 | ordered_list('a', 'b') 52 | args = ('a', 'b') 53 | ordered_list(*args) 54 | 55 | 56 | remove_zeros 57 | ~~~~~~~~~~~~ 58 | 59 | This command removes all models whose evaluation results in ``0``. Any models which rely on the definition of models will substitute a ``0`` in their expression for this model. This is shown in the ``remove1.py`` example. 60 | 61 | .. code:: 62 | 63 | symdiff('define_model(x, 0)') 64 | symdiff('define_model(y, x + z)') 65 | remove_zeros() 66 | print('%s' % symdiff('model_value(y)')) 67 | 68 | The resulting output is then: 69 | 70 | .. code:: 71 | 72 | z 73 | 74 | 75 | subexpression 76 | ~~~~~~~~~~~~~ 77 | 78 | This command will evaluate all of the currently defined models and find common sub expressions. If more than one dependent model uses the same sub-expression, |symdiff| will automatically substitute it with a new model with a generated name, as shown in the ``subexpression1.py`` example. 79 | 80 | .. code:: 81 | 82 | symdiff('define_model(x, simplify(y * z))') 83 | symdiff('define_model(z, simplify(z * y))') 84 | subexpression() 85 | l = model_list() 86 | for i in l: 87 | print("%s, %s" % (i, symdiff('model_value(%s)' % i))) 88 | 89 | The resulting output is then: 90 | 91 | .. code:: 92 | 93 | unique0, (y * z) 94 | x, unique0 95 | z, unique0 96 | 97 | The use of the ``simplify`` method is important to ensure that the subexpression elimination algorithm can recognize the common expressions. 98 | 99 | 100 | -------------------------------------------------------------------------------- /sphinx/source/devsim.bib: -------------------------------------------------------------------------------- 1 | @misc{gplv3, 2 | title = {{GNU} {G}eneral {P}ublic {L}icense {V}ersion 3}, 3 | author = {{F}ree {S}oftware {F}oundation}, 4 | url = {http://www.gnu.org/licenses/gpl.html}, 5 | } 6 | 7 | @misc{lgplv3, 8 | title = {{GNU} {L}esser {G}eneral {P}ublic {L}icense {V}ersion 3}, 9 | author = {{F}ree {S}oftware {F}oundation}, 10 | url = {http://www.gnu.org/licenses/lgpl.html}, 11 | } 12 | 13 | @misc{apache2, 14 | title = {{A}pache {L}icense, {V}ersion 2.0}, 15 | author = {{A}pache {S}oftware {F}oundation}, 16 | url = {http://www.apache.org/licenses/LICENSE-2.0.html}, 17 | } 18 | 19 | 20 | @Article{Gmsh:2009, 21 | author = "C. Geuzaine and J.-F. Remacle", 22 | title = "Gmsh: a three-dimensional finite element mesh generator with built-in pre- and post-processing facilities", 23 | journal = "International Journal for Numerical Methods in Engineering", 24 | year = "2009" 25 | } 26 | 27 | 28 | @Article{Ousterhout98scripting:higher, 29 | author = {John K. Ousterhout}, 30 | title = "Scripting: Higher level programming for the 21st century", 31 | journal = {IEEE Computer}, 32 | year = {1998}, 33 | volume = {31}, 34 | pages = {23--30} 35 | } 36 | 37 | @article{superlu99, 38 | author = {James W. Demmel and Stanley C. Eisenstat and 39 | John R. Gilbert and Xiaoye S. Li and Joseph W. H. Liu}, 40 | title = {A supernodal approach to sparse partial pivoting}, 41 | journal = {SIAM J. Matrix Analysis and Applications}, 42 | year = {1999}, 43 | volume = {20}, 44 | number = {3}, 45 | pages = {720-755} 46 | } 47 | 48 | @book{TclBook, 49 | author = "Brent Welch and Ken Jones and Jeffrey Hobbs", 50 | title = "Practical Programming in Tcl and Tk", 51 | edition = "4", 52 | publisher = "Prentice Hall PTR", 53 | year = "2003" 54 | } 55 | 56 | @book{Mueller, 57 | author = "Richard S. Muller and Theodore I. Kamins and Mansun Chan", 58 | title = "Device Electronics for Integrated Circuits", 59 | edition = "3", 60 | publisher = "John Wiley \& Sons", 61 | year = "2002" 62 | 63 | } 64 | @misc{adiff, 65 | title = "Adiff website", 66 | howpublished = "\url{http://www.adiff.com}" 67 | } 68 | 69 | @misc{python, 70 | title = "Python Programming Language –- Official Website", 71 | howpublished = "\url{http://www.python.org}" 72 | } 73 | 74 | @misc{atlas-hp, 75 | TITLE = "Automatically Tuned Linear Algebra Software~({ATLAS})", 76 | howpublished = "\url{http://math-atlas.sourceforge.net/}" 77 | } 78 | 79 | @Article{sgieeeted1969, 80 | author = "D. L. Scharfetter and H. K. Gummel", 81 | title = "Large-Signal Analysis of a Silicon {R}ead Diode Oscillator", 82 | journal = {IEEE Trans. Electron Devices}, 83 | volume = "ED-16", 84 | number = "1", 85 | pages = "64--77", 86 | month = jan, 87 | year = "1969", 88 | } 89 | 90 | -------------------------------------------------------------------------------- /sphinx/source/frontmatter.rst: -------------------------------------------------------------------------------- 1 | 2 | .. include:: macros.txt 3 | 4 | Front Matter 5 | ------------ 6 | 7 | .. _Contact: 8 | 9 | 10 | Contact 11 | ~~~~~~~ 12 | 13 | .. table:: 14 | 15 | ==================== ================= 16 | Web: |devsimurl| 17 | Email: info@devsim.com 18 | Open Source Project: |symdiffurl| 19 | ==================== ================= 20 | 21 | 22 | Copyright 23 | ~~~~~~~~~ 24 | 25 | |mycopyright| 26 | 27 | Documentation License 28 | ~~~~~~~~~~~~~~~~~~~~~ 29 | 30 | .. raw:: html 31 | 32 | Creative Commons License
SYMDIFF Manual by DEVSIM LLC is licensed under a Creative Commons Attribution-NoDerivatives 4.0 International License. 33 | 34 | .. only:: latex 35 | 36 | This work is licensed under the Creative Commons Attribution-NoDerivatives 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nd/4.0/. 37 | 38 | Disclaimer 39 | ~~~~~~~~~~ 40 | 41 | |devsimllc| MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 42 | 43 | Trademark 44 | ~~~~~~~~~ 45 | 46 | |devsim| is a registered trademark and |symdiff| is a trademark of |devsimllc|. All other product or company names are trademarks of their respective owners. 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /sphinx/source/index.rst: -------------------------------------------------------------------------------- 1 | .. SYMDIFF documentation master file, created by 2 | sphinx-quickstart on Sun Jun 5 20:56:38 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | SYMDIFF Manual 7 | ============== 8 | 9 | .. only:: html 10 | 11 | Contents: 12 | 13 | .. toctree:: 14 | :maxdepth: 2 15 | 16 | frontmatter 17 | 18 | releasenotes 19 | 20 | introduction 21 | 22 | syntax 23 | 24 | advanced 25 | 26 | additional 27 | 28 | installation 29 | 30 | references 31 | 32 | 33 | 34 | 35 | .. only:: html 36 | 37 | Indices and tables 38 | ================== 39 | 40 | * :ref:`genindex` 41 | * :ref:`modindex` 42 | * :ref:`search` 43 | 44 | -------------------------------------------------------------------------------- /sphinx/source/installation.rst: -------------------------------------------------------------------------------- 1 | 2 | .. include:: macros.txt 3 | 4 | .. _ch__installation: 5 | 6 | Installation 7 | ------------ 8 | 9 | Download 10 | ~~~~~~~~ 11 | 12 | |symdiff| is currently released as a source code distribution. The software download is available at ``_. Installation notes are in the ``INSTALL`` file in the source code distribution as well as on the project website. 13 | 14 | Supported Platforms 15 | ~~~~~~~~~~~~~~~~~~~ 16 | 17 | Currently supported platforms are |linux|, |macosx|, and |mswindows|. 18 | 19 | .. _sec__examplelocation: 20 | 21 | Directory Structure 22 | ~~~~~~~~~~~~~~~~~~~ 23 | 24 | A ``symdiff`` directory is created with the following sub directories. 25 | 26 | 27 | ============= ==================================================== 28 | ``bin`` contains the |symdiff| invocation scripts 29 | ``doc`` contains |symdiff| documentation 30 | ``lib`` contains runtime libraries 31 | ``examples`` contains example scripts 32 | ``testing`` contains example scripts using the |tcl| interface 33 | ============= ==================================================== 34 | 35 | 36 | -------------------------------------------------------------------------------- /sphinx/source/introduction.rst: -------------------------------------------------------------------------------- 1 | 2 | .. include:: macros.txt 3 | 4 | Introduction 5 | ------------ 6 | 7 | Getting Started 8 | ~~~~~~~~~~~~~~~ 9 | |symdiff| is a computer algebra tool capable of taking symbolic derivatives. Using a natural syntax, it is possible to manipulate symbolic equations to aid derivation of equations for a variety of applications. Additional commands provide the means to simplify results, create common subexpressions, and order expressions for use as source code in a computer program. With its |python| and |tcl| interpreters, you have the ability to create algorithms to generate equations programatically. 10 | 11 | |symdiff| is available from |symdiffurl|. The source code is available under the terms of the Apache License Version 2.0 :cite:`apache2`. Examples are released under the Apache License Version 2.0 :cite:`apache2`. Contributions to this project are welcome in the form of bug reporting, documentation, modeling, and feature implementation. 12 | 13 | Using the Tool 14 | ~~~~~~~~~~~~~~ 15 | 16 | Interactive Mode 17 | ^^^^^^^^^^^^^^^^ 18 | 19 | The tool is invoked by typing ``symdiff`` on the command line. On some platforms, the application may also be started by clicking on the application name in a file manager. 20 | A |python| shell is started. In this introduction, we start by importing the module into the global namespace: 21 | 22 | .. code:: 23 | 24 | >>> from symdiff import * 25 | 26 | We can then start executing |symdiff| commands. 27 | 28 | .. code:: 29 | 30 | >>> symdiff ('x^y') 31 | 'pow(x,y)' 32 | 33 | In this expression, both ``x`` and ``y`` are independent variables. To differentiate the expression with respect to ``x``, we type the following: 34 | 35 | .. code:: 36 | 37 | >>> symdiff('diff(x^y,x)') 38 | '(y * pow(x,(y - 1)))' 39 | 40 | By default, any non-numeric string which is not already a function name is treated as an independent variable. 41 | 42 | If we wish to simplify the expression, we do the following 43 | 44 | .. code:: 45 | 46 | >>> symdiff('simplify(x*x+ 2*x^2)') 47 | '(3 * pow(x,2))' 48 | 49 | and to expand out an expression 50 | 51 | .. code:: 52 | 53 | >>> symdiff('expand((x+ y)*x)') 54 | '((x * y) + pow(x,2))' 55 | 56 | A semicolon ``;`` is used to send multiple commands to the interpreter, but it is not recommended, as it makes debugging more difficult. 57 | 58 | Script Mode 59 | ^^^^^^^^^^^ 60 | 61 | With its built-in |python| interpreter, |symdiff| will execute a script and can be invoked on the command line of your terminal program as: 62 | 63 | .. code:: 64 | 65 | symdiff myfile.py 66 | 67 | where ``myfile.py`` is the name of your input file. 68 | 69 | .. _sec__unicode: 70 | 71 | Unicode 72 | ^^^^^^^ 73 | 74 | The |python| interpreter, by default, only allows ASCII characters. In order to enable |unicode| in your |python| scripts, the following line on the first or second line of the script should contain: 75 | 76 | .. code:: 77 | 78 | # -*- coding: utf-8 -*- 79 | 80 | This assumes that the source file is written using \utfeight. In interactive mode, using |unicode| is not recommended, based on issues in setting the environment properly for the |python| interpreter. 81 | 82 | Tcl version 83 | ~~~~~~~~~~~ 84 | 85 | A |tcl| interface to |symdiff| is also available by starting ``symdiff_tcl``. In order to use |symdiff| in the |tcl| intepreter, the following line is required: 86 | 87 | .. code:: 88 | 89 | % package require symdifftcl 90 | 91 | -------------------------------------------------------------------------------- /sphinx/source/macros.txt: -------------------------------------------------------------------------------- 1 | 2 | .. include:: 3 | 4 | .. |devsim| replace:: ``DEVSIM`` 5 | .. |mycopyright| replace:: Copyright |copy| 2009--2019 DEVSIM LLC 6 | 7 | .. |unicode| replace:: ``unicode`` 8 | .. |anaconda| replace:: ``Anaconda`` 9 | .. |centosfive| replace:: ``Centos 5`` 10 | .. |centossix| replace:: ``Centos 6`` 11 | .. |cpluspluseleven| replace:: ``C++11`` 12 | .. |visit| replace:: ``VisIt`` 13 | .. |paraview| replace:: ``ParaView`` 14 | .. |postmini| replace:: ``Postmini`` 15 | .. |tecplot| replace:: ``Tecplot`` 16 | 17 | .. |devsimgithub| replace:: `http://www.github.com/devsim/devsim `__ 18 | .. |devsimsourceforge| replace:: `http://sourceforge.net/projects/devsim `__ 19 | .. |devsimsupport| replace:: `http://www.github.com/devsim/devsim/issues `__ 20 | .. |devsimurl| replace:: `https://devsim.com `__ 21 | .. |devsimorg| replace:: `https://devsim.org `__ 22 | .. |devsimllc| replace:: DEVSIM LLC 23 | .. |symdiffurl| replace:: `https://symdiff.org `__ 24 | 25 | .. |cgns| replace:: ``CGNS`` 26 | .. |genius| replace:: ``Genius`` 27 | .. |geniusds| replace:: ``Genius Device Simulator`` 28 | .. |gmsh| replace:: ``Gmsh`` 29 | .. |intelmkl| replace:: ``Intel Math Kernel Library`` 30 | .. |intelmklce| replace:: |intelmkl| Community Edition 31 | .. |linux| replace:: ``Linux`` 32 | .. |macosx| replace:: ``Apple Mac OS X`` 33 | .. |macosxyosemite| replace:: ``Mac OS X 10.10 (Yosemite)`` 34 | .. |mswindows| replace:: ``Microsoft Windows`` 35 | .. |mswindowsseven| replace:: ``Windows 7`` 36 | .. |python| replace:: ``Python`` 37 | .. |pythonthree| replace:: ``Python 3`` 38 | .. |pythontwoseven| replace:: ``Python 2.7`` 39 | .. |rhelfive| replace:: ``Red Hat Enterprise Linux 5`` 40 | .. |rhelsix| replace:: ``Red Hat Enterprise Linux 6`` 41 | .. |symdiff| replace:: ``SYMDIFF`` 42 | .. |tcl| replace:: ``Tcl`` 43 | .. |ubuntuprecise| replace:: ``Ubuntu 12.04 (LTS)`` 44 | .. |ubuntutrusty| replace:: ``Ubuntu 14.04 (LTS)`` 45 | 46 | .. |superlu| replace:: ``SuperLU`` 47 | .. |sqlite| replace:: ``SQLite3`` 48 | .. |zlib| replace:: ``zlib`` 49 | -------------------------------------------------------------------------------- /sphinx/source/references.rst: -------------------------------------------------------------------------------- 1 | 2 | .. only:: html 3 | 4 | Bibliography 5 | ------------ 6 | 7 | .. bibliography:: devsim.bib 8 | :cited: 9 | 10 | -------------------------------------------------------------------------------- /sphinx/source/releasenotes.rst: -------------------------------------------------------------------------------- 1 | 2 | .. include:: macros.txt 3 | 4 | Release Notes 5 | ------------- 6 | 7 | Introduction 8 | ~~~~~~~~~~~~ 9 | 10 | Release 1.0.0 (May 7, 2019) 11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | 13 | The version number has been updated to having a major revision of ``1``. We adopt the semantic version numbering presented at https://semver.org. The version number can be accessed through the |python| interface using the ``symdiff.__version__`` variable. 14 | 15 | This is the first versioned release of |symdiff|. Using the stable ABI, the software is able to run newer |pythonthree| releases, without rebuilding the software. 16 | 17 | Unlike previous revisions of software, |pythontwoseven|, is removed from the build. 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_SUBDIRECTORY(engine) 2 | ADD_SUBDIRECTORY(pycomp) 3 | ADD_SUBDIRECTORY(tclcomp) 4 | 5 | -------------------------------------------------------------------------------- /src/engine/Add.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef ADD_HH 8 | #define ADD_HH 9 | #include "EquationObject.hh" 10 | namespace Eqo { 11 | class Add : public EquationObject { 12 | public: 13 | Add(EqObjPtr, EqObjPtr); 14 | Add(std::vector); 15 | 16 | EqObjPtr Derivative(EqObjPtr); 17 | EqObjPtr Simplify(); 18 | 19 | EqObjPtr CombineProduct(std::vector); 20 | EqObjPtr CombineAdd(std::vector); 21 | 22 | bool isZero(); 23 | bool isOne(); 24 | 25 | EqObjPtr getScale(); 26 | EqObjPtr getUnscaledValue(); 27 | 28 | double getSign(); 29 | EqObjPtr getUnsignedValue(); 30 | 31 | EqObjPtr clone(); 32 | EqObjPtr subst(const std::string &, EqObjPtr); 33 | 34 | EqObjPtr expand(); 35 | 36 | bool hasReciprocal() {return false;} 37 | EqObjPtr getReciprocal(); 38 | std::set getReferencedType(Eqo::EqObjType rt) 39 | { 40 | return UniteReferencedType(rt, values); 41 | } 42 | 43 | friend class Product; // expansion of (a + ...)*(b + ...) 44 | 45 | std::vector getArgs() { 46 | return createArgs(values); 47 | } 48 | 49 | std::string getName() const 50 | { 51 | return "+"; 52 | } 53 | private: 54 | std::string createStringValue() const; 55 | 56 | Add(const Add &); 57 | Add operator=(const Add &); 58 | 59 | std::vector values; 60 | }; 61 | } 62 | #endif 63 | -------------------------------------------------------------------------------- /src/engine/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | INCLUDE_DIRECTORIES ( 2 | ) 3 | 4 | SET (MC_SRCS 5 | ${CMAKE_CURRENT_BINARY_DIR}/mcParser.cc 6 | ${CMAKE_CURRENT_BINARY_DIR}/mcScanner.cc 7 | mcModelCompiler.cc 8 | mcTest.cc 9 | EquationFunc.cc 10 | parseexpr.cc 11 | Context.cc 12 | SubExpr.cc 13 | ProcessModelOrder.cc 14 | mcModel.cc 15 | ) 16 | 17 | SET (CXX_SRCS 18 | EngineAPI.cc 19 | EquationObject.cc 20 | UserFunc.cc 21 | LogicalFunc.cc 22 | Add.cc 23 | Constant.cc 24 | Exponent.cc 25 | IfElse.cc 26 | Log.cc 27 | Pow.cc 28 | Product.cc 29 | Variable.cc 30 | Functions.cc 31 | Utility.cc 32 | ProcessOrderedTable.cc 33 | ) 34 | 35 | INCLUDE_DIRECTORIES ( 36 | ${CMAKE_CURRENT_SOURCE_DIR} 37 | ) 38 | 39 | ADD_LIBRARY(symdiff_objects OBJECT ${CXX_SRCS} ${MC_SRCS}) 40 | set_property(TARGET symdiff_objects PROPERTY POSITION_INDEPENDENT_CODE ON) 41 | 42 | ADD_LIBRARY(symdiff_objects_private OBJECT ${CXX_SRCS} ${MC_SRCS}) 43 | set_target_properties(symdiff_objects_private PROPERTIES POSITION_INDEPENDENT_CODE ON COMPILE_DEFINITIONS SYMDIFF_NO_EXTERN_SYMBOLS) 44 | 45 | #ADD_LIBRARY(symdiff_static STATIC ${CXX_SRCS} ${MC_SRCS}) 46 | ADD_LIBRARY(symdiff_dynamic STATIC $) 47 | IF (NOT STATICONLY) 48 | ADD_LIBRARY(symdiff SHARED $) 49 | ENDIF () 50 | 51 | 52 | 53 | IF (WIN32) 54 | SET_SOURCE_FILES_PROPERTIES(mcScanner.cc mcParser.cc PROPERTIES GENERATED TRUE) 55 | ELSE (WIN32) 56 | SET_SOURCE_FILES_PROPERTIES(mcScanner.cc mcParser.cc PROPERTIES GENERATED TRUE COMPILE_FLAGS "-Wno-unused-function -Wno-sign-compare") 57 | ENDIF (WIN32) 58 | 59 | ADD_CUSTOM_COMMAND( 60 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mcScanner.cc 61 | COMMAND ${FLEX} 62 | ARGS -Pmc -omcScanner.cc ${CMAKE_CURRENT_SOURCE_DIR}/mcScanner.l 63 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/mcParser.hh ${CMAKE_CURRENT_SOURCE_DIR}/mcScanner.l 64 | mcTest.hh EquationObject.hh UserFunc.hh 65 | ) 66 | 67 | ADD_CUSTOM_COMMAND( 68 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mcParser.cc ${CMAKE_CURRENT_BINARY_DIR}/mcParser.hh 69 | COMMAND ${BISON} 70 | ARGS -pmc --debug -v -d -o mcParser.cc ${CMAKE_CURRENT_SOURCE_DIR}/mcParser.y 71 | # these must be read from parser.y 72 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/mcParser.y EquationObject.hh UserFunc.hh mcTest.hh mcModelCompiler.hh mcModel.hh 73 | ) 74 | 75 | IF (NOT STATICONLY) 76 | ADD_CUSTOM_COMMAND(TARGET symdiff 77 | POST_BUILD 78 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_LIBRARY_DIR} 79 | COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_LIBRARY_DIR}/. 80 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_INCLUDE_DIR} 81 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/SymdiffImport.hh ${PROJECT_INCLUDE_DIR}/. 82 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/EngineAPI.hh ${PROJECT_INCLUDE_DIR}/. 83 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/parseexpr.hh ${PROJECT_INCLUDE_DIR}/. 84 | ) 85 | ENDIF () 86 | 87 | #ADD_CUSTOM_COMMAND(TARGET symdiff_static 88 | # POST_BUILD 89 | # COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_LIBRARY_DIR} 90 | # COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_LIBRARY_DIR}/. 91 | #) 92 | 93 | ADD_CUSTOM_COMMAND(TARGET symdiff_dynamic 94 | POST_BUILD 95 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_LIBRARY_DIR} 96 | COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_LIBRARY_DIR}/. 97 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_INCLUDE_DIR} 98 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/SymdiffImport.hh ${PROJECT_INCLUDE_DIR}/. 99 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/EngineAPI.hh ${PROJECT_INCLUDE_DIR}/. 100 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/parseexpr.hh ${PROJECT_INCLUDE_DIR}/. 101 | ) 102 | 103 | IF (NOT STATICONLY) 104 | IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") 105 | SET_TARGET_PROPERTIES(symdiff PROPERTIES INSTALL_RPATH "\$ORIGIN/") 106 | ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") 107 | IF (APPLE) 108 | #SET_TARGET_PROPERTIES(symdiff PROPERTIES INSTALL_RPATH "@loader_path/") 109 | SET_TARGET_PROPERTIES(symdiff PROPERTIES LINK_FLAGS " -flat_namespace") 110 | ENDIF (APPLE) 111 | ENDIF () 112 | 113 | -------------------------------------------------------------------------------- /src/engine/Constant.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | #include "Constant.hh" 7 | #include "Functions.hh" 8 | #include 9 | #include 10 | #include 11 | namespace Eqo { 12 | 13 | EqObjPtr Constant::getUnscaledValue() 14 | { 15 | return con(1); 16 | } 17 | 18 | double Constant::getSign() 19 | { 20 | const double sign = (dvalue < 0.0) ? -1.0 : 1.0; 21 | return sign; 22 | } 23 | 24 | EqObjPtr Constant::getUnsignedValue() 25 | { 26 | const double val = (dvalue < 0.0) ? -dvalue : dvalue; 27 | return con(val); 28 | } 29 | 30 | Constant::Constant(double x) : EquationObject(CONST_OBJ), dvalue(x) 31 | { 32 | } 33 | 34 | std::string Constant::createStringValue() const 35 | { 36 | std::ostringstream os; 37 | if (dvalue != floor(dvalue)) 38 | { 39 | os << std::scientific << std::setprecision(15); 40 | } 41 | if (dvalue < 0.0) 42 | { 43 | os << "(" << dvalue << ")"; 44 | } 45 | else 46 | { 47 | os << dvalue; 48 | } 49 | return std::string(os.str()); 50 | } 51 | 52 | EqObjPtr Constant::Derivative(EqObjPtr foo) 53 | { 54 | EqObjPtr dog = con(0); 55 | return dog; 56 | } 57 | 58 | EqObjPtr Constant::Simplify() 59 | { 60 | return this->clone(); 61 | } 62 | 63 | EqObjPtr Constant::CombineProduct(std::vector y) 64 | { 65 | double x=dvalue; 66 | size_t len=y.size(); 67 | for (size_t i=0; i < len; ++i) 68 | { 69 | Constant *Y = static_cast(y[i].get()); 70 | x *= Y->dvalue; 71 | } 72 | return EqObjPtr(new Constant(x)); 73 | } 74 | 75 | EqObjPtr Constant::CombineAdd(std::vector y) 76 | { 77 | EqObjPtr ret; 78 | double dsum(0.0); 79 | dsum += this->getDoubleValue(); 80 | 81 | 82 | size_t len=y.size(); 83 | for (size_t i=0; i < len; ++i) 84 | { 85 | Constant *Y = static_cast(y[i].get()); 86 | 87 | dsum += Y->getDoubleValue(); 88 | } 89 | return con(dsum); 90 | } 91 | 92 | bool Constant::isZero() 93 | { 94 | return (this->getDoubleValue()==0.0); 95 | } 96 | 97 | bool Constant::isOne() 98 | { 99 | return (this->getDoubleValue()==1.0); 100 | } 101 | 102 | EqObjPtr Constant::clone() 103 | { 104 | return con(dvalue); 105 | } 106 | 107 | EqObjPtr Constant::subst(const std::string &str, EqObjPtr eqo) 108 | { 109 | if (str == this->stringValue()) 110 | return eqo; 111 | else 112 | return shared_from_this(); 113 | } 114 | 115 | EqObjPtr Constant::expand() 116 | { 117 | return shared_from_this(); 118 | } 119 | 120 | EqObjPtr Constant::getScale() 121 | { 122 | return shared_from_this(); 123 | } 124 | 125 | EqObjPtr Constant::getReciprocal() 126 | { 127 | return con(1.0/dvalue); 128 | } 129 | } 130 | 131 | -------------------------------------------------------------------------------- /src/engine/Constant.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef CONSTANT_HH 8 | #define CONSTANT_HH 9 | #include "EquationObject.hh" 10 | namespace Eqo { 11 | class Constant : public EquationObject { 12 | public: 13 | Constant(double); 14 | ~Constant() {}; 15 | 16 | 17 | EqObjPtr Derivative(EqObjPtr); 18 | EqObjPtr Simplify(); 19 | 20 | EqObjPtr CombineProduct(std::vector); 21 | EqObjPtr CombineAdd(std::vector); 22 | 23 | bool isZero(); 24 | bool isOne(); 25 | 26 | EqObjPtr getScale(); 27 | EqObjPtr getUnscaledValue(); 28 | 29 | double getSign(); 30 | EqObjPtr getUnsignedValue(); 31 | 32 | EqObjPtr clone(); 33 | EqObjPtr subst(const std::string &, EqObjPtr); 34 | 35 | EqObjPtr expand(); 36 | 37 | bool hasReciprocal() 38 | { 39 | return !(this->isZero()); 40 | } 41 | 42 | EqObjPtr getReciprocal(); 43 | 44 | double getDoubleValue() 45 | { 46 | return dvalue; 47 | } 48 | 49 | std::set getReferencedType(Eqo::EqObjType rt) { 50 | return CreateSetIfThisType(rt); 51 | } 52 | 53 | friend class Pow; 54 | friend class Product; 55 | 56 | std::vector getArgs() { 57 | return std::vector(); 58 | } 59 | 60 | std::string getName() const 61 | { 62 | return EquationObject::stringValue(); 63 | } 64 | private: 65 | std::string createStringValue() const; 66 | 67 | Constant(const Constant &); 68 | Constant operator=(const Constant &); 69 | 70 | const double dvalue; 71 | }; 72 | } 73 | #endif 74 | 75 | -------------------------------------------------------------------------------- /src/engine/Context.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | #include "Context.hh" 7 | 8 | Context *Context::instance_; 9 | 10 | Context::Context() 11 | { 12 | } 13 | 14 | Context::~Context() 15 | { 16 | } 17 | 18 | ModelMap_t &Context::GetModelMap() 19 | { 20 | return context_data_.model_list_; 21 | } 22 | 23 | Context &Context::GetInstance() 24 | { 25 | if (!instance_) 26 | { 27 | instance_ = new Context(); 28 | } 29 | return *instance_; 30 | } 31 | 32 | void Context::DestroyInstance() 33 | { 34 | delete instance_; 35 | instance_ = nullptr; 36 | } 37 | 38 | 39 | void Context::SetModelListCallBack(inModelListCallback_ptr foo) 40 | { 41 | context_data_.callback_func_ptr_ = foo; 42 | } 43 | 44 | /* 45 | Returns true if the model by the given name is in the ModelList 46 | */ 47 | bool Context::IsInModelList(const std::string &str) 48 | { 49 | if (context_data_.callback_func_ptr_) 50 | { 51 | return context_data_.callback_func_ptr_(str); 52 | } 53 | else 54 | { 55 | ModelMap_t::iterator it, end=context_data_.model_list_.end(); 56 | for (it=context_data_.model_list_.begin(); it != end; ++it) 57 | { 58 | if ((*it).first == str) 59 | return true; 60 | } 61 | } 62 | return false; 63 | } 64 | 65 | /* 66 | If it is in the model list, this will return a pointer to the model with the given 67 | name. 68 | */ 69 | Eqo::EqObjPtr Context::FindInModelList(const std::string &str) 70 | { 71 | Eqo::EqObjPtr ret; 72 | ModelMap_t::iterator it = context_data_.model_list_.find(str); 73 | if (it != context_data_.model_list_.end()) 74 | { 75 | ret = it->second; 76 | } 77 | 78 | return ret; 79 | } 80 | 81 | void Context::ClearAllModels() 82 | { 83 | context_data_.model_list_.clear(); 84 | } 85 | 86 | void Context::ClearModel(const std::string &str) 87 | { 88 | ModelMap_t::iterator it = context_data_.model_list_.find(str); 89 | if (it != context_data_.model_list_.end()) 90 | { 91 | context_data_.model_list_.erase(it); 92 | } 93 | } 94 | 95 | void Context::DeclareModel(const std::string &s) 96 | { 97 | if (!FindInModelList(s)) 98 | { 99 | //#warning "decide if we should zero out an existing model" 100 | context_data_.model_list_.insert(std::make_pair(s, Eqo::EqObjPtr())); 101 | } 102 | } 103 | 104 | void Context::DefineModel(const std::string &s, Eqo::EqObjPtr e) 105 | { 106 | GetModelMap()[s] = e; 107 | } 108 | 109 | Eqo::EqObjPtr Context::EvaluateModelDerivative(Eqo::EqObjPtr x, Eqo::EqObjPtr y) 110 | { 111 | return context_data_.model_derivative_rule_ptr_(x, y); 112 | } 113 | 114 | void Context::SetDerivativeRule(modelDerivativeRule_ptr x) 115 | { 116 | context_data_.model_derivative_rule_ptr_ = x; 117 | } 118 | 119 | 120 | -------------------------------------------------------------------------------- /src/engine/Context.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef MC_CONTEXT_HH 8 | #define MC_CONTEXT_HH 9 | #include 10 | #include 11 | #include 12 | #include "SymdiffImport.hh" 13 | 14 | namespace Eqo 15 | { 16 | class EquationObject; 17 | typedef std::shared_ptr EqObjPtr; 18 | } 19 | 20 | typedef std::map ModelMap_t; 21 | typedef bool (*inModelListCallback_ptr)(const std::string &); 22 | typedef Eqo::EqObjPtr (*modelDerivativeRule_ptr)(Eqo::EqObjPtr, Eqo::EqObjPtr); 23 | 24 | namespace Eqo 25 | { 26 | extern Eqo::EqObjPtr DLL_PROTECTED default_derivative_rule(Eqo::EqObjPtr, Eqo::EqObjPtr); 27 | } 28 | 29 | //// Be able to store rules in the future. 30 | class ContextData { 31 | public: 32 | ContextData() : callback_func_ptr_(nullptr), model_derivative_rule_ptr_(Eqo::default_derivative_rule) 33 | { 34 | } 35 | 36 | ModelMap_t model_list_; 37 | 38 | inModelListCallback_ptr callback_func_ptr_; 39 | modelDerivativeRule_ptr model_derivative_rule_ptr_; 40 | private: 41 | // ContextData(); 42 | // ~ContextData(); 43 | ContextData(const ContextData &); 44 | const ContextData &operator=(const ContextData &); 45 | }; 46 | 47 | class DLL_PROTECTED Context { 48 | public: 49 | static Context &GetInstance(); 50 | static void DestroyInstance(); 51 | 52 | Eqo::EqObjPtr EvaluateModelDerivative(Eqo::EqObjPtr, Eqo::EqObjPtr); 53 | Eqo::EqObjPtr FindInModelList(const std::string &); 54 | bool IsInModelList(const std::string &); 55 | void SetModelListCallBack(inModelListCallback_ptr); 56 | void SetDerivativeRule(modelDerivativeRule_ptr); 57 | ModelMap_t &GetModelMap(); 58 | 59 | void ClearAllModels(); 60 | void ClearModel(const std::string &); 61 | void DeclareModel(const std::string &); 62 | void DefineModel(const std::string &, Eqo::EqObjPtr); 63 | 64 | private: 65 | Context(); 66 | ~Context(); 67 | Context(const Context &); 68 | const Context &operator=(const Context &); 69 | 70 | ContextData context_data_; 71 | 72 | static Context *instance_; 73 | }; 74 | #endif 75 | 76 | -------------------------------------------------------------------------------- /src/engine/EngineAPI.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | #include "EngineAPI.hh" 7 | #include "LogicalFunc.hh" 8 | #include "IfElse.hh" 9 | #include "Functions.hh" 10 | #include "Context.hh" 11 | #include "mcModel.hh" 12 | #include "UserFunc.hh" 13 | 14 | namespace EngineAPI { 15 | Eqo::EqObjPtr createUnaryLogical(const std::string &unaryOp, Eqo::EqObjPtr arg) 16 | { 17 | return Eqo::EqObjPtr(new Eqo::UnaryLogical(unaryOp, arg)); 18 | } 19 | 20 | Eqo::EqObjPtr createBinaryLogical(const std::string &unaryOp, Eqo::EqObjPtr arg1, Eqo::EqObjPtr arg2) 21 | { 22 | return Eqo::EqObjPtr(new Eqo::BinaryLogical(unaryOp, arg1, arg2)); 23 | } 24 | 25 | Eqo::EqObjPtr createIfObj(Eqo::EqObjPtr test, Eqo::EqObjPtr result) 26 | { 27 | return Eqo::EqObjPtr(new Eqo::IfObj(test, result)); 28 | } 29 | 30 | Eqo::EqObjPtr createIfElseObj(Eqo::EqObjPtr test, Eqo::EqObjPtr left, Eqo::EqObjPtr right) 31 | { 32 | return Eqo::EqObjPtr(new Eqo::IfElseObj(test, left, right)); 33 | } 34 | 35 | /// Non member functions for intuitive math operations 36 | Eqo::EqObjPtr operator* (Eqo::EqObjPtr x, Eqo::EqObjPtr y) 37 | { 38 | return Eqo::operator*(x, y); 39 | } 40 | 41 | Eqo::EqObjPtr pow (Eqo::EqObjPtr x, Eqo::EqObjPtr y); 42 | 43 | Eqo::EqObjPtr operator/ (Eqo::EqObjPtr x, Eqo::EqObjPtr y) 44 | { 45 | return Eqo::operator/(x, y); 46 | } 47 | 48 | Eqo::EqObjPtr operator+ (Eqo::EqObjPtr x, Eqo::EqObjPtr y) 49 | { 50 | return Eqo::operator+(x, y); 51 | } 52 | 53 | Eqo::EqObjPtr operator- (Eqo::EqObjPtr x, Eqo::EqObjPtr y) 54 | { 55 | return Eqo::operator-(x, y); 56 | } 57 | 58 | Eqo::EqObjPtr exp (Eqo::EqObjPtr x) 59 | { 60 | return Eqo::exp(x); 61 | } 62 | 63 | Eqo::EqObjPtr pow (Eqo::EqObjPtr x, Eqo::EqObjPtr y) 64 | { 65 | return Eqo::pow(x, y); 66 | } 67 | 68 | Eqo::EqObjPtr log (Eqo::EqObjPtr x) 69 | { 70 | return Eqo::log(x); 71 | } 72 | 73 | Eqo::EqObjPtr diff(Eqo::EqObjPtr x, Eqo::EqObjPtr y) 74 | { 75 | return Eqo::diff(x, y); 76 | } 77 | 78 | Eqo::EqObjPtr con(double x) 79 | { 80 | return Eqo::con(x); 81 | } 82 | 83 | Eqo::EqObjPtr mod(const char *x) 84 | { 85 | return Eqo::mod(x); 86 | } 87 | 88 | Eqo::EqObjPtr mod(const std::string &x) 89 | { 90 | return Eqo::mod(x); 91 | } 92 | 93 | Eqo::EqObjPtr var(const char *x) 94 | { 95 | return Eqo::var(x); 96 | } 97 | 98 | Eqo::EqObjPtr var(const std::string &x) 99 | { 100 | return Eqo::var(x); 101 | } 102 | 103 | Eqo::EqObjPtr sqrt(Eqo::EqObjPtr x) 104 | { 105 | return Eqo::sqrt(x); 106 | } 107 | 108 | Eqo::EqObjPtr reciprocal_sqrt(Eqo::EqObjPtr x) 109 | { 110 | return Eqo::reciprocal_sqrt(x); 111 | } 112 | 113 | /// how we print things 114 | std::ostream & operator<< (std::ostream &os, Eqo::EqObjPtr foo) 115 | { 116 | return Eqo::operator<<(os, foo); 117 | } 118 | 119 | /// keeps simplifying expression until string value doesn't change 120 | Eqo::EqObjPtr Simplify(Eqo::EqObjPtr x) 121 | { 122 | return Eqo::Simplify(x); 123 | } 124 | 125 | Eqo::EqObjPtr getConstantFactor(Eqo::EqObjPtr x) 126 | { 127 | return Eqo::getConstantFactor(x); 128 | } 129 | 130 | Eqo::EqObjPtr Expand(Eqo::EqObjPtr x) 131 | { 132 | return Eqo::Expand(x); 133 | } 134 | 135 | Eqo::EqObjPtr getUnscaledValue(Eqo::EqObjPtr x) 136 | { 137 | return Eqo::getUnscaledValue(x); 138 | } 139 | 140 | Eqo::EqObjPtr getUnsignedValue(Eqo::EqObjPtr x) 141 | { 142 | return Eqo::getUnsignedValue(x); 143 | } 144 | 145 | Eqo::EqObjPtr getSign(Eqo::EqObjPtr x) 146 | { 147 | return Eqo::getSign(x); 148 | } 149 | 150 | /// Sorts in order of constants, variables, then other objects 151 | void SortEqVector(std::vector &v1) 152 | { 153 | Eqo::SortEqVector(v1); 154 | } 155 | 156 | Eqo::EqObjPtr subst(Eqo::EqObjPtr a, Eqo::EqObjPtr b, Eqo::EqObjPtr c) 157 | { 158 | return Eqo::subst(a, b, c); 159 | } 160 | 161 | Eqo::EqObjPtr getNegation(Eqo::EqObjPtr x) 162 | { 163 | return Eqo::getNegation(x); 164 | } 165 | 166 | bool isBinaryFunction(const std::string &str) 167 | { 168 | return Eqo::getBinaryFuncPtr(str) != nullptr; 169 | } 170 | 171 | bool isUnaryFunction(const std::string &str) 172 | { 173 | return Eqo::getUnaryFuncPtr(str) != nullptr; 174 | } 175 | EqBinaryFuncPtr getBinaryFuncPtr(const std::string &str) 176 | { 177 | return Eqo::getBinaryFuncPtr(str); 178 | } 179 | 180 | EqUnaryFuncPtr DLL_PROTECTED getUnaryFuncPtr(const std::string &str) 181 | { 182 | return Eqo::getUnaryFuncPtr(str); 183 | } 184 | 185 | std::string DLL_PROTECTED getName(Eqo::EqObjPtr x) 186 | { 187 | return x->getName(); 188 | } 189 | 190 | std::string DLL_PROTECTED getType(Eqo::EqObjPtr x) 191 | { 192 | std::string ret; 193 | ret = Eqo::EqObjNames[x->getType()]; 194 | return ret; 195 | } 196 | 197 | EqObjType DLL_PROTECTED getEnumeratedType(Eqo::EqObjPtr x) 198 | { 199 | return EqObjType(x->getType()); 200 | } 201 | 202 | std::string DLL_PROTECTED getStringValue(Eqo::EqObjPtr x) 203 | { 204 | return x->stringValue(); 205 | } 206 | 207 | double DLL_PROTECTED getDoubleValue(Eqo::EqObjPtr x) 208 | { 209 | assert(x->getType() == Eqo::CONST_OBJ); 210 | return static_cast(x.get())->getDoubleValue(); 211 | } 212 | 213 | std::set DLL_PROTECTED getReferencedType(Eqo::EqObjPtr x, EqObjType t) 214 | { 215 | return x->getReferencedType(Eqo::EqObjType(t)); 216 | } 217 | 218 | std::vector DLL_PROTECTED getArgs(Eqo::EqObjPtr x) 219 | { 220 | return x->getArgs(); 221 | } 222 | 223 | void DLL_PROTECTED SetModelListCallBack(inModelListCallback_ptr x) 224 | { 225 | Context &context = Context::GetInstance(); 226 | context.SetModelListCallBack(x); 227 | } 228 | 229 | void DLL_PROTECTED SetDerivativeRule(modelDerivativeRule_ptr x) 230 | { 231 | Context &context = Context::GetInstance(); 232 | context.SetDerivativeRule(x); 233 | } 234 | 235 | void DLL_PROTECTED ResetAllData() 236 | { 237 | Eqo::variableMap.clear(); 238 | Eqo::UserFuncMap.clear(); 239 | Context::DestroyInstance(); 240 | } 241 | } 242 | 243 | -------------------------------------------------------------------------------- /src/engine/EngineAPI.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef ENGINEAPI_HH 8 | #define ENGINEAPI_HH 9 | #include 10 | #include "SymdiffImport.hh" 11 | #include 12 | #include 13 | #include 14 | namespace Eqo { 15 | class EquationObject; 16 | typedef std::shared_ptr EqObjPtr; 17 | } 18 | 19 | namespace EngineAPI { 20 | enum EqObjType {CONST_OBJ=0, VARIABLE_OBJ, ADD_OBJ, PRODUCT_OBJ, EXPONENT_OBJ, POW_OBJ, LOG_OBJ, MODEL_OBJ, USERFUNC_OBJ, BLOGICAL_OBJ, ULOGICAL_OBJ, IF_OBJ, IFELSE_OBJ, NUM_TYPES}; 21 | 22 | typedef Eqo::EqObjPtr (*EqUnaryFuncPtr) (Eqo::EqObjPtr); 23 | typedef Eqo::EqObjPtr (*EqBinaryFuncPtr) (Eqo::EqObjPtr, Eqo::EqObjPtr); 24 | 25 | Eqo::EqObjPtr DLL_PROTECTED createUnaryLogical(const std::string &/*unaryOp*/, Eqo::EqObjPtr /*arg*/); 26 | Eqo::EqObjPtr DLL_PROTECTED createBinaryLogical(const std::string &/*unaryOp*/, Eqo::EqObjPtr /*arg*/, Eqo::EqObjPtr /*arg*/); 27 | Eqo::EqObjPtr DLL_PROTECTED createIfObj(Eqo::EqObjPtr /*test*/, Eqo::EqObjPtr /*result*/); 28 | Eqo::EqObjPtr DLL_PROTECTED createIfElseObj(Eqo::EqObjPtr /*test*/, Eqo::EqObjPtr /*left*/, Eqo::EqObjPtr /*right*/); 29 | /// Non member functions for intuitive math operations 30 | Eqo::EqObjPtr DLL_PROTECTED operator* (Eqo::EqObjPtr x, Eqo::EqObjPtr y); 31 | Eqo::EqObjPtr DLL_PROTECTED pow (Eqo::EqObjPtr x, Eqo::EqObjPtr y); 32 | Eqo::EqObjPtr DLL_PROTECTED operator/ (Eqo::EqObjPtr x, Eqo::EqObjPtr y); 33 | Eqo::EqObjPtr DLL_PROTECTED operator+ (Eqo::EqObjPtr x, Eqo::EqObjPtr y); 34 | Eqo::EqObjPtr DLL_PROTECTED operator- (Eqo::EqObjPtr x, Eqo::EqObjPtr y); 35 | 36 | Eqo::EqObjPtr DLL_PROTECTED exp (Eqo::EqObjPtr x); 37 | 38 | Eqo::EqObjPtr DLL_PROTECTED pow (Eqo::EqObjPtr x, Eqo::EqObjPtr y); 39 | 40 | Eqo::EqObjPtr DLL_PROTECTED log (Eqo::EqObjPtr x); 41 | 42 | Eqo::EqObjPtr DLL_PROTECTED diff(Eqo::EqObjPtr x, Eqo::EqObjPtr y); 43 | 44 | Eqo::EqObjPtr DLL_PROTECTED con(double x); 45 | 46 | Eqo::EqObjPtr DLL_PROTECTED mod(const char *x); 47 | 48 | Eqo::EqObjPtr DLL_PROTECTED mod(const std::string &x); 49 | 50 | Eqo::EqObjPtr DLL_PROTECTED var(const char *x); 51 | 52 | Eqo::EqObjPtr DLL_PROTECTED var(const std::string &x); 53 | 54 | Eqo::EqObjPtr DLL_PROTECTED sqrt(Eqo::EqObjPtr x); 55 | 56 | Eqo::EqObjPtr DLL_PROTECTED reciprocal_sqrt(Eqo::EqObjPtr x); 57 | 58 | /// how we print things 59 | std::ostream & operator<< (std::ostream &os, Eqo::EqObjPtr foo); 60 | 61 | /// keeps simplifying expression until string value doesn't change 62 | Eqo::EqObjPtr DLL_PROTECTED Simplify(Eqo::EqObjPtr x); 63 | 64 | Eqo::EqObjPtr DLL_PROTECTED getConstantFactor(Eqo::EqObjPtr x); 65 | 66 | Eqo::EqObjPtr DLL_PROTECTED Expand(Eqo::EqObjPtr x); 67 | 68 | Eqo::EqObjPtr DLL_PROTECTED getUnscaledValue(Eqo::EqObjPtr x); 69 | 70 | Eqo::EqObjPtr DLL_PROTECTED getUnsignedValue(Eqo::EqObjPtr x); 71 | 72 | Eqo::EqObjPtr DLL_PROTECTED getSign(Eqo::EqObjPtr x); 73 | 74 | /// Sorts in order of constants, variables, then other objects 75 | void SortEqVector(std::vector &v1); 76 | 77 | Eqo::EqObjPtr DLL_PROTECTED subst(Eqo::EqObjPtr a, Eqo::EqObjPtr b, Eqo::EqObjPtr c); 78 | 79 | Eqo::EqObjPtr DLL_PROTECTED getNegation(Eqo::EqObjPtr x); 80 | 81 | bool DLL_PROTECTED isBinaryFunction(const std::string &str); 82 | bool DLL_PROTECTED isUnaryFunction(const std::string &str); 83 | 84 | EqBinaryFuncPtr DLL_PROTECTED getBinaryFuncPtr(const std::string &); 85 | EqUnaryFuncPtr DLL_PROTECTED getUnaryFuncPtr(const std::string &); 86 | 87 | std::string DLL_PROTECTED getName(Eqo::EqObjPtr x); 88 | std::string DLL_PROTECTED getType(Eqo::EqObjPtr x); 89 | std::set DLL_PROTECTED getReferencedType(Eqo::EqObjPtr x, EqObjType t); 90 | double DLL_PROTECTED getDoubleValue(Eqo::EqObjPtr x); 91 | std::string DLL_PROTECTED getStringValue(Eqo::EqObjPtr x); 92 | EqObjType DLL_PROTECTED getEnumeratedType(Eqo::EqObjPtr x); 93 | std::vector DLL_PROTECTED getArgs(Eqo::EqObjPtr x); 94 | 95 | typedef bool (*inModelListCallback_ptr)(const std::string &); 96 | void DLL_PROTECTED SetModelListCallBack(inModelListCallback_ptr); 97 | 98 | typedef Eqo::EqObjPtr (*modelDerivativeRule_ptr)(Eqo::EqObjPtr, Eqo::EqObjPtr); 99 | void DLL_PROTECTED SetDerivativeRule(modelDerivativeRule_ptr); 100 | 101 | void DLL_PROTECTED ResetAllData(); 102 | } 103 | #endif 104 | -------------------------------------------------------------------------------- /src/engine/EquationFunc.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | #include "EquationFunc.hh" 7 | #include "EquationObject.hh" 8 | #include "mcModelCompiler.hh" 9 | #include "parseexpr.hh" 10 | #include "Context.hh" 11 | 12 | #include 13 | namespace sdHelp { 14 | 15 | 16 | ret_pair SymdiffEval(const std::string &expr) 17 | { 18 | bool ret = false; 19 | ret_data data; 20 | 21 | EvalExpr::error_t terrors; 22 | 23 | Eqo::EqObjPtr testeq = EvalExpr::evaluateExpression(expr, terrors); 24 | 25 | if (!terrors.empty()) 26 | { 27 | std::ostringstream os; 28 | os << "While evaluating expression \"" << expr << "\"\n"; 29 | for (EvalExpr::error_t::iterator it = terrors.begin(); it != terrors.end(); ++it) 30 | { 31 | os << *it << "\n"; 32 | } 33 | ret = false; 34 | data.string_ = os.str(); 35 | } 36 | else 37 | { 38 | data.string_ = testeq->stringValue(); 39 | data.eqptr_ = testeq; 40 | ret = true; 41 | } 42 | 43 | return std::make_pair(ret, data); 44 | } 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/engine/EquationFunc.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef EQUATION_FUNC_HH 8 | #define EQUATION_FUNC_HH 9 | #include 10 | #include "SymdiffImport.hh" 11 | #include 12 | #include 13 | 14 | namespace Eqo { 15 | class EquationObject; 16 | typedef std::shared_ptr EqObjPtr; 17 | } 18 | 19 | namespace sdHelp { 20 | struct ret_data { 21 | std::string string_; 22 | Eqo::EqObjPtr eqptr_; 23 | }; 24 | 25 | typedef std::pair ret_pair; 26 | DLL_PROTECTED ret_pair SymdiffEval(const std::string &); 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/engine/EquationObject.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "EquationObject.hh" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | namespace Eqo { 20 | typedef std::shared_ptr EqObjPtr; 21 | 22 | std::map variableMap; 23 | 24 | 25 | const std::string &EquationObject::stringValue() const 26 | { 27 | if (stringValue_.empty()) 28 | { 29 | stringValue_ = this->createStringValue(); 30 | } 31 | 32 | return stringValue_; 33 | } 34 | 35 | 36 | 37 | 38 | std::set UniteReferencedType(EqObjType rt, const EqObjPtr &op1, const EqObjPtr &op2) 39 | { 40 | std::set out; 41 | 42 | if (op1->getType() == rt) 43 | { 44 | out.insert(op1->stringValue()); 45 | } 46 | else 47 | { 48 | std::set rm= op1->getReferencedType(rt); 49 | std::set::iterator it=rm.begin(); 50 | std::set::iterator end=rm.end(); 51 | for ( ; it != end; ++it) 52 | out.insert(*it); 53 | } 54 | 55 | if (op2->getType() == rt) 56 | { 57 | out.insert(op2->stringValue()); 58 | } 59 | else 60 | { 61 | std::set rm= op2->getReferencedType(rt); 62 | std::set::iterator it=rm.begin(); 63 | std::set::iterator end=rm.end(); 64 | for ( ; it != end; ++it) 65 | out.insert(*it); 66 | } 67 | return out; 68 | } 69 | 70 | std::set UniteReferencedType(EqObjType rt, const std::vector &x) 71 | { 72 | std::set out; 73 | for (size_t i=0; i < x.size(); ++i) 74 | { 75 | if (x[i]->getType() == rt) 76 | { 77 | out.insert(x[i]->stringValue()); 78 | } 79 | else 80 | { 81 | std::set rm= x[i]->getReferencedType(rt); 82 | std::set::iterator it=rm.begin(); 83 | std::set::iterator end=rm.end(); 84 | for ( ; it != end; ++it) 85 | { 86 | out.insert(*it); 87 | } 88 | } 89 | } 90 | return out; 91 | } 92 | 93 | } // always close the namespace 94 | 95 | -------------------------------------------------------------------------------- /src/engine/Exponent.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "Exponent.hh" 8 | #include "Functions.hh" 9 | #include 10 | 11 | namespace Eqo { 12 | Exponent::Exponent(EqObjPtr var) : EquationObject(EXPONENT_OBJ), value(var) 13 | { 14 | } 15 | 16 | std::string Exponent::createStringValue() const 17 | { 18 | std::ostringstream os; 19 | os << "exp(" << value << ")"; 20 | return std::string(os.str()); 21 | } 22 | 23 | EqObjPtr Exponent::Derivative(EqObjPtr foo) 24 | { 25 | if (value->getType() == CONST_OBJ) 26 | { 27 | return con(0.0); 28 | } 29 | else 30 | { 31 | return value->Derivative(foo)*exp(value); 32 | } 33 | } 34 | 35 | EqObjPtr Exponent::Simplify() 36 | { 37 | if (value->isZero()) 38 | return con(1); 39 | 40 | if (value->getType() == LOG_OBJ) 41 | { 42 | Log *Y = dynamic_cast(value.get()); 43 | return (Y->value); 44 | } 45 | 46 | return exp(value->Simplify()); 47 | } 48 | 49 | /** 50 | * exp(y)*exp(x)=exp(x+y) 51 | */ 52 | EqObjPtr Exponent::CombineProduct(std::vector y) 53 | { 54 | std::vector tmp; 55 | tmp.push_back(value); 56 | const size_t len = y.size(); 57 | for (size_t i=0; i < len; ++i) 58 | { 59 | Exponent *Y = dynamic_cast(y[i].get()); 60 | tmp.push_back(Y->value); 61 | } 62 | return EqObjPtr(new Exponent(EqObjPtr(new Add(tmp)))); 63 | } 64 | 65 | EqObjPtr Exponent::CombineAdd(std::vector y) 66 | { 67 | if (y.empty()) 68 | return shared_from_this(); 69 | 70 | y.push_back(EqObjPtr(new Exponent(value))); 71 | return EqObjPtr(new Add(y)); 72 | } 73 | 74 | bool Exponent::isZero() 75 | { 76 | return false; 77 | } 78 | 79 | bool Exponent::isOne() 80 | { 81 | return false; 82 | } 83 | 84 | EqObjPtr Exponent::getScale() 85 | { 86 | return con(1.0); 87 | } 88 | 89 | EqObjPtr Exponent::getUnscaledValue() 90 | { 91 | return shared_from_this(); 92 | } 93 | 94 | double Exponent::getSign() 95 | { 96 | return 1.0; 97 | } 98 | 99 | EqObjPtr Exponent::getUnsignedValue() 100 | { 101 | return shared_from_this(); 102 | } 103 | 104 | EqObjPtr Exponent::clone() 105 | { 106 | EquationObject *n = new Exponent(value->clone()); 107 | return EqObjPtr(n); 108 | } 109 | 110 | EqObjPtr Exponent::subst(const std::string &str, EqObjPtr eqo) 111 | { 112 | if (str == this->stringValue()) 113 | return eqo; 114 | else 115 | return exp(value->subst(str, eqo)); 116 | } 117 | 118 | EqObjPtr Exponent::expand() 119 | { 120 | return exp(value->expand()); 121 | } 122 | 123 | EqObjPtr Exponent::getReciprocal() 124 | { 125 | assert(false); 126 | return con(0); 127 | } 128 | } 129 | 130 | -------------------------------------------------------------------------------- /src/engine/Exponent.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef EXPONENT_HH 8 | #define EXPONENT_HH 9 | #include "EquationObject.hh" 10 | namespace Eqo { 11 | class Exponent : public EquationObject { 12 | public: 13 | Exponent(EqObjPtr); 14 | 15 | EqObjPtr Derivative(EqObjPtr); 16 | EqObjPtr Simplify(); 17 | 18 | EqObjPtr CombineProduct(std::vector); 19 | EqObjPtr CombineAdd(std::vector); 20 | 21 | bool isZero(); 22 | bool isOne(); 23 | 24 | EqObjPtr getScale(); 25 | EqObjPtr getUnscaledValue(); 26 | 27 | double getSign(); 28 | EqObjPtr getUnsignedValue(); 29 | 30 | EqObjPtr clone(); 31 | EqObjPtr subst(const std::string &, EqObjPtr); 32 | 33 | EqObjPtr expand(); 34 | 35 | bool hasReciprocal() {return false;} 36 | EqObjPtr getReciprocal(); 37 | 38 | std::set getReferencedType(Eqo::EqObjType rt) 39 | { 40 | return value->getReferencedType(rt); 41 | } 42 | 43 | std::vector getArgs() { 44 | return createArgs(value); 45 | } 46 | 47 | std::string getName() const 48 | { 49 | return "exp"; 50 | } 51 | 52 | friend class Log; 53 | private: 54 | std::string createStringValue() const; 55 | 56 | Exponent(const Exponent &); 57 | Exponent operator=(const Exponent &); 58 | 59 | const EqObjPtr value; 60 | }; 61 | 62 | } 63 | #endif 64 | 65 | -------------------------------------------------------------------------------- /src/engine/Functions.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "Functions.hh" 8 | 9 | namespace Eqo 10 | { 11 | UnaryTblEntry UnaryTable[] = { 12 | {"simplify", Simplify, "simplify(obj) -- Simplify as much as possible"}, 13 | {"exp", exp, "exp(obj) -- Exponentiation with respect to e"}, 14 | {"expand", Expand, "expand(obj) -- Perform expansion of products with sums"}, 15 | {"log", log, "log(obj) -- Natural logarithm"}, 16 | {"unscaledval", getUnscaledValue, "unscaledval(obj) -- Get value without constant scaling"}, 17 | {"scale", getConstantFactor,"scale(obj) -- Get constant factor"}, 18 | {"unsignedval", getUnsignedValue, "unsignedval(obj) -- Get unsigned value"}, 19 | {"sign", getSign, "sign(obj) -- Get sign as 1 or -1"}, 20 | {nullptr, nullptr, nullptr} 21 | }; 22 | 23 | BinaryTblEntry BinaryTable[] = { 24 | {"pow", pow, "pow(obj1, obj2) -- Raise obj1 to the power of obj2"}, 25 | {"diff", diff, "diff(obj1, obj2) -- Take derivative of obj1 with respect to obj2"}, 26 | {nullptr, nullptr, nullptr} 27 | }; 28 | 29 | EqUnaryFuncPtr getUnaryFuncPtr(std::string x) { 30 | size_t i=0; 31 | while (UnaryTable[i].name != nullptr) 32 | { 33 | if (x == UnaryTable[i].name) 34 | return UnaryTable[i].func; 35 | ++i; 36 | } 37 | return nullptr; 38 | } 39 | 40 | EqBinaryFuncPtr getBinaryFuncPtr(std::string x) { 41 | size_t i=0; 42 | while (BinaryTable[i].name != nullptr) 43 | { 44 | if (x == BinaryTable[i].name) 45 | return BinaryTable[i].func; 46 | ++i; 47 | } 48 | return nullptr; 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/engine/Functions.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef INLINE_FUNCTIONS_HH 8 | #define INLINE_FUNCTIONS_HH 9 | #include "EquationObject.hh" 10 | #include "Product.hh" 11 | #include "Add.hh" 12 | #include "Exponent.hh" 13 | #include "Log.hh" 14 | #include "Pow.hh" 15 | #include "Constant.hh" 16 | #include "Variable.hh" 17 | namespace Eqo { 18 | /// Non member functions for intuitive math operations 19 | inline EqObjPtr con(double x) 20 | { 21 | return EqObjPtr(new Constant(x)); 22 | } 23 | 24 | inline EqObjPtr operator* (EqObjPtr x, EqObjPtr y) 25 | { 26 | EqObjPtr ret; 27 | if (x->isZero() || y->isZero()) 28 | { 29 | ret = con(0.0); 30 | } 31 | else if (x->isOne()) 32 | { 33 | ret = y; 34 | } 35 | else if (y->isOne()) 36 | { 37 | ret = x; 38 | } 39 | else if (x->getType() == Eqo::PRODUCT_OBJ) 40 | { 41 | std::vector x_args = x->getArgs(); 42 | 43 | if (y->getType() == Eqo::PRODUCT_OBJ) 44 | { 45 | std::vector y_args = y->getArgs(); 46 | for (std::vector::iterator it = y_args.begin(); it != y_args.end(); ++it) 47 | { 48 | x_args.push_back(*it); 49 | } 50 | } 51 | else 52 | { 53 | x_args.push_back(y); 54 | } 55 | 56 | ret = EqObjPtr(new Product(x_args)); 57 | } 58 | else if (y->getType() == Eqo::PRODUCT_OBJ) 59 | { 60 | std::vector y_args = y->getArgs(); 61 | std::vector x_args; 62 | x_args.reserve(y_args.size() + 1); 63 | x_args.push_back(x); 64 | for (std::vector::iterator it = y_args.begin(); it != y_args.end(); ++it) 65 | { 66 | x_args.push_back(*it); 67 | } 68 | ret = EqObjPtr(new Product(x_args)); 69 | } 70 | else 71 | { 72 | ret = EqObjPtr(new Product(x, y)); 73 | } 74 | 75 | return ret; 76 | } 77 | 78 | EqObjPtr pow (EqObjPtr x, EqObjPtr y); 79 | 80 | inline EqObjPtr operator/ (EqObjPtr x, EqObjPtr y) 81 | { 82 | if (y->hasReciprocal()) 83 | { 84 | if ((x->getType() == CONST_OBJ) && (y->getType() == CONST_OBJ)) 85 | { 86 | return EqObjPtr(new Product(x, y->getReciprocal()))->Simplify(); 87 | } 88 | } 89 | return EqObjPtr(new Product(x, pow(y, con(-1)))); 90 | } 91 | 92 | inline EqObjPtr operator+ (EqObjPtr x, EqObjPtr y) 93 | { 94 | EqObjPtr ret; 95 | if (x->isZero()) 96 | { 97 | ret = y; 98 | } 99 | else if (y->isZero()) 100 | { 101 | ret = x; 102 | } 103 | else if (x->getType() == Eqo::ADD_OBJ) 104 | { 105 | std::vector x_args = x->getArgs(); 106 | 107 | if (y->getType() == Eqo::ADD_OBJ) 108 | { 109 | std::vector y_args = y->getArgs(); 110 | for (std::vector::iterator it = y_args.begin(); it != y_args.end(); ++it) 111 | { 112 | x_args.push_back(*it); 113 | } 114 | } 115 | else 116 | { 117 | x_args.push_back(y); 118 | } 119 | 120 | ret = EqObjPtr(new Add(x_args)); 121 | } 122 | else if (y->getType() == Eqo::ADD_OBJ) 123 | { 124 | std::vector y_args = y->getArgs(); 125 | std::vector x_args; 126 | x_args.reserve(y_args.size() + 1); 127 | x_args.push_back(x); 128 | for (std::vector::iterator it = y_args.begin(); it != y_args.end(); ++it) 129 | { 130 | x_args.push_back(*it); 131 | } 132 | 133 | ret = EqObjPtr(new Add(x_args)); 134 | } 135 | else 136 | { 137 | ret = EqObjPtr(new Add(x,y)); 138 | } 139 | 140 | return ret; 141 | } 142 | 143 | inline EqObjPtr operator- (EqObjPtr x, EqObjPtr y) 144 | { 145 | return (x + (con(-1)*y)); 146 | } 147 | 148 | inline EqObjPtr exp (EqObjPtr x) 149 | { 150 | return EqObjPtr(new Exponent(x)); 151 | } 152 | 153 | inline EqObjPtr pow (EqObjPtr x, EqObjPtr y) 154 | { 155 | return EqObjPtr(new Pow(x, y)); 156 | } 157 | 158 | inline EqObjPtr log (EqObjPtr x) 159 | { 160 | return EqObjPtr(new Log(x)); 161 | } 162 | 163 | inline EqObjPtr diff(EqObjPtr x, EqObjPtr y) 164 | { 165 | return x->Derivative(y); 166 | } 167 | 168 | inline EqObjPtr var(const char *x) 169 | { 170 | return EqObjPtr(new Variable(std::string(x))); 171 | } 172 | 173 | inline EqObjPtr var(const std::string &x) 174 | { 175 | return EqObjPtr(new Variable(x)); 176 | } 177 | 178 | inline EqObjPtr sqrt(EqObjPtr x) 179 | { 180 | return EqObjPtr(pow(x, con(0.5))); 181 | } 182 | 183 | inline EqObjPtr reciprocal_sqrt(EqObjPtr x) 184 | { 185 | return EqObjPtr(pow(x, con(-0.5))); 186 | } 187 | 188 | /// keeps simplifying expression until string value doesn't change 189 | inline EqObjPtr Simplify(EqObjPtr x) 190 | { 191 | std::string y = x->stringValue(); 192 | EqObjPtr z = x->Simplify(); 193 | while (y != z->stringValue()) 194 | { 195 | y = z -> stringValue(); 196 | z = z -> Simplify(); 197 | } 198 | return z; 199 | } 200 | 201 | inline EqObjPtr getConstantFactor(EqObjPtr x) 202 | { 203 | return x->getScale(); 204 | } 205 | 206 | inline EqObjPtr Expand(EqObjPtr x) 207 | { 208 | std::string str = x->stringValue(); 209 | EqObjPtr eq = x->expand(); 210 | while (str != eq->stringValue()) 211 | { 212 | str = eq->stringValue(); 213 | eq = eq->expand(); 214 | } 215 | return Simplify(eq); 216 | } 217 | 218 | inline EqObjPtr getUnscaledValue(EqObjPtr x) 219 | { 220 | return x->getUnscaledValue(); 221 | } 222 | 223 | inline EqObjPtr getUnsignedValue(EqObjPtr x) 224 | { 225 | return x->getUnsignedValue(); 226 | } 227 | 228 | inline EqObjPtr getSign(EqObjPtr x) 229 | { 230 | return EqObjPtr(new Constant(x->getSign())); 231 | } 232 | 233 | /// Sorts in order of constants, variables, then other objects 234 | void SortEqVector(std::vector &v1); 235 | 236 | inline EqObjPtr subst(EqObjPtr a, EqObjPtr b, EqObjPtr c) 237 | { 238 | return a->subst(b->stringValue(), c); 239 | } 240 | 241 | inline EqObjPtr getNegation(EqObjPtr x) 242 | { 243 | EqObjPtr ret = Eqo::con(-1) * x; 244 | if (x->getType() == Eqo::CONST_OBJ) 245 | { 246 | ret = ret->Simplify(); 247 | } 248 | return ret; 249 | } 250 | } 251 | #endif 252 | 253 | 254 | -------------------------------------------------------------------------------- /src/engine/IfElse.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "IfElse.hh" 8 | #include "Functions.hh" 9 | #include 10 | 11 | namespace Eqo { 12 | std::set IfObj::getReferencedType(Eqo::EqObjType rt) 13 | { 14 | std::vector x; 15 | x.push_back(test); 16 | x.push_back(arg); 17 | return UniteReferencedType(rt, x); 18 | } 19 | 20 | std::set IfElseObj::getReferencedType(Eqo::EqObjType rt) 21 | { 22 | std::vector x; 23 | x.push_back(test); 24 | x.push_back(arg1); 25 | x.push_back(arg2); 26 | return UniteReferencedType(rt, x); 27 | } 28 | 29 | 30 | IfObj::IfObj(EqObjPtr t, EqObjPtr a) : EquationObject(IF_OBJ), test(t), arg(a) 31 | { 32 | } 33 | 34 | std::string IfObj::createStringValue() const 35 | { 36 | std::ostringstream os; 37 | os << "(if (" 38 | << test->stringValue() 39 | << ", " 40 | << arg->stringValue() << "))"; 41 | return os.str(); 42 | } 43 | 44 | EqObjPtr IfObj::Derivative(EqObjPtr foo) 45 | { 46 | return EqObjPtr(new IfObj(test->clone(), arg->Derivative(foo))); 47 | } 48 | 49 | EqObjPtr IfObj::Simplify() 50 | { 51 | return EqObjPtr(new IfObj(test->Simplify(), arg->Simplify())); 52 | } 53 | 54 | /// let it just be what it was 55 | EqObjPtr IfObj::CombineProduct(std::vector y) 56 | { 57 | if (y.empty()) 58 | return (shared_from_this()); 59 | 60 | y.push_back(shared_from_this()); 61 | return EqObjPtr(new Product(y)); 62 | } 63 | 64 | EqObjPtr IfObj::CombineAdd(std::vector y) 65 | { 66 | if (y.empty()) 67 | return (shared_from_this()); 68 | 69 | y.push_back(shared_from_this()); 70 | return EqObjPtr(new Add(y)); 71 | } 72 | 73 | EqObjPtr IfObj::clone() 74 | { 75 | return EqObjPtr(new IfObj(test->clone(), arg->clone())); 76 | } 77 | 78 | bool IfObj::isZero() 79 | { 80 | return false; 81 | } 82 | 83 | bool IfObj::isOne() 84 | { 85 | return false; 86 | } 87 | 88 | EqObjPtr IfObj::getUnscaledValue() 89 | { 90 | return shared_from_this(); 91 | } 92 | 93 | double IfObj::getSign() 94 | { 95 | return 1.0; 96 | } 97 | 98 | EqObjPtr IfObj::getUnsignedValue() 99 | { 100 | return shared_from_this(); 101 | } 102 | 103 | EqObjPtr IfObj::expand() 104 | { 105 | return shared_from_this(); 106 | } 107 | 108 | EqObjPtr IfObj::getScale() 109 | { 110 | return con(1.0); 111 | } 112 | 113 | EqObjPtr IfObj::subst(const std::string &str, EqObjPtr eqo) 114 | { 115 | if (str == this->stringValue()) 116 | { 117 | return eqo->clone(); 118 | } 119 | else 120 | { 121 | return EqObjPtr(new IfObj(test->subst(str, eqo), arg->subst(str,eqo))); 122 | } 123 | } 124 | 125 | EqObjPtr IfObj::getReciprocal() 126 | { 127 | assert(false); 128 | return con(0); 129 | } 130 | 131 | IfElseObj::IfElseObj(EqObjPtr t, EqObjPtr a1, EqObjPtr a2) : EquationObject(IFELSE_OBJ), test(t), arg1(a1), arg2(a2) 132 | { 133 | } 134 | 135 | std::string IfElseObj::createStringValue() const 136 | { 137 | std::ostringstream os; 138 | os << "(ifelse (" 139 | << test->stringValue() 140 | << ", " 141 | << arg1->stringValue() << ", " 142 | << arg2->stringValue() << "))"; 143 | return os.str(); 144 | } 145 | 146 | EqObjPtr IfElseObj::Derivative(EqObjPtr foo) 147 | { 148 | return EqObjPtr(new IfElseObj(test->clone(), arg1->Derivative(foo), arg2->Derivative(foo))); 149 | } 150 | 151 | EqObjPtr IfElseObj::Simplify() 152 | { 153 | return EqObjPtr(new IfElseObj(test->Simplify(), arg1->Simplify(), arg2->Simplify())); 154 | } 155 | 156 | /// let it just be what it was 157 | EqObjPtr IfElseObj::CombineProduct(std::vector y) 158 | { 159 | if (y.empty()) 160 | return (shared_from_this()); 161 | 162 | y.push_back(shared_from_this()); 163 | return EqObjPtr(new Product(y)); 164 | } 165 | 166 | EqObjPtr IfElseObj::CombineAdd(std::vector y) 167 | { 168 | if (y.empty()) 169 | return (shared_from_this()); 170 | 171 | y.push_back(shared_from_this()); 172 | return EqObjPtr(new Add(y)); 173 | } 174 | 175 | EqObjPtr IfElseObj::clone() 176 | { 177 | return EqObjPtr(new IfElseObj(test->clone(), arg1->clone(), arg2->clone())); 178 | } 179 | 180 | bool IfElseObj::isZero() 181 | { 182 | return false; 183 | } 184 | 185 | bool IfElseObj::isOne() 186 | { 187 | return false; 188 | } 189 | 190 | EqObjPtr IfElseObj::getUnscaledValue() 191 | { 192 | return shared_from_this(); 193 | } 194 | 195 | double IfElseObj::getSign() 196 | { 197 | return 1.0; 198 | } 199 | 200 | EqObjPtr IfElseObj::getUnsignedValue() 201 | { 202 | return shared_from_this(); 203 | } 204 | 205 | EqObjPtr IfElseObj::expand() 206 | { 207 | return shared_from_this(); 208 | } 209 | 210 | EqObjPtr IfElseObj::getScale() 211 | { 212 | return con(1.0); 213 | } 214 | 215 | EqObjPtr IfElseObj::subst(const std::string &str, EqObjPtr eqo) 216 | { 217 | if (str == this->stringValue()) 218 | { 219 | return eqo->clone(); 220 | } 221 | else 222 | { 223 | return EqObjPtr(new IfElseObj(test->subst(str, eqo), arg1->subst(str,eqo), arg2->subst(str,eqo))); 224 | } 225 | } 226 | 227 | EqObjPtr IfElseObj::getReciprocal() 228 | { 229 | assert(false); 230 | return con(0); 231 | } 232 | 233 | } 234 | 235 | -------------------------------------------------------------------------------- /src/engine/IfElse.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef IF_ELSE_HH 8 | #define IF_ELSE_HH 9 | #include "EquationObject.hh" 10 | 11 | namespace Eqo { 12 | class IfObj : public EquationObject 13 | { 14 | public: 15 | IfObj(EqObjPtr /*test*/, EqObjPtr /*result*/); 16 | ~IfObj() {}; 17 | 18 | EqObjPtr Derivative(EqObjPtr); 19 | EqObjPtr Simplify(); 20 | 21 | EqObjPtr CombineProduct(std::vector); 22 | EqObjPtr CombineAdd(std::vector); 23 | 24 | bool isZero(); 25 | bool isOne(); 26 | 27 | EqObjPtr getScale(); 28 | EqObjPtr getUnscaledValue(); 29 | 30 | double getSign(); 31 | EqObjPtr getUnsignedValue(); 32 | 33 | EqObjPtr clone(); 34 | EqObjPtr subst(const std::string &, EqObjPtr); 35 | 36 | EqObjPtr expand(); 37 | 38 | std::vector getArgs() { 39 | return createArgs(test, arg); 40 | } 41 | 42 | bool hasReciprocal() {return false;} 43 | EqObjPtr getReciprocal(); 44 | 45 | std::set getReferencedType(Eqo::EqObjType rt); 46 | 47 | std::string getName() const 48 | { 49 | return "if"; 50 | } 51 | 52 | private: 53 | std::string createStringValue() const; 54 | 55 | IfObj(const IfObj &); 56 | IfObj operator=(const IfObj &); 57 | 58 | const EqObjPtr test; 59 | const EqObjPtr arg; 60 | }; 61 | 62 | class IfElseObj : public EquationObject 63 | { 64 | public: 65 | IfElseObj(EqObjPtr /*test*/, EqObjPtr /*left*/, EqObjPtr /*right*/); 66 | ~IfElseObj() {}; 67 | 68 | EqObjPtr Derivative(EqObjPtr); 69 | EqObjPtr Simplify(); 70 | 71 | EqObjPtr CombineProduct(std::vector); 72 | EqObjPtr CombineAdd(std::vector); 73 | 74 | bool isZero(); 75 | bool isOne(); 76 | 77 | EqObjPtr getScale(); 78 | EqObjPtr getUnscaledValue(); 79 | 80 | double getSign(); 81 | EqObjPtr getUnsignedValue(); 82 | 83 | EqObjPtr clone(); 84 | EqObjPtr subst(const std::string &, EqObjPtr); 85 | 86 | EqObjPtr expand(); 87 | 88 | std::vector getArgs() { 89 | return createArgs(test, arg1, arg2); 90 | } 91 | 92 | bool hasReciprocal() {return false;} 93 | EqObjPtr getReciprocal(); 94 | 95 | std::set getReferencedType(Eqo::EqObjType rt); 96 | 97 | std::string getName() const 98 | { 99 | return "ifelse"; 100 | } 101 | private: 102 | std::string createStringValue() const; 103 | 104 | IfElseObj(const IfElseObj &); 105 | IfElseObj operator=(const IfElseObj &); 106 | 107 | EqObjPtr test; 108 | EqObjPtr arg1; 109 | EqObjPtr arg2; 110 | }; 111 | } 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /src/engine/Log.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "Log.hh" 8 | #include "Functions.hh" 9 | #include 10 | 11 | namespace Eqo { 12 | Log::Log(EqObjPtr var) : EquationObject(LOG_OBJ), value(var) 13 | { 14 | } 15 | 16 | std::string Log::createStringValue() const 17 | { 18 | std::ostringstream os; 19 | os << "log(" << value << ")"; 20 | return std::string(os.str()); 21 | } 22 | 23 | EqObjPtr Log::Derivative(EqObjPtr foo) 24 | { 25 | EqObjPtr ret; 26 | if (value->getType() == CONST_OBJ) 27 | { 28 | ret = con(0.0); 29 | } 30 | else 31 | { 32 | ret = value->Derivative(foo)*pow(value,EqObjPtr(new Constant(-1.0))); 33 | } 34 | 35 | return ret; 36 | } 37 | 38 | EqObjPtr Log::Simplify() 39 | { 40 | if (value->isOne()) 41 | return con(0); 42 | 43 | ///log(exp(x))) = x; 44 | if (value->getType() == EXPONENT_OBJ) 45 | { 46 | Exponent *Y = dynamic_cast(value.get()); 47 | return (Y->value); 48 | } 49 | 50 | ///log(exp(x))) = x; 51 | if (value->getType() == EXPONENT_OBJ) 52 | { 53 | Exponent *Y = dynamic_cast(value.get()); 54 | return (Y->value); 55 | } 56 | 57 | ///log(pow(x,y))) = y*log(x); 58 | if (value->getType() == POW_OBJ) 59 | { 60 | Pow *Y = dynamic_cast(value.get()); 61 | return (Y->exponent * log(Y->base)); 62 | } 63 | 64 | return log(value->Simplify()); 65 | } 66 | 67 | EqObjPtr Log::CombineProduct(std::vector y) 68 | { 69 | if (y.empty()) 70 | return shared_from_this(); 71 | 72 | y.push_back(shared_from_this()); 73 | return EqObjPtr(new Product(y)); 74 | } 75 | 76 | /** 77 | * now just return original std::vector 78 | * in the future, log(x)+log(y) = log(x*y) 79 | */ 80 | EqObjPtr Log::CombineAdd(std::vector y) 81 | { 82 | if (y.empty()) 83 | return shared_from_this(); 84 | 85 | y.push_back(shared_from_this()); 86 | return EqObjPtr(new Add(y)); 87 | } 88 | 89 | bool Log::isZero() 90 | { 91 | return false; 92 | } 93 | 94 | bool Log::isOne() 95 | { 96 | return false; 97 | } 98 | 99 | EqObjPtr Log::getScale() 100 | { 101 | return con(1); 102 | } 103 | 104 | EqObjPtr Log::getUnscaledValue() 105 | { 106 | return shared_from_this(); 107 | } 108 | 109 | double Log::getSign() 110 | { 111 | return 1.0; 112 | } 113 | 114 | EqObjPtr Log::getUnsignedValue() 115 | { 116 | return shared_from_this(); 117 | } 118 | 119 | EqObjPtr Log::clone() 120 | { 121 | EquationObject *n = new Log(value->clone()); 122 | return EqObjPtr(n); 123 | } 124 | 125 | EqObjPtr Log::subst(const std::string &str, EqObjPtr eqo) 126 | { 127 | if (str == this->stringValue()) 128 | return eqo; 129 | else 130 | return log(value->subst(str, eqo)); 131 | } 132 | 133 | EqObjPtr Log::expand() 134 | { 135 | return log(value->expand()); 136 | } 137 | 138 | EqObjPtr Log::getReciprocal() 139 | { 140 | assert(false); 141 | return con(0); 142 | } 143 | } 144 | 145 | -------------------------------------------------------------------------------- /src/engine/Log.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef LOG_HH 8 | #define LOG_HH 9 | #include "EquationObject.hh" 10 | namespace Eqo { 11 | class Log : public EquationObject { 12 | public: 13 | Log(EqObjPtr); 14 | 15 | EqObjPtr Derivative(EqObjPtr); 16 | EqObjPtr Simplify(); 17 | 18 | EqObjPtr CombineProduct(std::vector); 19 | EqObjPtr CombineAdd(std::vector); 20 | 21 | bool isZero(); 22 | bool isOne(); 23 | 24 | EqObjPtr getScale(); 25 | EqObjPtr getUnscaledValue(); 26 | 27 | double getSign(); 28 | EqObjPtr getUnsignedValue(); 29 | 30 | EqObjPtr clone(); 31 | EqObjPtr subst(const std::string &, EqObjPtr); 32 | 33 | EqObjPtr expand(); 34 | 35 | bool hasReciprocal() {return false;} 36 | EqObjPtr getReciprocal(); 37 | std::set getReferencedType(Eqo::EqObjType rt) 38 | { 39 | return value->getReferencedType(rt); 40 | } 41 | 42 | friend class Exponent; 43 | 44 | std::vector getArgs() { 45 | return createArgs(value); 46 | } 47 | 48 | std::string getName() const 49 | { 50 | return "log"; 51 | } 52 | 53 | private: 54 | std::string createStringValue() const; 55 | 56 | Log(const Log &); 57 | Log operator=(const Log &); 58 | 59 | const EqObjPtr value; 60 | }; 61 | } 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /src/engine/LogicalFunc.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "LogicalFunc.hh" 8 | #include "Functions.hh" 9 | #include 10 | #include 11 | 12 | namespace Eqo { 13 | /** 14 | * this will most likely always take "!" 15 | */ 16 | UnaryLogical::UnaryLogical(const std::string &op, EqObjPtr x) : EquationObject(ULOGICAL_OBJ), unaryOperator(op), arg(x) 17 | { 18 | } 19 | 20 | std::string UnaryLogical::createStringValue() const 21 | { 22 | std::ostringstream os; 23 | os << "(" 24 | << unaryOperator 25 | << arg->stringValue() << ")"; 26 | return os.str(); 27 | } 28 | 29 | /** 30 | * Logical operators should always return 0 31 | */ 32 | EqObjPtr UnaryLogical::Derivative(EqObjPtr) 33 | { 34 | return con(0.0); 35 | } 36 | 37 | /** 38 | * a !! should cancel things out 39 | * work this out later 40 | * this should be invariant in a logical 41 | */ 42 | EqObjPtr UnaryLogical::Simplify() 43 | { 44 | return shared_from_this(); 45 | } 46 | 47 | /// let it just be what it was 48 | EqObjPtr UnaryLogical::CombineProduct(std::vector y) 49 | { 50 | if (y.empty()) 51 | return (shared_from_this()); 52 | 53 | y.push_back(shared_from_this()); 54 | return EqObjPtr(new Product(y)); 55 | } 56 | 57 | EqObjPtr UnaryLogical::CombineAdd(std::vector y) 58 | { 59 | if (y.empty()) 60 | return (shared_from_this()); 61 | 62 | y.push_back(shared_from_this()); 63 | return EqObjPtr(new Add(y)); 64 | } 65 | 66 | EqObjPtr UnaryLogical::clone() 67 | { 68 | return EqObjPtr(new UnaryLogical(unaryOperator, arg->clone())); 69 | } 70 | 71 | bool UnaryLogical::isZero() 72 | { 73 | return false; 74 | } 75 | 76 | bool UnaryLogical::isOne() 77 | { 78 | return false; 79 | } 80 | 81 | EqObjPtr UnaryLogical::getUnscaledValue() 82 | { 83 | return shared_from_this(); 84 | } 85 | 86 | double UnaryLogical::getSign() 87 | { 88 | return 1.0; 89 | } 90 | 91 | EqObjPtr UnaryLogical::getUnsignedValue() 92 | { 93 | return shared_from_this(); 94 | } 95 | 96 | EqObjPtr UnaryLogical::expand() 97 | { 98 | return shared_from_this(); 99 | } 100 | 101 | EqObjPtr UnaryLogical::getScale() 102 | { 103 | return con(1.0); 104 | } 105 | 106 | EqObjPtr UnaryLogical::subst(const std::string &str, EqObjPtr eqo) 107 | { 108 | if (str == this->stringValue()) 109 | { 110 | return eqo->clone(); 111 | } 112 | else 113 | { 114 | return EqObjPtr(new UnaryLogical(unaryOperator, arg->subst(str, eqo))); 115 | } 116 | } 117 | 118 | EqObjPtr UnaryLogical::getReciprocal() 119 | { 120 | assert(false); 121 | return con(0); 122 | } 123 | 124 | BinaryLogical::BinaryLogical(const std::string &op, EqObjPtr x, EqObjPtr y) : EquationObject(BLOGICAL_OBJ), binaryOperator(op), arg1(x), arg2(y) 125 | { 126 | } 127 | 128 | std::string BinaryLogical::createStringValue() const 129 | { 130 | std::ostringstream os; 131 | os << "(" << arg1->stringValue() 132 | << " " << binaryOperator << " " 133 | << arg2->stringValue() << ")"; 134 | return os.str(); 135 | } 136 | 137 | /** 138 | * Logical operators should always return 0 139 | */ 140 | EqObjPtr BinaryLogical::Derivative(EqObjPtr) 141 | { 142 | return con(0.0); 143 | } 144 | 145 | /** 146 | * a !! should cancel things out 147 | * work this out later 148 | * this should be invariant in a logical 149 | */ 150 | EqObjPtr BinaryLogical::Simplify() 151 | { 152 | return shared_from_this(); 153 | } 154 | 155 | /// let it just be what it was 156 | EqObjPtr BinaryLogical::CombineProduct(std::vector y) 157 | { 158 | if (y.empty()) 159 | return (shared_from_this()); 160 | 161 | y.push_back(shared_from_this()); 162 | return EqObjPtr(new Product(y)); 163 | } 164 | 165 | EqObjPtr BinaryLogical::CombineAdd(std::vector y) 166 | { 167 | if (y.empty()) 168 | return (shared_from_this()); 169 | 170 | y.push_back(shared_from_this()); 171 | return EqObjPtr(new Add(y)); 172 | } 173 | 174 | EqObjPtr BinaryLogical::clone() 175 | { 176 | return EqObjPtr(new BinaryLogical(binaryOperator, arg1->clone(), arg2->clone())); 177 | } 178 | 179 | bool BinaryLogical::isZero() 180 | { 181 | return false; 182 | } 183 | 184 | bool BinaryLogical::isOne() 185 | { 186 | return false; 187 | } 188 | 189 | EqObjPtr BinaryLogical::getUnscaledValue() 190 | { 191 | return shared_from_this(); 192 | } 193 | 194 | double BinaryLogical::getSign() 195 | { 196 | return 1.0; 197 | } 198 | 199 | EqObjPtr BinaryLogical::getUnsignedValue() 200 | { 201 | return shared_from_this(); 202 | } 203 | 204 | EqObjPtr BinaryLogical::expand() 205 | { 206 | return shared_from_this(); 207 | } 208 | 209 | EqObjPtr BinaryLogical::getScale() 210 | { 211 | return con(1.0); 212 | } 213 | 214 | EqObjPtr BinaryLogical::subst(const std::string &str, EqObjPtr eqo) 215 | { 216 | if (str == this->stringValue()) 217 | { 218 | return eqo->clone(); 219 | } 220 | else 221 | { 222 | return EqObjPtr(new BinaryLogical(binaryOperator, arg1->subst(str,eqo), arg2->subst(str,eqo))); 223 | } 224 | } 225 | 226 | EqObjPtr BinaryLogical::getReciprocal() 227 | { 228 | assert(false); 229 | return con(0); 230 | } 231 | 232 | } 233 | 234 | -------------------------------------------------------------------------------- /src/engine/LogicalFunc.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef LOGICALFUNC_HH 8 | #define LOGICALFUNC_HH 9 | #include "EquationObject.hh" 10 | 11 | /** 12 | * Here we will define two types of functions for logicals 13 | * 1. Unary ! 14 | * 2. Binary != == < > <= >= && || 15 | * 16 | * Derivatives are assumed to be zero 17 | */ 18 | namespace Eqo { 19 | class UnaryLogical : public EquationObject 20 | { 21 | public: 22 | UnaryLogical(const std::string &/*unaryOp*/, EqObjPtr /*arg*/); 23 | ~UnaryLogical() {}; 24 | 25 | EqObjPtr Derivative(EqObjPtr); 26 | EqObjPtr Simplify(); 27 | 28 | EqObjPtr CombineProduct(std::vector); 29 | EqObjPtr CombineAdd(std::vector); 30 | 31 | bool isZero(); 32 | bool isOne(); 33 | 34 | EqObjPtr getScale(); 35 | EqObjPtr getUnscaledValue(); 36 | 37 | double getSign(); 38 | EqObjPtr getUnsignedValue(); 39 | 40 | EqObjPtr clone(); 41 | EqObjPtr subst(const std::string &, EqObjPtr); 42 | 43 | EqObjPtr expand(); 44 | 45 | std::vector getArgs() { 46 | return createArgs(arg); 47 | } 48 | 49 | const std::string &getOperator() const 50 | { 51 | return unaryOperator; 52 | } 53 | 54 | std::string getName() const 55 | { 56 | return getOperator(); 57 | } 58 | 59 | bool hasReciprocal() {return false;} 60 | EqObjPtr getReciprocal(); 61 | 62 | std::set getReferencedType(Eqo::EqObjType rt) { 63 | return arg->getReferencedType(rt); 64 | } 65 | 66 | private: 67 | std::string createStringValue() const; 68 | 69 | UnaryLogical(const UnaryLogical &); 70 | UnaryLogical operator=(const UnaryLogical &); 71 | 72 | const std::string unaryOperator; 73 | const EqObjPtr arg; 74 | }; 75 | 76 | class BinaryLogical : public EquationObject 77 | { 78 | public: 79 | BinaryLogical(const std::string & /*op*/, EqObjPtr /*left*/, EqObjPtr /*right*/); 80 | ~BinaryLogical() {}; 81 | 82 | EqObjPtr Derivative(EqObjPtr); 83 | EqObjPtr Simplify(); 84 | 85 | EqObjPtr CombineProduct(std::vector); 86 | EqObjPtr CombineAdd(std::vector); 87 | 88 | bool isZero(); 89 | bool isOne(); 90 | 91 | EqObjPtr getScale(); 92 | EqObjPtr getUnscaledValue(); 93 | 94 | double getSign(); 95 | EqObjPtr getUnsignedValue(); 96 | 97 | EqObjPtr clone(); 98 | EqObjPtr subst(const std::string &, EqObjPtr); 99 | 100 | EqObjPtr expand(); 101 | 102 | std::vector getArgs() { 103 | return createArgs(arg1, arg2); 104 | } 105 | 106 | const std::string &getOperator() const 107 | { 108 | return binaryOperator; 109 | } 110 | 111 | std::string getName() const 112 | { 113 | return getOperator(); 114 | } 115 | 116 | bool hasReciprocal() {return false;} 117 | EqObjPtr getReciprocal(); 118 | 119 | std::set getReferencedType(Eqo::EqObjType rt) { 120 | return UniteReferencedType(rt, arg1, arg2); 121 | } 122 | 123 | private: 124 | std::string createStringValue() const; 125 | 126 | BinaryLogical(const BinaryLogical &); 127 | BinaryLogical operator=(const BinaryLogical &); 128 | 129 | const std::string binaryOperator; 130 | EqObjPtr arg1; 131 | EqObjPtr arg2; 132 | }; 133 | } 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /src/engine/Pow.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef POW_HH 8 | #define POW_HH 9 | #include "EquationObject.hh" 10 | namespace Eqo { 11 | class Pow : public EquationObject { 12 | public: 13 | Pow(EqObjPtr, EqObjPtr); 14 | 15 | EqObjPtr Derivative(EqObjPtr); 16 | EqObjPtr Simplify(); 17 | 18 | EqObjPtr CombineProduct(std::vector); 19 | EqObjPtr CombineAdd(std::vector); 20 | 21 | bool isZero(); 22 | bool isOne(); 23 | 24 | EqObjPtr getScale(); 25 | EqObjPtr getUnscaledValue(); 26 | 27 | double getSign(); 28 | EqObjPtr getUnsignedValue(); 29 | 30 | EqObjPtr clone(); 31 | EqObjPtr subst(const std::string &, EqObjPtr); 32 | 33 | EqObjPtr expand(); 34 | 35 | bool hasReciprocal() {return false;} 36 | EqObjPtr getReciprocal(); 37 | std::set getReferencedType(Eqo::EqObjType rt) 38 | { 39 | return UniteReferencedType(rt, base, exponent); 40 | } 41 | 42 | friend class Log; 43 | friend class Product; 44 | 45 | std::vector getArgs() { 46 | return createArgs(base, exponent); 47 | } 48 | 49 | std::string getName() const 50 | { 51 | return "pow"; 52 | } 53 | private: 54 | std::string createStringValue() const; 55 | 56 | Pow(const Pow &); 57 | Pow operator=(const Pow &); 58 | 59 | const EqObjPtr base; 60 | const EqObjPtr exponent; 61 | }; 62 | 63 | } 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /src/engine/ProcessModelOrder.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "ProcessModelOrder.hh" 8 | #include "EquationObject.hh" 9 | #include 10 | 11 | const ModelNameVector_t &ProcessModelOrder::GetModelVector(const ModelMap_t &model_list, const ModelNameVector_t &input_list) 12 | { 13 | processedList_.clear(); 14 | processedList_.reserve(input_list.size()); 15 | processStatusMap_.clear(); 16 | for (ModelNameVector_t::const_iterator it = input_list.begin(); it != input_list.end(); ++it) 17 | { 18 | const std::string &model_name = *it; 19 | const ProcessStatus_t status = processStatusMap_[model_name]; 20 | 21 | ModelMap_t::const_iterator mit = model_list.find(model_name); 22 | 23 | if (status == DONE) 24 | { 25 | } 26 | else if (mit == model_list.end()) 27 | { 28 | errorString_ += model_name + " was not declared or defined as a model\n"; 29 | 30 | } 31 | else if (!(mit->second)) 32 | { 33 | errorString_ += model_name + " was not defined as a model\n"; 34 | } 35 | //// impossible for this model to be in processing 36 | else if (status == UNTOUCHED) 37 | { 38 | 39 | processModelVector(model_list, mit->second); 40 | } 41 | 42 | processStatusMap_[model_name] = DONE; 43 | processedList_.push_back(model_name); 44 | } 45 | 46 | return processedList_; 47 | } 48 | 49 | /* 50 | Only print equations 51 | Called recursively. Refactor, if possible, using iteration. 52 | */ 53 | void ProcessModelOrder::processModelVector(const ModelMap_t &model_list, Eqo::EqObjPtr eq) 54 | { 55 | std::set mset; 56 | 57 | const Eqo::EqObjType equation_type = eq->getType(); 58 | if (equation_type == Eqo::MODEL_OBJ) 59 | { 60 | const std::string &mname = eq->stringValue(); 61 | const ProcessStatus_t status = processStatusMap_[mname]; 62 | if (status == DONE) 63 | { 64 | return; 65 | } 66 | else if (status == PROCESSING) 67 | { 68 | errorString_ += mname + " is being processed in terms of itself\n"; 69 | processStatusMap_[mname] = DONE; 70 | return; 71 | } 72 | else if (status == UNTOUCHED) 73 | { 74 | processStatusMap_[mname] = PROCESSING; 75 | } 76 | 77 | ModelMap_t::const_iterator mit = model_list.find(mname); 78 | if (mit != model_list.end()) 79 | { 80 | if (mit->second) 81 | { 82 | mset = (mit->second)->getReferencedType(Eqo::MODEL_OBJ); 83 | } 84 | } 85 | 86 | } 87 | else 88 | { 89 | //// Get all models referenced by this object 90 | mset = eq->getReferencedType(Eqo::MODEL_OBJ); 91 | } 92 | 93 | std::set::iterator it =mset.begin(); 94 | std::set::iterator end=mset.end(); 95 | for ( ; it != end; ++it) 96 | { 97 | const std::string &sname = *it; 98 | // Model was processed, we are done 99 | if (processStatusMap_[sname] == DONE) 100 | { 101 | continue; 102 | } 103 | 104 | ModelMap_t::const_iterator mit = model_list.find(sname); 105 | if (mit != model_list.end()) 106 | { 107 | //// print out all models referenced by this equation 108 | Eqo::EqObjPtr x = mit->second; 109 | if (x) 110 | { 111 | processModelVector(model_list, x); 112 | } 113 | processedList_.push_back(sname); 114 | processStatusMap_[sname] = DONE; 115 | 116 | } 117 | } 118 | 119 | //// If we are a model, go ahead and print out our equation 120 | if (equation_type == Eqo::MODEL_OBJ) 121 | { 122 | const std::string &mname = eq->stringValue(); 123 | processedList_.push_back(mname); 124 | processStatusMap_[mname] = DONE; 125 | } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /src/engine/ProcessModelOrder.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef PROCESSED_MODEL_ORDER 8 | #define PROCESSED_MODEL_ORDER 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include "SymdiffImport.hh" 16 | 17 | 18 | namespace Eqo 19 | { 20 | class EquationObject; 21 | typedef std::shared_ptr EqObjPtr; 22 | } 23 | 24 | typedef std::map ModelMap_t; 25 | typedef std::list > ModelList_t; 26 | typedef std::vector ModelNameVector_t; 27 | 28 | 29 | class DLL_PROTECTED ProcessModelOrder 30 | { 31 | public: 32 | // ProcessModelOrder(); 33 | 34 | const std::string &GetErrorString() const 35 | { 36 | return errorString_; 37 | } 38 | 39 | //// first list is all of our models 40 | //// second is list of model names we want together 41 | const ModelNameVector_t &GetModelVector(const ModelMap_t &, const ModelNameVector_t &); 42 | 43 | private: 44 | void processModelVector(const ModelMap_t &, Eqo::EqObjPtr); 45 | 46 | enum ProcessStatus_t {UNTOUCHED = 0, PROCESSING, DONE}; 47 | 48 | /// Use this for detecting cycles 49 | std::map processStatusMap_; 50 | /// This is the final list that we create as part of the operation 51 | ModelNameVector_t processedList_; 52 | std::string errorString_; 53 | 54 | }; 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /src/engine/ProcessOrderedTable.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2013 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "ProcessOrderedTable.hh" 8 | #include "EquationObject.hh" 9 | 10 | 11 | void ProcessOrderedTable::run(Eqo::EqObjPtr eq) 12 | { 13 | errors_.clear(); 14 | orderedTable_.clear(); 15 | orderedIndex_.clear(); 16 | processStatusMap_.clear(); 17 | processOrderedTable(eq); 18 | for (size_t i = 0; i < orderedTable_.size(); ++i) 19 | { 20 | std::vector &refs = orderedTable_[i].indexes_; 21 | if (!refs.empty()) 22 | { 23 | for (size_t j = 0; j < refs.size(); ++j) 24 | { 25 | orderedTable_[refs[j]].references_.push_back(i); 26 | } 27 | } 28 | } 29 | /* 30 | it should be noted that the existence of 2 different instances 31 | of the string value in the index means there is a type mismatch 32 | */ 33 | for (OrderedIndex_t::const_iterator it = orderedIndex_.begin(); it != orderedIndex_.end(); ++it) 34 | { 35 | if (it->second.size() > 1) 36 | { 37 | errors_.push_back(it->first); 38 | } 39 | } 40 | } 41 | 42 | namespace { 43 | bool CompareRows(const OrderedTableData &r1, const OrderedTableData &r2) 44 | { 45 | bool ret = true; 46 | if (r1.ptr_ != r2.ptr_) 47 | { 48 | const size_t len = r1.indexes_.size(); 49 | if (r1.ptr_->getType() != r2.ptr_->getType()) 50 | { 51 | ret = false; 52 | } 53 | else if (len != r2.indexes_.size()) 54 | { 55 | ret = false; 56 | } 57 | else 58 | { 59 | /* 60 | For the same type and args, each sub index will match 61 | */ 62 | for (size_t i = 0; i < len; ++i) 63 | { 64 | if (r1.indexes_[i] != r2.indexes_[i]) 65 | { 66 | ret = false; 67 | break; 68 | } 69 | } 70 | } 71 | } 72 | return ret; 73 | } 74 | 75 | size_t FindMatchedRow(const OrderedTable_t &table, const std::vector &indexes, OrderedTableData &newrow) 76 | { 77 | size_t ret = size_t(-1); 78 | size_t len = indexes.size(); 79 | for (size_t i = 0; i < len; ++i) 80 | { 81 | if (CompareRows(table[indexes[i]], newrow)) 82 | { 83 | ret = indexes[i]; 84 | break; 85 | } 86 | } 87 | return ret; 88 | } 89 | } 90 | 91 | /* make this return the indexes of the args processed */ 92 | /* does not handle when sub types (model/variable) have different types */ 93 | /* looks like it also handles subexpression elimination as well */ 94 | size_t ProcessOrderedTable::processOrderedTable(Eqo::EqObjPtr eq) { 95 | /* are we already in the table */ 96 | const std::string &value = eq->stringValue(); 97 | 98 | /* this implicitly creates if it doesn't exist */ 99 | std::vector &myindexes = orderedIndex_[value]; 100 | 101 | size_t myindex = size_t(-1); 102 | 103 | OrderedTableData newrow; 104 | newrow.value_ = value; 105 | newrow.ptr_ = eq; 106 | 107 | // This first test just does a pointer match 108 | myindex = FindMatchedRow(orderedTable_, myindexes, newrow); 109 | 110 | /* a deep comparison to make sure sub arguments are in the table */ 111 | if (myindex == size_t(-1)) 112 | { 113 | const std::vector &args = eq->getArgs(); 114 | newrow.indexes_.reserve(args.size()); 115 | // This is our current index 116 | for (std::vector::const_iterator it = args.begin(); it != args.end(); ++it) 117 | { 118 | newrow.indexes_.push_back(processOrderedTable(*it)); 119 | } 120 | 121 | myindex = FindMatchedRow(orderedTable_, myindexes, newrow); 122 | if (myindex == size_t(-1)) 123 | { 124 | myindex = orderedTable_.size(); 125 | // implicitly adds to the existing index row 126 | myindexes.push_back(myindex); 127 | orderedTable_.push_back(newrow); 128 | } 129 | } 130 | return myindex; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /src/engine/ProcessOrderedTable.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2013 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef ORDEREDTABLE_H 8 | #define ORDEREDTABLE_H 9 | 10 | 11 | #include 12 | #include "SymdiffImport.hh" 13 | #include 14 | #include 15 | #include 16 | /* 17 | Get a table representation of an existing expression 18 | */ 19 | namespace Eqo 20 | { 21 | class EquationObject; 22 | typedef std::shared_ptr EqObjPtr; 23 | } 24 | 25 | struct OrderedTableData { 26 | std::string value_; 27 | Eqo::EqObjPtr ptr_; 28 | std::vector indexes_; 29 | std::vector references_; 30 | }; 31 | typedef std::vector OrderedTable_t; 32 | typedef std::map > OrderedIndex_t; 33 | 34 | /** 35 | Creates a flat table by doing a depth first search. Refactor other algorithms use this. 36 | */ 37 | class DLL_PROTECTED ProcessOrderedTable { 38 | public: 39 | const std::vector &GetErrors() const 40 | { 41 | return errors_; 42 | } 43 | 44 | //// first list is all of our models 45 | //// second is list of model names we want together 46 | void run(Eqo::EqObjPtr); 47 | const OrderedTable_t &GetOrderedTable() 48 | { 49 | return orderedTable_; 50 | } 51 | const OrderedIndex_t &GetOrderedIndex() 52 | { 53 | return orderedIndex_; 54 | } 55 | 56 | private: 57 | size_t processOrderedTable(Eqo::EqObjPtr); 58 | 59 | enum ProcessStatus_t {UNTOUCHED = 0, PROCESSING, DONE}; 60 | 61 | /// Use this for detecting cycles 62 | std::map processStatusMap_; 63 | /// This is the final list that we create as part of the operation 64 | OrderedTable_t orderedTable_; 65 | OrderedIndex_t orderedIndex_; 66 | std::vector errors_; 67 | /// Add index here 68 | }; 69 | #endif 70 | 71 | -------------------------------------------------------------------------------- /src/engine/Product.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef PRODUCT_HH 8 | #define PRODUCT_HH 9 | #include "EquationObject.hh" 10 | namespace Eqo { 11 | class Product : public EquationObject { 12 | public: 13 | friend class Pow; 14 | Product(EqObjPtr, EqObjPtr); 15 | Product(std::vector); 16 | 17 | EqObjPtr Derivative(EqObjPtr); 18 | EqObjPtr Simplify(); 19 | 20 | EqObjPtr CombineProduct(std::vector); 21 | EqObjPtr CombineAdd(std::vector); 22 | 23 | bool isZero(); 24 | bool isOne(); 25 | 26 | EqObjPtr getScale(); 27 | EqObjPtr getUnscaledValue(); 28 | 29 | double getSign(); 30 | EqObjPtr getUnsignedValue(); 31 | 32 | EqObjPtr clone(); 33 | EqObjPtr subst(const std::string &, EqObjPtr); 34 | 35 | EqObjPtr expand(); 36 | 37 | void ProductVecSimplify(std::vector &); 38 | 39 | bool hasReciprocal() {return false;} 40 | EqObjPtr getReciprocal(); 41 | 42 | std::set getReferencedType(Eqo::EqObjType rt) 43 | { 44 | return UniteReferencedType(rt, values); 45 | } 46 | 47 | std::vector getArgs() { 48 | return createArgs(values); 49 | } 50 | 51 | std::string getName() const 52 | { 53 | return "*"; 54 | } 55 | 56 | private: 57 | std::string createStringValue() const; 58 | 59 | Product(const Product &); 60 | Product operator=(const Product &); 61 | 62 | std::vector values; 63 | }; 64 | } 65 | #endif 66 | -------------------------------------------------------------------------------- /src/engine/SubExpr.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef SUBEXPR_HH 8 | #define SUBEXPR_HH 9 | #include 10 | #include "SymdiffImport.hh" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | 18 | namespace Eqo 19 | { 20 | class EquationObject; 21 | typedef std::shared_ptr EqObjPtr; 22 | } 23 | 24 | typedef std::vector ModelNameVector_t; 25 | typedef std::map ModelMap_t; 26 | 27 | 28 | class SubExpr; 29 | 30 | class SubExprData 31 | { 32 | public: 33 | SubExprData() : refcount(0) {} 34 | explicit SubExprData(Eqo::EqObjPtr x); 35 | 36 | void addCount() 37 | { 38 | ++refcount; 39 | } 40 | size_t getCount() const 41 | { 42 | return refcount; 43 | } 44 | 45 | Eqo::EqObjPtr getEquation() const; 46 | 47 | const std::string &getName(SubExpr &subexpr) const; 48 | 49 | private: 50 | size_t refcount; 51 | Eqo::EqObjPtr equation; 52 | mutable std::string name; 53 | }; 54 | 55 | /// Creates sub expressions on the fly 56 | class DLL_PROTECTED SubExpr 57 | { 58 | public: 59 | SubExpr(); 60 | 61 | std::string GetUniqueName(); 62 | 63 | const std::string &GetErrorString() const 64 | { 65 | return errorString_; 66 | } 67 | 68 | void CreateSubexpressions(ModelMap_t &); 69 | void RemoveZeros(ModelMap_t &); 70 | 71 | private: 72 | bool removeZeros(ModelMap_t &); 73 | void scanSubexpression(Eqo::EqObjPtr &); 74 | void createSubexpressions(ModelMap_t &); 75 | 76 | enum ProcessStatus_t {UNTOUCHED = 0, PROCESSING, DONE}; 77 | 78 | /// Use this for detecting cycles 79 | std::map processStatusMap_; 80 | 81 | /// report errors if there is a problem 82 | std::string errorString_; 83 | 84 | std::map SubExprMap; 85 | std::vector SubExprOrdered; 86 | 87 | size_t unique_counter_; 88 | }; 89 | 90 | 91 | #endif 92 | 93 | -------------------------------------------------------------------------------- /src/engine/SymdiffImport.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | #ifndef SYMDIFF_IMPORT_HH 7 | #define SYMDIFF_IMPORT_HH 8 | #if defined _WIN32 9 | #define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax. 10 | #define DLL_LOCAL __declspec(dllimport) 11 | #else 12 | #define DLL_PUBLIC __attribute__ ((visibility("default"))) 13 | #define DLL_LOCAL __attribute__ ((visibility("hidden"))) 14 | #endif 15 | #endif 16 | 17 | #if defined _WIN32 18 | #define DLL_PROTECTED DLL_PUBLIC 19 | #elif defined(SYMDIFF_NO_EXTERN_SYMBOLS) 20 | #define DLL_PROTECTED DLL_LOCAL 21 | #else 22 | #define DLL_PROTECTED DLL_PUBLIC 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /src/engine/UserFunc.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "UserFunc.hh" 8 | #include "Functions.hh" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace Eqo { 16 | 17 | EqObjPtr UserFunc::getReciprocal() 18 | { 19 | assert(false); 20 | return con(0.0); 21 | } 22 | 23 | std::map UserFuncMap; 24 | 25 | // Used for implicitly declared functions 26 | void CreateUserFunc(std::string nm, size_t nar) 27 | { 28 | UserFuncMap[nm].resize(nar); 29 | } 30 | 31 | void SetUserFuncDiffs(std::string nm, UserDiffInfoVec &dif) 32 | { 33 | // cannot set diffs if they are already set 34 | // should actually print error 35 | if (UserFuncMap.count(nm)) 36 | { 37 | // \todo error handling 38 | // must be the same exact size 39 | } 40 | 41 | UserFuncMap[nm] = dif; // assume that I own this data 42 | #if 0 43 | UserDiffInfoVec f; 44 | for (size_t i = 0; i < dif.size(); ++i) 45 | { 46 | // clone may not be necessary 47 | f.push_back(std::make_pair(dif[i].first, dif[i].second->clone())); 48 | } 49 | UserFuncMap[nm] = f; 50 | #endif 51 | } 52 | 53 | UserFunc::UserFunc(std::string nm, std::vector &a) : EquationObject(USERFUNC_OBJ), name(nm) 54 | { 55 | if (!UserFuncMap.count(nm)) 56 | { 57 | UserFuncMap[nm].resize(a.size()); 58 | } 59 | 60 | args = a; // assume that I own this data 61 | } 62 | 63 | std::string UserFunc::createStringValue() const 64 | { 65 | const size_t len = args.size(); 66 | 67 | // \todo need to set special error handling 68 | std::ostringstream os; 69 | os << name << "("; 70 | for (size_t i=0; i < len; ++i) 71 | { 72 | if (i != 0) 73 | os << ", "; 74 | os << args[i]; 75 | } 76 | os << ")"; 77 | return os.str(); 78 | } 79 | 80 | // I'm substituting in for variable names 81 | EqObjPtr UserFunc::subst(const std::string &str, EqObjPtr eqo) 82 | { 83 | if (str == this->stringValue()) 84 | return eqo; 85 | else 86 | { 87 | std::vector new_args(args.size()); 88 | for (size_t i = 0; i < args.size(); ++i) 89 | { 90 | new_args[i] = args[i]->subst(str, eqo); 91 | } 92 | return EqObjPtr(new UserFunc(name, new_args)); 93 | } 94 | } 95 | 96 | //// unfinished 97 | // \todo optimize 98 | EqObjPtr UserFunc::Derivative(EqObjPtr foo) 99 | { 100 | std::vector der; 101 | for (size_t i = 0; i < args.size(); ++i) 102 | { 103 | Eqo::EqObjPtr y = args[i]->Derivative(foo); 104 | // clean up and use const references 105 | EqObjPtr x; 106 | if (UserFuncMap[name][i].second) 107 | { 108 | x = UserFuncMap[name][i].second; 109 | } 110 | else 111 | { 112 | x = con(0); 113 | } 114 | // substitute in all of our arguments 115 | for (size_t j = 0; j < args.size(); ++j) 116 | { 117 | const std::string &var = UserFuncMap[name][j].first; 118 | x = x->subst(var, args[j]); 119 | } 120 | // Bring this test out of the for loop 121 | if (y->isZero()) // don't want redundant ddx = 1 122 | { 123 | x = con(0); // chain rule 124 | } 125 | else if (!y->isOne()) 126 | { 127 | x = x * y; 128 | } 129 | der.push_back(x); 130 | } 131 | if (der.size() == 1) 132 | return der[0]; 133 | else 134 | return EqObjPtr(new Add(der)); 135 | } 136 | 137 | EqObjPtr UserFunc::Simplify() 138 | { 139 | std::vector vals; 140 | vals.reserve(args.size()); 141 | for (size_t i = 0; i < args.size(); ++i) 142 | { 143 | vals.push_back(args[i]->Simplify()); 144 | } 145 | return (EqObjPtr(new UserFunc(name, vals))); 146 | } 147 | 148 | bool UserFunc::isZero() 149 | { 150 | return false; 151 | } 152 | 153 | bool UserFunc::isOne() 154 | { 155 | return false; 156 | } 157 | 158 | EqObjPtr UserFunc::clone() 159 | { 160 | const size_t len = args.size(); 161 | std::vector tmp(len); 162 | for (size_t i = 0; i < len; ++i) 163 | { 164 | tmp[i] = args[i]->clone(); 165 | } 166 | EquationObject *n = new UserFunc(name, tmp); 167 | return EqObjPtr(n); 168 | } 169 | 170 | EqObjPtr UserFunc::getScale() 171 | { 172 | return EqObjPtr(new Constant(1.0)); 173 | } 174 | 175 | EqObjPtr UserFunc::getUnscaledValue() 176 | { 177 | return EqObjPtr(new UserFunc(name, args)); 178 | } 179 | 180 | double UserFunc::getSign() 181 | { 182 | return 1.0; 183 | } 184 | 185 | EqObjPtr UserFunc::getUnsignedValue() 186 | { 187 | return EqObjPtr(new UserFunc(name, args)); 188 | } 189 | 190 | EqObjPtr UserFunc::CombineAdd(std::vector y) 191 | { 192 | if (y.empty()) 193 | return (EqObjPtr(new UserFunc(name, args))); 194 | 195 | y.push_back(EqObjPtr(new UserFunc(name, args))); 196 | 197 | if (y.size() == 1) 198 | return y[0]; 199 | else 200 | return (EqObjPtr(new Add(y))); 201 | } 202 | 203 | EqObjPtr UserFunc::CombineProduct(std::vector y) 204 | { 205 | if (y.empty()) 206 | return EqObjPtr(new UserFunc(name, args)); 207 | 208 | y.push_back(EqObjPtr(new UserFunc(name, args))); 209 | 210 | if (y.size() == 1) 211 | return y[0]; 212 | else 213 | return (EqObjPtr(new Product(y))); 214 | } 215 | 216 | EqObjPtr UserFunc::expand() 217 | { 218 | const size_t len = args.size(); 219 | 220 | std::vector tmp(len); 221 | for (size_t i = 0; i < len; ++i) 222 | { 223 | tmp[i] = args[i]->expand(); 224 | } 225 | EquationObject *n = new UserFunc(name, tmp); 226 | return EqObjPtr(n); 227 | } 228 | 229 | std::set UserFunc::getReferencedType(Eqo::EqObjType rt) 230 | { 231 | return UniteReferencedType(rt, args); 232 | } 233 | 234 | }// end namespace 235 | 236 | -------------------------------------------------------------------------------- /src/engine/UserFunc.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef USER_FUNC_HH 8 | #define USER_FUNC_HH 9 | #include "EquationObject.hh" 10 | #include "SymdiffImport.hh" 11 | #include 12 | #include 13 | #include 14 | #include 15 | namespace Eqo { 16 | // first arg, simple variable, second arg, is the diff 17 | typedef std::pair UserDiffInfo; 18 | typedef std::vector UserDiffInfoVec; 19 | 20 | void DLL_PROTECTED SetUserFuncDiffs(std::string, UserDiffInfoVec &); 21 | void DLL_PROTECTED CreateUserFunc(std::string, size_t); 22 | 23 | extern std::map UserFuncMap; 24 | 25 | class UserFunc : public EquationObject { 26 | public: 27 | UserFunc(std::string, std::vector &); 28 | 29 | std::string getName() const 30 | { 31 | return name; 32 | } 33 | 34 | EqObjPtr Derivative(EqObjPtr); 35 | EqObjPtr Simplify(); 36 | 37 | EqObjPtr CombineProduct(std::vector); 38 | EqObjPtr CombineAdd(std::vector); 39 | 40 | bool isZero(); 41 | bool isOne(); 42 | 43 | EqObjPtr getScale(); 44 | EqObjPtr getUnscaledValue(); 45 | 46 | double getSign(); 47 | EqObjPtr getUnsignedValue(); 48 | 49 | EqObjPtr clone(); 50 | EqObjPtr subst(const std::string &, EqObjPtr); 51 | 52 | EqObjPtr expand(); 53 | 54 | std::vector getArgs() 55 | { 56 | return createArgs(args); 57 | } 58 | /// Maybe this should be configurable 59 | bool hasReciprocal() {return false;} 60 | EqObjPtr getReciprocal(); 61 | 62 | std::set getReferencedType(Eqo::EqObjType rt); 63 | private: 64 | std::string createStringValue() const; 65 | 66 | UserFunc(const UserFunc &); 67 | UserFunc operator=(const UserFunc &); 68 | 69 | std::string name; // name of this function (must not be in any other variable table) 70 | std::vector args; // number of arguments if initialized this way 71 | }; 72 | } 73 | #endif 74 | -------------------------------------------------------------------------------- /src/engine/Utility.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "Utility.hh" 8 | #include "EquationObject.hh" 9 | 10 | #include 11 | 12 | namespace Eqo { 13 | namespace { 14 | //// order by CONST_OBJ, the VARIABLE_OBJ, then everything else see enum 15 | struct EqVecCompare 16 | { 17 | bool operator()(EqObjPtr x, EqObjPtr y) 18 | { 19 | const EqObjType xtype = x->getType(); 20 | const EqObjType ytype = y->getType(); 21 | 22 | bool ret = false; 23 | 24 | if (xtype < ytype) 25 | { 26 | ret = true; 27 | } 28 | else if (xtype == ytype) 29 | { 30 | const std::string &xstr = x->stringValue(); 31 | const std::string &ystr = y->stringValue(); 32 | 33 | ret = (xstr < ystr); 34 | } 35 | 36 | return ret; 37 | } 38 | }; 39 | 40 | } 41 | /// Sorts in order of constants, variables, then other objects 42 | void SortEqVector(std::vector &v1) 43 | { 44 | std::sort(v1.begin(), v1.end(), EqVecCompare()); 45 | } 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/engine/Utility.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef UTILITY_HH 8 | #define UTILITY_HH 9 | #include 10 | #include 11 | namespace Eqo 12 | { 13 | class EquationObject; 14 | typedef std::shared_ptr EqObjPtr; 15 | } 16 | 17 | namespace Eqo 18 | { 19 | void SortEqVector(std::vector &v1); 20 | } 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /src/engine/Variable.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "Variable.hh" 8 | #include "Functions.hh" 9 | #include 10 | namespace Eqo { 11 | EqObjPtr Variable::getScale() 12 | { 13 | return con(1); 14 | } 15 | 16 | EqObjPtr Variable::getUnscaledValue() 17 | { 18 | return shared_from_this(); 19 | } 20 | 21 | double Variable::getSign() 22 | { 23 | return 1.0; 24 | } 25 | 26 | EqObjPtr Variable::getUnsignedValue() 27 | { 28 | return shared_from_this(); 29 | } 30 | 31 | 32 | Variable::Variable(std::string var) : EquationObject(VARIABLE_OBJ), value(var) 33 | { 34 | } 35 | 36 | std::string Variable::createStringValue() const 37 | { 38 | return value; 39 | } 40 | 41 | EqObjPtr Variable::Derivative(EqObjPtr foo) 42 | { 43 | if (foo->stringValue() == value) 44 | return con(1.0); 45 | else 46 | return con(0.0); 47 | } 48 | 49 | EqObjPtr Variable::Simplify() 50 | { 51 | return shared_from_this(); 52 | } 53 | 54 | /** 55 | * This function may never be called if variables 56 | * are turned into Pow's. 57 | */ 58 | EqObjPtr Variable::CombineProduct(std::vector y) 59 | { 60 | if (y.empty()) 61 | return shared_from_this(); 62 | 63 | y.push_back(shared_from_this()); 64 | return EqObjPtr(new Product(y)); 65 | } 66 | 67 | EqObjPtr Variable::CombineAdd(std::vector y) 68 | { 69 | if (y.empty()) 70 | return EqObjPtr(shared_from_this()); 71 | 72 | y.push_back(shared_from_this()); 73 | return EqObjPtr(new Add(y)); 74 | } 75 | 76 | bool Variable::isZero() 77 | { 78 | return false; 79 | } 80 | 81 | bool Variable::isOne() 82 | { 83 | return false; 84 | } 85 | 86 | EqObjPtr Variable::clone() 87 | { 88 | EquationObject *n = new Variable(value); 89 | return EqObjPtr(n); 90 | } 91 | 92 | EqObjPtr Variable::subst(const std::string &str, EqObjPtr eqo) 93 | { 94 | if (str == this->stringValue()) 95 | return eqo; 96 | else 97 | return shared_from_this(); 98 | } 99 | 100 | EqObjPtr Variable::expand() 101 | { 102 | return shared_from_this(); 103 | } 104 | 105 | EqObjPtr Variable::getReciprocal() 106 | { 107 | assert(false); 108 | return con(0); 109 | } 110 | } 111 | 112 | -------------------------------------------------------------------------------- /src/engine/Variable.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef VARIABLE_HH 8 | #define VARIABLE_HH 9 | #include "EquationObject.hh" 10 | 11 | namespace Eqo { 12 | class Variable : public EquationObject { 13 | public: 14 | const std::string &getVariableName() const { 15 | return value; 16 | } 17 | 18 | std::string getName() const 19 | { 20 | return getVariableName(); 21 | } 22 | 23 | Variable(std::string); 24 | ~Variable() {}; 25 | EqObjPtr Derivative(EqObjPtr); 26 | EqObjPtr Simplify(); 27 | 28 | EqObjPtr CombineProduct(std::vector); 29 | EqObjPtr CombineAdd(std::vector); 30 | 31 | bool isZero(); 32 | bool isOne(); 33 | 34 | EqObjPtr getScale(); 35 | EqObjPtr getUnscaledValue(); 36 | 37 | double getSign(); 38 | EqObjPtr getUnsignedValue(); 39 | 40 | EqObjPtr clone(); 41 | EqObjPtr subst(const std::string &, EqObjPtr); 42 | 43 | EqObjPtr expand(); 44 | 45 | std::vector getArgs() { 46 | return std::vector(); 47 | } 48 | 49 | bool hasReciprocal() {return false;} 50 | EqObjPtr getReciprocal(); 51 | std::set getReferencedType(Eqo::EqObjType rt) { 52 | return CreateSetIfThisType(rt); 53 | } 54 | 55 | private: 56 | std::string createStringValue() const; 57 | 58 | Variable(const Variable &); 59 | Variable operator=(const Variable &); 60 | 61 | const std::string value; 62 | }; 63 | } 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /src/engine/gcd.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | // actually do it 11 | // large must be first 12 | int gcd_do(int large, int small) 13 | { 14 | cout << "gcd " << large << " " << small << endl; 15 | int rem = large % small; 16 | 17 | if (rem == 0) 18 | { 19 | return small; 20 | } 21 | else if ((rem == 1) && (small > 10000)) 22 | { 23 | // precision of 1 part in 5 24 | return small; 25 | } 26 | 27 | return gcd_do(small, rem); 28 | } 29 | 30 | // for now expect positive ints 31 | // doesn't handle zeros 32 | int gcd(int x, int y) 33 | { 34 | if (x == y) 35 | { 36 | return x; 37 | } 38 | 39 | x = abs(x); 40 | y = abs(y); 41 | if (x < y) 42 | { 43 | return gcd_do(y,x); 44 | } 45 | 46 | return gcd_do(x,y); 47 | 48 | } 49 | int main() 50 | { 51 | // Binary euclid algorithm is probably faster 52 | // Make sure don't surpass any 32 bit limits 53 | int x = 1333333333; 54 | int y = 1000000000; 55 | int g = gcd(x,y); 56 | cout << g << endl; 57 | 58 | // in integer arithmetic we filter out any pesky remainders 59 | cout << "x / y = " << x/g << " / " << y/g << endl; 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/engine/mcModel.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "mcModel.hh" 8 | #include "mcModelCompiler.hh" 9 | #include "Functions.hh" 10 | #include "Context.hh" 11 | 12 | namespace Eqo { 13 | EqObjPtr Model::getScale() 14 | { 15 | return con(1.0); 16 | } 17 | 18 | EqObjPtr Model::getUnscaledValue() 19 | { 20 | return shared_from_this(); 21 | } 22 | 23 | double Model::getSign() 24 | { 25 | return 1.0; 26 | } 27 | 28 | EqObjPtr Model::getUnsignedValue() 29 | { 30 | return shared_from_this(); 31 | } 32 | 33 | EqObjPtr Model::expand() 34 | { 35 | return shared_from_this(); 36 | } 37 | 38 | EqObjPtr Model::clone() 39 | { 40 | return mod(value); 41 | } 42 | 43 | EqObjPtr Model::subst(const std::string &str, EqObjPtr eqo) 44 | { 45 | if (str == this->stringValue()) 46 | { 47 | //// TODO: how does this work 48 | return eqo->clone(); 49 | } 50 | else 51 | { 52 | return shared_from_this(); 53 | } 54 | } 55 | 56 | Model::Model(std::string var) : EquationObject(MODEL_OBJ), value(var) 57 | { 58 | } 59 | 60 | std::string Model::createStringValue() const 61 | { 62 | return value; 63 | } 64 | 65 | extern Eqo::EqObjPtr DLL_PROTECTED default_derivative_rule(Eqo::EqObjPtr self, Eqo::EqObjPtr foo) 66 | { 67 | Context &context = Context::GetInstance(); 68 | const std::string &value = self->stringValue(); 69 | 70 | if (foo->stringValue() == value) 71 | { 72 | return con(1.0); 73 | } 74 | 75 | EqObjPtr dval; 76 | 77 | if (context.IsInModelList(value)) 78 | { 79 | EqObjPtr eq = context.FindInModelList(value); 80 | if (eq) 81 | { 82 | dval = eq->Derivative(foo)->Simplify(); 83 | } 84 | } 85 | 86 | EqObjPtr ret; 87 | 88 | { 89 | std::string bar(value); 90 | bar += "__"; 91 | bar += foo->stringValue(); 92 | 93 | if (!context.IsInModelList(bar)) 94 | { 95 | context.DefineModel(bar, dval); 96 | } 97 | else 98 | { 99 | /// model already defined elsewhere, should we redefine it 100 | context.DefineModel(bar, dval); 101 | } 102 | ret = mod(bar); 103 | } 104 | 105 | return ret; 106 | } 107 | 108 | EqObjPtr Model::Derivative(EqObjPtr foo) 109 | { 110 | Context &context = Context::GetInstance(); 111 | return context.EvaluateModelDerivative(shared_from_this(), foo); 112 | } 113 | 114 | EqObjPtr Model::Simplify() 115 | { 116 | return shared_from_this(); 117 | } 118 | 119 | /** 120 | * This function may never be called if variables 121 | * are turned into Pow's. 122 | */ 123 | EqObjPtr Model::CombineProduct(std::vector y) 124 | { 125 | if (y.empty()) 126 | return shared_from_this(); 127 | 128 | y.push_back(shared_from_this()); 129 | return EqObjPtr(new Product(y)); 130 | } 131 | 132 | EqObjPtr Model::CombineAdd(std::vector y) 133 | { 134 | if (y.empty()) 135 | return shared_from_this(); 136 | 137 | y.push_back(shared_from_this()); 138 | return EqObjPtr(new Add(y)); 139 | } 140 | 141 | bool Model::isZero() 142 | { 143 | return false; 144 | } 145 | 146 | bool Model::isOne() 147 | { 148 | return false; 149 | } 150 | 151 | EqObjPtr Model::getReciprocal() 152 | { 153 | assert(false); 154 | return con(0); 155 | } 156 | } 157 | 158 | -------------------------------------------------------------------------------- /src/engine/mcModel.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef MC_MODEL_HH 8 | #define MC_MODEL_HH 9 | #include "EquationObject.hh" 10 | namespace Eqo { 11 | class Model : public EquationObject { 12 | public: 13 | 14 | Model(std::string); 15 | ~Model() {}; 16 | EqObjPtr Derivative(EqObjPtr); 17 | EqObjPtr Simplify(); 18 | 19 | EqObjPtr CombineProduct(std::vector); 20 | EqObjPtr CombineAdd(std::vector); 21 | 22 | bool isZero(); 23 | bool isOne(); 24 | 25 | EqObjPtr getScale(); 26 | EqObjPtr getUnscaledValue(); 27 | 28 | double getSign(); 29 | EqObjPtr getUnsignedValue(); 30 | 31 | EqObjPtr clone(); 32 | EqObjPtr subst(const std::string &, EqObjPtr); 33 | 34 | EqObjPtr expand(); 35 | 36 | std::vector getArgs() { 37 | return std::vector(); 38 | } 39 | 40 | bool hasReciprocal() {return false;} 41 | EqObjPtr getReciprocal(); 42 | 43 | std::set getReferencedType(Eqo::EqObjType rt) { 44 | return CreateSetIfThisType(rt); 45 | } 46 | 47 | std::string getName() const 48 | { 49 | return value; 50 | } 51 | 52 | private: 53 | std::string createStringValue() const; 54 | 55 | Model(const Model &); 56 | Model operator=(const Model &); 57 | 58 | //Models are stored elsewhere 59 | const std::string value; 60 | }; 61 | 62 | inline EqObjPtr mod(const std::string &x) 63 | { 64 | return EqObjPtr(new Model(std::string(x))); 65 | } 66 | } 67 | #endif 68 | -------------------------------------------------------------------------------- /src/engine/mcModelCompiler.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "mcModelCompiler.hh" 8 | #include "Functions.hh" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "mcModel.hh" 16 | #include "Context.hh" 17 | 18 | Eqo::EqObjPtr ClearModel(const std::string &s) 19 | { 20 | Context &context = Context::GetInstance(); 21 | context.ClearModel(s); 22 | return Eqo::con(0.0); 23 | } 24 | 25 | Eqo::EqObjPtr DeclareModel(const std::string &s) 26 | { 27 | Context &context = Context::GetInstance(); 28 | context.DeclareModel(s); 29 | return Eqo::mod(s); 30 | } 31 | 32 | Eqo::EqObjPtr DefineModel(const std::string &s, Eqo::EqObjPtr e) 33 | { 34 | Context &context = Context::GetInstance(); 35 | context.DefineModel(s, e); 36 | return Eqo::mod(s); 37 | } 38 | 39 | /// Does not error out. For this use top level command 40 | Eqo::EqObjPtr GetModelValue(const std::string &s) 41 | { 42 | Eqo::EqObjPtr ret = Eqo::var("UNDEFINED"); 43 | 44 | Context &context = Context::GetInstance(); 45 | if (context.IsInModelList(s)) 46 | { 47 | Eqo::EqObjPtr x = context.FindInModelList(s); 48 | if (x) 49 | { 50 | ret = x; 51 | } 52 | } 53 | 54 | return ret; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/engine/mcModelCompiler.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef MC_MODEL_COMPILER_HH 8 | #define MC_MODEL_COMPILER_HH 9 | #include "EquationObject.hh" 10 | #include 11 | Eqo::EqObjPtr ClearModel(const std::string &); 12 | 13 | Eqo::EqObjPtr DeclareModel(const std::string &); 14 | 15 | Eqo::EqObjPtr GetModelValue(const std::string &); 16 | 17 | Eqo::EqObjPtr DefineModel(const std::string &, Eqo::EqObjPtr); 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /src/engine/mcScanner.l: -------------------------------------------------------------------------------- 1 | %{ 2 | /*** 3 | Copyright 2012 DEVSIM LLC 4 | 5 | SPDX-License-Identifier: Apache-2.0 6 | ***/ 7 | 8 | // must include test.hh first 9 | // to use struct instead of union. 10 | #include 11 | #include "mcTest.hh" 12 | #include "mcParser.hh" 13 | #include "EngineAPI.hh" 14 | // For isatty 15 | #ifdef _WIN32 16 | #include 17 | #define YY_NO_UNISTD_H 18 | #else 19 | #include 20 | #endif 21 | #include "EquationObject.hh" 22 | #include "UserFunc.hh" 23 | //#include "FunctionTables.hh" 24 | #include "Context.hh" 25 | #define YY_NO_UNPUT 26 | // remove clang compiler warning about deprecated keyword 27 | #define register 28 | %} 29 | %option noyywrap 30 | %option nounput 31 | /*%option stack*/ 32 | 33 | integer [0-9]+ 34 | float1 [0-9]*\.[0-9]+ 35 | float2 [0-9]+\.[0-9]* 36 | float3 [0-9]+\.?[0-9]*[eE][+-]?[0-9]+ 37 | 38 | /* Unicode goodness from http://osdir.com/ml/lex.flex.general/2004-03/msg00023.html */ 39 | U80 [\200-\277] 40 | U81 [\300-\337]{U80} 41 | U82 [\340-\357]{U80}{2} 42 | U83 [\360-\367]{U80}{3} 43 | U84 [\370-\373]{U80}{4} 44 | U85 [\374-\375]{U80}{5} 45 | UTF8 {U81}|{U82}|{U83}|{U84}|{U85} 46 | 47 | 48 | %% 49 | [ \t\r\n]* ; 50 | 51 | [\n\;] {return EOL;} 52 | 53 | {float1}|{float2}|{float3} {mclval.dval = atof(yytext); return FLOAT;} 54 | 55 | {integer} {mclval.dval = atoi(yytext); return INT;} 56 | 57 | subst {mclval.str=yytext; return SUBST;} 58 | 59 | define {mclval.str=yytext; return DEFUSERFUNC;} 60 | 61 | declare {mclval.str=yytext; return DECUSERFUNC;} 62 | 63 | declare_model {mclval.str=yytext; return DECMODEL;} 64 | 65 | model_value {mclval.str=yytext; return MODEL_VALUE_CMD;/*Should this return a value, or should we have a top level command test*/} 66 | 67 | define_model {mclval.str=yytext; return DEFMODEL;} 68 | 69 | clear_model {mclval.str=yytext; return CLEARMODEL;} 70 | 71 | clear {mclval.str=yytext; return CLEARUSERFUNC;} 72 | 73 | \$_ {mclval.str = yytext; return MACRO;} 74 | 75 | 76 | \< {mclval.str=yytext; return LT;} 77 | \<= {mclval.str=yytext; return LTE;} 78 | \> {mclval.str=yytext; return GT;} 79 | \>= {mclval.str=yytext; return GTE;} 80 | == {mclval.str=yytext; return EQ;} 81 | != {mclval.str=yytext; return NEQ;} 82 | ! {mclval.str=yytext; return NOT;} 83 | && {mclval.str=yytext; return AND;} 84 | \|\| {mclval.str=yytext; return OR;} 85 | 86 | \$([A-Za-z]|{UTF8})([A-Za-z_0-9]|{UTF8})* { 87 | mclval.str = yytext; return MACRO; 88 | } 89 | if { 90 | mclval.str = yytext; 91 | return IF; 92 | } 93 | 94 | ifelse { 95 | mclval.str = yytext; 96 | return IFELSE; 97 | } 98 | 99 | ([A-Za-z]|{UTF8})([A-Za-z_0-9:@.]|{UTF8})* { 100 | mclval.str = yytext; 101 | 102 | if (EngineAPI::isUnaryFunction(mclval.str)) 103 | return UNARYFUNC; 104 | else if (EngineAPI::isBinaryFunction(mclval.str)) 105 | return BINARYFUNC; 106 | else if (Eqo::UserFuncMap.count(mclval.str)) 107 | return USERFUNC; 108 | else if (Context::GetInstance().IsInModelList(mclval.str)) 109 | return MODELNAME; 110 | else 111 | return VAR; 112 | } 113 | 114 | . {return yytext[0];} 115 | %% 116 | 117 | 118 | -------------------------------------------------------------------------------- /src/engine/mcTest.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef MC_TEST_HH 8 | #define MC_TEST_HH 9 | 10 | #include 11 | #include 12 | 13 | #include "EquationObject.hh" 14 | 15 | typedef struct { 16 | std::string str; 17 | double dval; 18 | Eqo::EqObjPtr eqptr; 19 | std::vector vararg; // variable number of arguments 20 | std::vector varobj; // variable number of objects 21 | } myyystype; 22 | 23 | #define YYSTYPE myyystype 24 | 25 | int mcerror(const char *); 26 | int mclex(); 27 | int mcparse(); 28 | void mcrestart(FILE *); 29 | extern FILE * mcin; 30 | void prompt(); 31 | // flex stuff to parse string 32 | #define yyconst const 33 | typedef struct yy_buffer_state *YY_BUFFER_STATE; 34 | YY_BUFFER_STATE mc_scan_string( yyconst char *yy_str ); 35 | void mc_delete_buffer( YY_BUFFER_STATE b ); 36 | 37 | Eqo::EqObjPtr CreateErrorMessage(const Eqo::EqObjPtr &, const std::string &, const Eqo::EqObjPtr &, const std::string &); 38 | Eqo::EqObjPtr CreateErrorMessageWithOtherType(const Eqo::EqObjPtr &, const std::string &, const std::string &, const std::string &); 39 | Eqo::EqObjPtr CreateBuiltInError(const std::string &); 40 | Eqo::EqObjPtr CreateParenthesisError(const std::string &, const std::string &, const std::string &); 41 | 42 | Eqo::EqObjPtr processUnaryFunction(const std::string &, const std::vector &); 43 | Eqo::EqObjPtr processBinaryFunction(const std::string &, const std::vector &); 44 | Eqo::EqObjPtr processSubstFunction(const std::string &, const std::vector &); 45 | Eqo::EqObjPtr processClearFunction(); 46 | 47 | Eqo::EqObjPtr DefineMacro(const std::string &, Eqo::EqObjPtr); 48 | Eqo::EqObjPtr GetMacro(const std::string &s); 49 | 50 | 51 | 52 | Eqo::EqObjPtr DeclareUserFunction(const std::string &, const std::vector &); 53 | Eqo::EqObjPtr DefineUserFunction(const std::string &, std::vector, std::vector); 54 | Eqo::EqObjPtr ReDefineUserFunction(const std::string &, std::vector, std::vector); 55 | Eqo::EqObjPtr EvaluateUserFunction(const std::string &, std::vector); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/engine/parseexpr.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "parseexpr.hh" 8 | #include "mcTest.hh" 9 | #include "Functions.hh" 10 | #include 11 | namespace EvalExpr { 12 | static error_t *lerrors; 13 | 14 | void clearVariableMap() { 15 | Eqo::variableMap.clear(); 16 | } 17 | 18 | /// Returns Equation Object containing the result of calculation, as well as any errors 19 | /// error list should be empty on entry 20 | Eqo::EqObjPtr evaluateExpression(const std::string &x, error_t &errors) 21 | { 22 | std::string y; 23 | y.reserve(x.size() + 1); 24 | y += x; 25 | y += ";"; 26 | lerrors = &errors; 27 | YY_BUFFER_STATE yyb = nullptr; 28 | // clearVariableMap(); 29 | yyb = mc_scan_string(y.c_str()); 30 | int retval = 0; 31 | retval = mcparse(); 32 | if (yyb != nullptr) 33 | { 34 | mc_delete_buffer(yyb); 35 | } 36 | Eqo::EqObjPtr result; 37 | if (retval == 0) 38 | { 39 | result = Eqo::variableMap["$_"]; 40 | } 41 | else 42 | { 43 | result = Eqo::con(0.0); 44 | } 45 | lerrors=nullptr; 46 | return result; 47 | } 48 | } 49 | 50 | // Not in any namespace 51 | int mcerror(const char *msg) { 52 | EvalExpr::lerrors->push_back(std::string(msg)); 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/engine/parseexpr.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef PARSEEXPR_HH 8 | #define PARSEEXPR_HH 9 | #include "SymdiffImport.hh" 10 | #include 11 | #include 12 | #include 13 | 14 | namespace Eqo { 15 | class EquationObject; 16 | typedef std::shared_ptr EqObjPtr; 17 | }; 18 | 19 | namespace EvalExpr { 20 | typedef std::list error_t; 21 | 22 | /// We are using the parser for a new purpose 23 | void clearVariableMap(); 24 | 25 | Eqo::EqObjPtr DLL_PROTECTED evaluateExpression(const std::string &, error_t &); 26 | } 27 | 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /src/pycomp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | INCLUDE_DIRECTORIES ( 3 | ../engine 4 | ) 5 | 6 | SET (PYTHON_SRCS 7 | PythonSymdiffCommands.cc 8 | ) 9 | 10 | #SET(PYVERSION symdiff_py2) 11 | 12 | FUNCTION(build_python_version arg1) 13 | ADD_LIBRARY (${arg1} SHARED ${PYTHON_SRCS}) 14 | TARGET_LINK_LIBRARIES (${arg1} symdiff_dynamic) 15 | IF(WIN32) 16 | SET_TARGET_PROPERTIES(${arg1} PROPERTIES PREFIX "" SUFFIX ".pyd" OUTPUT_NAME "${arg1}") 17 | ELSE(WIN32) 18 | SET_TARGET_PROPERTIES(${arg1} PROPERTIES PREFIX "" SUFFIX ".so" OUTPUT_NAME "${arg1}") 19 | ENDIF(WIN32) 20 | 21 | ADD_CUSTOM_COMMAND(TARGET ${arg1} 22 | POST_BUILD 23 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_LIBRARY_DIR}/symdiff 24 | COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_LIBRARY_DIR}/symdiff 25 | ) 26 | 27 | IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") 28 | SET_TARGET_PROPERTIES(${arg1} PROPERTIES INSTALL_RPATH "\$ORIGIN/") 29 | ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") 30 | IF (APPLE) 31 | #SET_TARGET_PROPERTIES(${arg1} PROPERTIES INSTALL_RPATH "@loader_path/") 32 | SET_TARGET_PROPERTIES(${arg1} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -flat_namespace") 33 | ENDIF (APPLE) 34 | ENDFUNCTION(build_python_version arg1) 35 | 36 | IF (PYTHON3) 37 | build_python_version(symdiff_py3) 38 | TARGET_INCLUDE_DIRECTORIES (symdiff_py3 PUBLIC ${PYTHON3_INCLUDE}) 39 | IF(WIN32) 40 | TARGET_LINK_LIBRARIES (symdiff_py3 ${PYTHON3_ARCHIVE}) 41 | ELSE(WIN32) 42 | # macOS and Linux do not need to dynamically link against python 43 | ENDIF(WIN32) 44 | target_compile_definitions(symdiff_py3 PRIVATE -DPy_LIMITED_API=0x03030000) 45 | #TARGET_LINK_LIBRARIES (symdiff_py3 symdiff ${PYTHON3_ARCHIVE}) 46 | ENDIF (PYTHON3) 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/tclcomp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | INCLUDE_DIRECTORIES ( 3 | ../engine 4 | ${TCL_INCLUDE} 5 | ) 6 | 7 | SET (TCL_SOURCES 8 | TclCommands.cc 9 | TclSymdiffCommands.cc 10 | tclcomp.cc 11 | ) 12 | 13 | IF(TCLMAIN) 14 | ADD_LIBRARY (symdiff_tcl SHARED ${TCL_SOURCES}) 15 | TARGET_LINK_LIBRARIES (symdiff_tcl ${TCL_ARCHIVE} symdiff_dynamic) 16 | #TARGET_LINK_LIBRARIES (symdiff_tcl symdiff ${TCL_ARCHIVE}) 17 | #TARGET_LINK_LIBRARIES (symdiff_tcl $ ${TCL_ARCHIVE}) 18 | SET_TARGET_PROPERTIES(symdiff_tcl PROPERTIES OUTPUT_NAME "symdifftcl") 19 | 20 | ADD_CUSTOM_COMMAND(TARGET symdiff_tcl 21 | POST_BUILD 22 | WORKING_DIRECTORY ${PROJECT_LIBRARY_DIR} 23 | COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_LIBRARY_DIR} 24 | COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_LIBRARY_DIR}/ 25 | COMMAND ${TCL_BIN} ${PROJECT_SCRIPTS_DIR}/mkindex.tcl 26 | ) 27 | 28 | IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") 29 | SET_TARGET_PROPERTIES(symdiff_tcl PROPERTIES INSTALL_RPATH "\$ORIGIN/") 30 | ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") 31 | IF (APPLE) 32 | #SET_TARGET_PROPERTIES(symdiff_tcl PROPERTIES INSTALL_RPATH "@loader_path/") 33 | SET_TARGET_PROPERTIES(symdiff_tcl PROPERTIES LINK_FLAGS " -flat_namespace") 34 | ENDIF (APPLE) 35 | ENDIF(TCLMAIN) 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/tclcomp/TclCommands.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include "TclCommands.hh" 8 | 9 | #include "TclSymdiffCommands.hh" 10 | 11 | #include 12 | #include 13 | 14 | namespace dsTcl { 15 | 16 | int 17 | CmdDispatch(ClientData clientData, Tcl_Interp *interp, 18 | int objc, Tcl_Obj *CONST objv[]) 19 | { 20 | int myerror = TCL_OK; 21 | 22 | 23 | try 24 | { 25 | tclcmd cmd = reinterpret_cast(clientData)->GetCommand(); 26 | myerror = cmd(clientData, interp, objc, objv); 27 | } 28 | #if 0 29 | catch (const dsException &x) 30 | { 31 | myerror = TCL_ERROR; 32 | Tcl_SetResult(interp, const_cast(x.what()), TCL_VOLATILE); 33 | } 34 | #endif 35 | catch (std::bad_alloc &) 36 | { 37 | myerror = TCL_ERROR; 38 | Tcl_SetResult(interp, const_cast("OUT OF MEMORY"), TCL_VOLATILE); 39 | } 40 | 41 | return myerror; 42 | } 43 | 44 | void AddCommands(Tcl_Interp *interp, Commands *clist) 45 | { 46 | for ( ; (clist->name) != nullptr; ++clist) 47 | { 48 | void *cdata = dsClientData::CreateData(clist->name, clist->command); 49 | 50 | Tcl_CreateObjCommand(interp, clist->name, CmdDispatch, 51 | (ClientData) cdata, (Tcl_CmdDeleteProc *) dsClientData::DeleteData); 52 | } 53 | } 54 | 55 | int 56 | Commands_Init(Tcl_Interp *interp) { 57 | AddCommands(interp, TclSymdiffCommands); 58 | return TCL_OK; 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/tclcomp/TclCommands.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef TCLCOMMANDS_HH 8 | #define TCLCOMMANDS_HH 9 | #include 10 | namespace dsTcl { 11 | typedef int (*tclcmd) (ClientData clientData, Tcl_Interp *interp, 12 | int objc, Tcl_Obj *CONST objv[]); 13 | 14 | struct Commands 15 | { 16 | const char *name; 17 | tclcmd command; 18 | }; 19 | 20 | int Commands_Init(Tcl_Interp *interp); 21 | 22 | class dsClientData { 23 | private: 24 | dsClientData(const char *name, tclcmd impl) : command_name_(name), command_impl_(impl) 25 | { 26 | } 27 | 28 | public: 29 | static void *CreateData(const char *name, tclcmd impl) 30 | { 31 | 32 | void *handle; 33 | handle = new dsClientData(name, impl); 34 | return handle; 35 | } 36 | 37 | static void DeleteData(void *handle) 38 | { 39 | delete reinterpret_cast(handle); 40 | } 41 | 42 | static const char *GetCommandName(void *handle) 43 | { 44 | return reinterpret_cast(handle)->command_name_; 45 | } 46 | 47 | tclcmd GetCommand() { 48 | return command_impl_; 49 | } 50 | 51 | private: 52 | dsClientData(); 53 | dsClientData(const dsClientData &); 54 | dsClientData &operator=(const dsClientData &); 55 | 56 | 57 | ~dsClientData() 58 | { 59 | } 60 | 61 | const char *command_name_; 62 | tclcmd command_impl_; 63 | }; 64 | } 65 | #endif 66 | -------------------------------------------------------------------------------- /src/tclcomp/TclSymdiffCommands.hh: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #ifndef SYMDIFF_COMMANDS_HH 8 | #define SYMDIFF_COMMANDS_HH 9 | #include "TclCommands.hh" 10 | namespace dsTcl { 11 | extern Commands TclSymdiffCommands[]; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/tclcomp/tclcomp.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright 2012 DEVSIM LLC 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | ***/ 6 | 7 | #include 8 | #include "SymdiffImport.hh" 9 | #include "TclCommands.hh" 10 | 11 | #if 0 12 | int main(int argc, char * argv[]) 13 | { 14 | Tcl_Main(argc, argv, Tcl_AppInit); 15 | 16 | } 17 | #endif 18 | extern "C" { 19 | int DLL_PUBLIC 20 | Symdifftcl_Init(Tcl_Interp *interp) 21 | { 22 | if (Tcl_InitStubs(interp, TCL_VERSION, 0) == nullptr) { 23 | return TCL_ERROR; 24 | } 25 | if (Tcl_PkgProvide(interp, "symdifftcl", "1.0") == TCL_ERROR) { 26 | return TCL_ERROR; 27 | } 28 | dsTcl::Commands_Init(interp); 29 | return TCL_OK; 30 | } 31 | 32 | DLL_PUBLIC Tcl_PackageInitProc *Symdifftcl_SafeInit = Symdifftcl_Init; 33 | DLL_PUBLIC Tcl_PackageUnloadProc *Symdifftcl_SafeUnload = nullptr; 34 | DLL_PUBLIC Tcl_PackageUnloadProc *Symdifftcl_Unload = nullptr; 35 | 36 | 37 | } 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /testing/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | INCLUDE_DIRECTORIES ( 2 | ) 3 | 4 | # pass linker so order important 5 | 6 | IF (WIN32) 7 | SET (GOLDENDIR ${PROJECT_SOURCE_DIR}/goldenresults/unix) 8 | SET (RUNDIR ${PROJECT_SOURCE_DIR}/testing) 9 | SET (TCLCOMP ${PROJECT_BIN_DIR}/symdiff_tcl.bat) 10 | SET (PYTHON3COMP ${PROJECT_BIN_DIR}/symdiff_py3.bat) 11 | SET (RUNDIFFTEST ${PYTHON3COMP} ${PROJECT_SOURCE_DIR}/testing/rundifftest.py) 12 | ELSE (WIN32) 13 | SET (GOLDENDIR ${PROJECT_SOURCE_DIR}/goldenresults/unix) 14 | SET (RUNDIR ${PROJECT_SOURCE_DIR}/testing) 15 | SET (TCLCOMP ${PROJECT_BIN_DIR}/symdiff_tcl) 16 | SET (PYTHON3COMP ${PROJECT_BIN_DIR}/symdiff_py3) 17 | SET (RUNDIFFTEST ${PYTHON3COMP} ${PROJECT_SOURCE_DIR}/testing/rundifftest.py) 18 | ENDIF (WIN32) 19 | 20 | ENABLE_TESTING() 21 | 22 | IF(TCLMAIN) 23 | SET (TCLTESTS parsetest_tcl symdiff1 symdiff2 symdiff3 symdiff4 arrhenius_tcl units table) 24 | FOREACH(I ${TCLTESTS}) 25 | ADD_TEST("${I}" ${RUNDIFFTEST} --testexe ${TCLCOMP} --goldendir ${GOLDENDIR} --output ${I}.out --working ${RUNDIR} --args ${RUNDIR}/${I}.tcl) 26 | ENDFOREACH(I) 27 | ENDIF(TCLMAIN) 28 | 29 | SET (EXAMPLES_DIR ${PROJECT_SOURCE_DIR}/examples) 30 | SET (PYTHONTESTS parsetest deftest arrhenius modellist1 ordered remove1 subexpression1 undefined1 utf8 models1 table) 31 | IF (PYTHON3) 32 | FOREACH(I ${PYTHONTESTS}) 33 | ADD_TEST("${I}_py3" ${RUNDIFFTEST} --testexe ${PYTHON3COMP} --goldendir ${GOLDENDIR} --output ${I}_py3.out --working ${EXAMPLES_DIR} --args ${EXAMPLES_DIR}/${I}.py) 34 | ENDFOREACH(I) 35 | ENDIF (PYTHON3) 36 | 37 | -------------------------------------------------------------------------------- /testing/arrhenius_tcl.tcl: -------------------------------------------------------------------------------- 1 | package require symdifftcl 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff {define_model(arrhenius, simplify(Cf * pow(T, Etar) * exp(-Ea/T)))} 6 | symdiff {define_model(KC1 , simplify(A3 * R * T * exp((A1 * (-pow(T,(-1)) + pow(A2,(-1))) * pow(R,(-1))))))} 7 | symdiff {define_model(kb_model , simplify(arrhenius / KC1))} 8 | symdiff {declare_model(fprod)} 9 | 10 | symdiff {define_model(rprod , simplify(H * CN * AR))} 11 | symdiff {define_model(omega_dot_H , simplify((vr_H - vf_H) * (arrhenius * fprod - kb_model * rprod)))} 12 | symdiff {diff(omega_dot_H, T)} 13 | symdiff {diff(omega_dot_H, H)} 14 | symdiff {diff(omega_dot_H, HCN)} 15 | symdiff {diff(omega_dot_H, AR)} 16 | symdiff {diff(omega_dot_H, CN)} 17 | 18 | subexpression 19 | remove_zeros 20 | set mylist [ordered_list omega_dot_H omega_dot_H__T omega_dot_H__H omega_dot_H__HCN omega_dot_H__AR omega_dot_H__CN] 21 | foreach {i} $mylist { 22 | puts [format "%s, %s" $i [symdiff "model_value($i)"] ] 23 | } 24 | -------------------------------------------------------------------------------- /testing/parsetest_tcl.tcl: -------------------------------------------------------------------------------- 1 | package require symdifftcl 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | proc maptest {myvar} { 6 | puts "" 7 | puts $myvar; 8 | catch {set out [symdiff "$myvar"]} out 9 | puts $out 10 | } 11 | 12 | maptest "a*x" 13 | maptest "simplify(a*a)" 14 | maptest "simplify(pow(x, 0.0))" 15 | maptest "simplify(pow(x, 1.0))" 16 | maptest "simplify(pow(1.0, x))" 17 | maptest "simplify(exp(1.0))" 18 | maptest "simplify(exp(0.0))" 19 | maptest "simplify(exp(log(x)))" 20 | maptest "simplify(log(exp(x)))" 21 | maptest "simplify(log(1.0))" 22 | 23 | maptest "(exp(pow(c,pow(x,pow(c,x)))))" 24 | maptest "diff((exp(pow(c,pow(x,pow(c,x))))),x)" 25 | maptest "simplify(diff((exp(pow(c,pow(x,pow(c,x))))),x))" 26 | maptest "simplify((((((((1 * pow(x,(-1))) * pow(c,x)) + ((log(c) * pow(c,x)) * log(x))) * pow(x,pow(c,x))) * log(c)) * pow(c,pow(x,pow(c,x)))) * exp(pow(c,pow(x,pow(c,x))))))" 27 | 28 | maptest "simplify(a*5*pow(a,-1))" 29 | 30 | maptest "c*c*c*c" 31 | maptest "simplify(c*c*c*c)" 32 | maptest "diff(c*c*x*x,x)" 33 | 34 | maptest "simplify(log(pow(x,y)))" 35 | 36 | maptest "simplify(a*a+a*a*a)" 37 | maptest "simplify(a*a+a*a)" 38 | maptest "simplify(a+a+a*a)" 39 | maptest "simplify(a+a+a+a*a)" 40 | 41 | maptest "simplify(y*pow(x,(-1)) * pow(x,y))" 42 | maptest "simplify(pow(x,(-1)) * pow(x,y)*y)" 43 | maptest "simplify(pow(x,(-1)) * pow(x,y)*x)" 44 | 45 | maptest "unscaledval(2*x)" 46 | maptest "scale(2*x)" 47 | 48 | maptest "a - a" 49 | maptest "a + -a" 50 | maptest "a - b" 51 | 52 | maptest "simplify(a - a)" 53 | maptest "simplify(a + -a)" 54 | maptest "simplify(a - b)" 55 | 56 | maptest "-simplify(a - b)" 57 | maptest "simplify(-simplify(a - b))" 58 | 59 | maptest "(-1*3*4*-3*x)" 60 | maptest "simplify(-1*3*4*-3*x)" 61 | 62 | maptest "-a" 63 | maptest "a++-+a" 64 | maptest "a+*+a" 65 | maptest "diff(-1*3*4*(-3)*x,x)" 66 | maptest "diff(simplify(-1*3*4*(-3)*x),x)" 67 | maptest "diff((-1*3*4*(-3)*x),x)" 68 | 69 | maptest "(a *(-a))" 70 | maptest "(a * -a)" 71 | maptest "(a * (+a))" 72 | maptest "(a * +a)" 73 | 74 | maptest "expand((a)*(c+d))" 75 | maptest "expand((a + b)*(c+d))" 76 | maptest "expand((a+b)*(c+d)*(e+f+g))" 77 | maptest "expand((a-1)*(b+1))" 78 | maptest "expand((a-1)*(a+1))" 79 | 80 | maptest "simplify((a-1)*(a+1)/(a+1))" 81 | maptest "simplify((a-1)*(a+1)^2/(a+1))" 82 | maptest "simplify((a-1)*(a+1)^2/(a+1)^3)" 83 | 84 | maptest "expand((a-b)^-2)" 85 | maptest "expand((a-b)^+2)" 86 | maptest "expand(((a-b)^2)/((a-b)^2))" 87 | maptest "expand((a-b)^2/(a-b)^2)" 88 | maptest "simplify(expand((a-b)^2/(a-b)^2))" 89 | maptest "simplify((a-b)^2/expand((a-b)^2))" 90 | 91 | maptest "unscaledval(-1*10)" 92 | maptest "scale(-1*10)" 93 | maptest "unsignedval(-1*10)" 94 | maptest "sign(-1*10)" 95 | maptest "(a-3)" 96 | maptest "simplify(a-3)" 97 | maptest "2-10" 98 | maptest "unscaledval(-10)" 99 | maptest "scale(-10)" 100 | maptest "sign(-10)" 101 | maptest "unsignedval(-10)" 102 | maptest "simplify(-8*a*x^2 -3*b*c^2)" 103 | 104 | maptest "simplify(x,y)" 105 | maptest "subst(y)" 106 | -------------------------------------------------------------------------------- /testing/rundifftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # ARGUMENTS 4 | # testexe with full path 5 | # goldenresults directory with full path 6 | # name of the test output file to create and to compare with the goldenresults 7 | 8 | import argparse 9 | import os 10 | import subprocess 11 | import difflib 12 | 13 | parser = argparse.ArgumentParser() 14 | 15 | parser.add_argument('--testexe', help="binary to test", required=False) 16 | parser.add_argument('--goldendir', help="golden results directory", required=True) 17 | parser.add_argument('--working', help="working directory", required=False, default="") 18 | parser.add_argument('--output', help="output filename to compare with goldenresult", required=True) 19 | parser.add_argument('--args', help="list of input arguments", nargs='+', required=False) 20 | args = parser.parse_args() 21 | 22 | output_file = os.path.abspath(os.path.join(args.working, args.output)) 23 | compare_file = os.path.abspath(os.path.join(args.goldendir, args.output)) 24 | 25 | if (args.working): 26 | os.chdir(args.working) 27 | if args.testexe: 28 | arguments = [args.testexe,] 29 | if args.args: 30 | arguments.extend(args.args) 31 | try: 32 | with open(output_file, 'w') as ofile: 33 | process = subprocess.run( 34 | arguments, 35 | stdout = ofile, 36 | stderr = subprocess.STDOUT 37 | ) 38 | if process.returncode != 0: 39 | raise RuntimeError("%s returned error code %d" % (args.testexe, process.returncode)) 40 | except Exception as ex: 41 | with open(output_file, 'r') as errorfile: 42 | print(errorfile.read()) 43 | raise 44 | 45 | f1stat = os.stat(output_file) 46 | f2stat = os.stat(compare_file) 47 | 48 | with open(output_file) as f1: 49 | with open(compare_file) as f2: 50 | while (True): 51 | a1 = next(f1, "SENTINELlkj") 52 | a2 = next(f2, "SENTINELlkj") 53 | if a1 != a2: 54 | raise RuntimeError("%s differs from %s" % (output_file, compare_file)) 55 | elif a1 == "SENTINELlkj": 56 | break 57 | 58 | -------------------------------------------------------------------------------- /testing/symdiff1.tcl: -------------------------------------------------------------------------------- 1 | package require symdifftcl 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | proc callSymdiff {arg} { 6 | puts [format "\"%s\"\n\"%s\"\n\"%s\"\n\n" $arg [symdiff "$arg"] [symdiff "diff($arg,x)"]] 7 | } 8 | 9 | callSymdiff "exp(0)" 10 | callSymdiff "simplify(exp(0))" 11 | callSymdiff "exp(1)" 12 | callSymdiff "exp(2)" 13 | 14 | callSymdiff "pow(x,0)" 15 | callSymdiff "simplify(pow(x,0))" 16 | callSymdiff "pow(x,1)" 17 | callSymdiff "simplify(pow(x,1))" 18 | callSymdiff "pow(x*y,1)" 19 | callSymdiff "pow(x*y,2)" 20 | callSymdiff "pow(x,2)" 21 | callSymdiff "pow(2,x)" 22 | callSymdiff "pow(2,x*y)" 23 | callSymdiff "pow(2,3)" 24 | callSymdiff "pow(0,x)" 25 | callSymdiff "simplify(pow(0,x))" 26 | callSymdiff "pow(1,x)" 27 | callSymdiff "simplify(pow(1,x))" 28 | 29 | callSymdiff "exp(x)" 30 | callSymdiff "exp(x*y)" 31 | callSymdiff "log(x)" 32 | callSymdiff "log(x*y)" 33 | callSymdiff "log(1)" 34 | callSymdiff "x*y" 35 | callSymdiff "x" 36 | callSymdiff "0*x" 37 | callSymdiff "0*x*y" 38 | callSymdiff "x*y*z" 39 | callSymdiff "0+x+y" 40 | callSymdiff "pow(x*y,z)" 41 | callSymdiff "pow(y,x*z)" 42 | callSymdiff "pow(x*y,x*z)" 43 | -------------------------------------------------------------------------------- /testing/symdiff2.tcl: -------------------------------------------------------------------------------- 1 | package require symdifftcl 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff "declare_model(x)" 6 | puts [symdiff "diff(x,y)"] 7 | puts [symdiff "diff(x,x)"] 8 | puts [symdiff "define_model(z, 2 * a + b *c)"] 9 | puts [symdiff "diff(z, x)"] 10 | puts [symdiff "diff(z, a)"] 11 | puts [symdiff "model_value(z)"] 12 | puts [symdiff "model_value(z__x)"] 13 | puts [symdiff "model_value(z__a)"] 14 | puts [symdiff "define_model(qq, 2 * a)"] 15 | puts [symdiff "model_value(qq)"] 16 | puts [symdiff "define_model(qq, model_value(qq)+ b)"] 17 | puts [symdiff "model_value(qq)"] 18 | # this is a recursive definition and should be caught if ever printed out 19 | puts [symdiff "define_model(qq, model_value(qq)+ qq)"] 20 | puts [symdiff "model_value(qq)"] 21 | puts [symdiff "define_model(qq, simplify(model_value(qq)))"] 22 | puts [symdiff "model_value(qq)"] 23 | 24 | -------------------------------------------------------------------------------- /testing/symdiff3.tcl: -------------------------------------------------------------------------------- 1 | package require symdifftcl 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff "define_model(a, b + d)" 6 | symdiff "define_model(c, b + d)" 7 | puts "\n\nBEFORE\n\n" 8 | foreach {i} [model_list] { 9 | puts [format "%s, %s" $i [symdiff "model_value($i)"] ] 10 | } 11 | 12 | symdiff "define_model(x, a + c)" 13 | 14 | subexpression 15 | puts "\n\nAFTER\n\n" 16 | foreach {i} [model_list] { 17 | puts [format "%s, %s" $i [symdiff "model_value($i)"] ] 18 | } 19 | 20 | puts "\n\nORDERED for a c\n\n" 21 | foreach {i} [ordered_list a c] { 22 | puts [format "%s, %s" $i [symdiff "model_value($i)"] ] 23 | } 24 | 25 | puts "\n\nORDERED for x\n\n" 26 | foreach {i} [ordered_list x] { 27 | puts [format "%s, %s" $i [symdiff "model_value($i)"] ] 28 | } 29 | 30 | puts "\n\nORDERED for a\n\n" 31 | foreach {i} [ordered_list a] { 32 | puts [format "%s, %s" $i [symdiff "model_value($i)"] ] 33 | } 34 | -------------------------------------------------------------------------------- /testing/symdiff4.tcl: -------------------------------------------------------------------------------- 1 | package require symdifftcl 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff "define_model(a,b + c)" 6 | symdiff "diff(a,b)" 7 | puts [symdiff "model_value(a__b)"] 8 | symdiff "define_model(a,c)" 9 | symdiff "diff(a,b)" 10 | puts [symdiff "model_value(a__b)"] 11 | 12 | -------------------------------------------------------------------------------- /testing/table.tcl: -------------------------------------------------------------------------------- 1 | package require symdifftcl 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff "declare_model(x)" 6 | set i 0 7 | set x [symdiff_table "a*x + b*c"] 8 | foreach j $x { 9 | puts "$i $j" 10 | incr i 11 | } 12 | 13 | -------------------------------------------------------------------------------- /testing/units.tcl: -------------------------------------------------------------------------------- 1 | package require symdifftcl 2 | # Any copyright is dedicated to the Public Domain. 3 | # http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | symdiff {define_model(E, m * c^2)} 6 | symdiff {$a = model_value(E); 7 | $a = subst($a, m, Kg); 8 | $a = subst($a, c, m/s); 9 | $a = simplify($_);} 10 | puts [symdiff {$a}] 11 | --------------------------------------------------------------------------------